From 1995260c9b4a48d8d4da77fbc31f23f69a9ace34 Mon Sep 17 00:00:00 2001 From: Sokhibjon Orzikulov Date: Mon, 20 Nov 2023 07:04:09 +0500 Subject: [PATCH] uploading latest changes from @ismoilovdevml --- .github/CODEOWNERS | 6 +- .github/workflows/build.yml | 96 +- .github/workflows/install-mdbook/action.yml | 12 +- .github/workflows/publish.yml | 9 +- .gitignore | 10 + Cargo.lock | 946 +- Cargo.toml | 5 +- README.md | 29 +- STYLE.md | 89 + TRANSLATIONS.md | 33 +- book.toml | 21 + i18n-helpers/Cargo.toml | 15 - i18n-helpers/src/bin/mdbook-gettext.rs | 248 - i18n-helpers/src/bin/mdbook-xgettext.rs | 128 - i18n-helpers/src/lib.rs | 123 - mdbook-exerciser/Cargo.toml | 15 + mdbook-exerciser/README.md | 26 + mdbook-exerciser/src/lib.rs | 73 + mdbook-exerciser/src/main.rs | 70 + po/da.po | 19927 +++++++++----- po/de.po | 17460 ++++++++---- po/el.po | 22020 ++++++++++++++++ po/es.po | 14068 ++++++++++ po/fr.po | 17984 +++++++++++++ po/it.po | 20304 ++++++++++++++ po/ko.po | 7154 +++-- po/pt-BR.po | 4022 +-- po/uz.po | 34 +- rustfmt.toml | 1 + src/SUMMARY.md | 191 +- src/android.md | 6 +- src/async.md | 25 + src/async/async-await.md | 48 + src/async/channels.md | 49 + src/async/control-flow.md | 7 + src/async/control-flow/join.md | 50 + src/async/control-flow/select.md | 77 + src/async/futures.md | 45 + src/async/pitfalls.md | 7 + src/async/pitfalls/async-traits.md | 63 + src/async/pitfalls/blocking-executor.md | 50 + src/async/pitfalls/pin.md | 112 + src/async/runtimes.md | 29 + src/async/runtimes/tokio.md | 49 + src/async/tasks.md | 64 + src/bare-metal.md | 48 + .../alloc-example/.cargo/config.toml | 2 + src/bare-metal/alloc-example/Cargo.lock | 57 + src/bare-metal/alloc-example/Cargo.toml | 17 + src/bare-metal/alloc-example/src/main.rs | 43 + src/bare-metal/alloc.md | 22 + src/bare-metal/android.md | 44 + src/bare-metal/android/vmbase.md | 27 + src/bare-metal/aps.md | 15 + src/bare-metal/aps/better-uart.md | 30 + src/bare-metal/aps/better-uart/bitflags.md | 14 + src/bare-metal/aps/better-uart/driver.md | 14 + src/bare-metal/aps/better-uart/registers.md | 16 + src/bare-metal/aps/better-uart/using.md | 16 + .../aps/examples/.cargo/config.toml | 3 + src/bare-metal/aps/examples/Cargo.lock | 78 + src/bare-metal/aps/examples/Cargo.toml | 32 + src/bare-metal/aps/examples/Makefile | 50 + src/bare-metal/aps/examples/build.rs | 29 + src/bare-metal/aps/examples/entry.S | 142 + src/bare-metal/aps/examples/exceptions.S | 178 + src/bare-metal/aps/examples/idmap.S | 42 + src/bare-metal/aps/examples/image.ld | 104 + src/bare-metal/aps/examples/src/exceptions.rs | 65 + src/bare-metal/aps/examples/src/logger.rs | 54 + .../aps/examples/src/main_improved.rs | 63 + .../aps/examples/src/main_logger.rs | 52 + .../aps/examples/src/main_minimal.rs | 49 + src/bare-metal/aps/examples/src/main_psci.rs | 51 + src/bare-metal/aps/examples/src/pl011.rs | 166 + .../aps/examples/src/pl011_minimal.rs | 78 + src/bare-metal/aps/inline-assembly.md | 31 + src/bare-metal/aps/logging.md | 16 + src/bare-metal/aps/logging/using.md | 14 + src/bare-metal/aps/mmio.md | 17 + src/bare-metal/aps/other-projects.md | 11 + src/bare-metal/aps/uart.md | 24 + src/bare-metal/aps/uart/traits.md | 14 + src/bare-metal/microcontrollers.md | 17 + .../microcontrollers/board-support.md | 23 + src/bare-metal/microcontrollers/debugging.md | 38 + .../microcontrollers/embedded-hal.md | 23 + .../examples/.cargo/config.toml | 5 + .../microcontrollers/examples/Cargo.lock | 366 + .../microcontrollers/examples/Cargo.toml | 33 + .../microcontrollers/examples/Embed.toml | 8 + .../examples/src/bin/board_support.rs | 33 + .../microcontrollers/examples/src/bin/hal.rs | 42 + .../examples/src/bin/interrupts/mod.rs | 17 + .../examples/src/bin/minimal.rs | 28 + .../microcontrollers/examples/src/bin/mmio.rs | 68 + .../microcontrollers/examples/src/bin/pac.rs | 52 + .../examples/src/bin/typestate.rs | 52 + src/bare-metal/microcontrollers/hals.md | 23 + src/bare-metal/microcontrollers/mmio.md | 20 + .../microcontrollers/other-projects.md | 26 + src/bare-metal/microcontrollers/pacs.md | 29 + src/bare-metal/microcontrollers/probe-rs.md | 29 + src/bare-metal/microcontrollers/type-state.md | 20 + src/bare-metal/minimal.md | 26 + src/bare-metal/no_std.md | 65 + src/bare-metal/useful-crates.md | 3 + .../useful-crates/aarch64-paging.md | 36 + .../allocator-example/Cargo.toml | 8 + .../allocator-example/src/main.rs | 28 + .../useful-crates/buddy_system_allocator.md | 23 + src/bare-metal/useful-crates/spin.md | 33 + src/bare-metal/useful-crates/tinyvec.md | 28 + .../useful-crates/zerocopy-example/Cargo.toml | 8 + .../zerocopy-example/src/main.rs | 46 + src/bare-metal/useful-crates/zerocopy.md | 25 + src/basic-syntax/functions-interlude.md | 2 +- src/basic-syntax/functions.md | 41 +- src/basic-syntax/methods.md | 19 +- src/basic-syntax/rustdoc.md | 33 + src/basic-syntax/scalar-types.md | 29 +- src/concurrency.md | 2 +- src/concurrency/send-sync/send.md | 7 + src/concurrency/shared_state/arc.md | 4 +- src/concurrency/shared_state/example.md | 10 +- src/control-flow/break-continue.md | 9 +- src/control-flow/for-expressions.md | 5 +- src/control-flow/if-expressions.md | 8 +- src/control-flow/if-let-expressions.md | 19 +- src/control-flow/loop-expressions.md | 9 +- src/control-flow/match-expressions.md | 5 +- src/control-flow/while-expressions.md | 5 +- src/control-flow/while-let-expressions.md | 7 +- src/enums/sizes.md | 156 +- .../converting-error-types-example.md | 4 +- src/error-handling/error-contexts.md | 2 +- src/error-handling/panic-unwind.md | 2 +- src/error-handling/result.md | 2 +- src/error-handling/try-operator.md | 6 +- src/exercises/Cargo.toml | 9 +- .../afternoon.md => android/morning.md} | 4 +- src/exercises/bare-metal/afternoon.md | 11 + src/exercises/bare-metal/compass.md | 79 + .../bare-metal/compass/.cargo/config.toml | 5 + src/exercises/bare-metal/compass/Cargo.lock | 375 + src/exercises/bare-metal/compass/Cargo.toml | 14 + src/exercises/bare-metal/compass/Embed.toml | 8 + src/exercises/bare-metal/compass/src/main.rs | 156 + src/exercises/bare-metal/morning.md | 11 + src/exercises/bare-metal/rtc.md | 130 + .../bare-metal/rtc/.cargo/config.toml | 3 + src/exercises/bare-metal/rtc/Cargo.lock | 118 + src/exercises/bare-metal/rtc/Cargo.toml | 18 + src/exercises/bare-metal/rtc/Makefile | 38 + src/exercises/bare-metal/rtc/build.rs | 29 + src/exercises/bare-metal/rtc/entry.S | 142 + src/exercises/bare-metal/rtc/exceptions.S | 178 + src/exercises/bare-metal/rtc/idmap.S | 42 + src/exercises/bare-metal/rtc/image.ld | 104 + .../bare-metal/rtc/src/exceptions.rs | 67 + src/exercises/bare-metal/rtc/src/logger.rs | 54 + src/exercises/bare-metal/rtc/src/main.rs | 137 + src/exercises/bare-metal/rtc/src/pl011.rs | 168 + src/exercises/bare-metal/rtc/src/pl031.rs | 119 + .../bare-metal/solutions-afternoon.md | 17 + src/exercises/bare-metal/solutions-morning.md | 9 + src/exercises/concurrency/afternoon.md | 17 + src/exercises/concurrency/chat-app.md | 109 + .../concurrency/chat-async/Cargo.toml | 10 + .../concurrency/chat-async/src/bin/client.rs | 52 + .../concurrency/chat-async/src/bin/server.rs | 80 + .../concurrency/dining-philosophers-async.md | 57 + .../concurrency/dining-philosophers-async.rs | 103 + .../dining-philosophers.md | 17 +- .../dining-philosophers.rs | 3 +- .../{day-4 => concurrency}/link-checker.md | 10 + .../{day-4 => concurrency}/link-checker.rs | 0 .../{day-4 => concurrency}/morning.md | 0 .../concurrency/solutions-afternoon.md | 26 + .../solutions-morning.md | 2 +- src/exercises/day-1/book-library.md | 9 +- src/exercises/day-1/book-library.rs | 64 +- src/exercises/day-2/luhn.rs | 3 +- src/exercises/day-3/safe-ffi-wrapper.md | 29 +- src/exercises/day-3/safe-ffi-wrapper.rs | 56 +- src/exercises/day-3/simple-gui.rs | 25 +- src/generics/data-types.md | 8 + src/generics/trait-objects.md | 86 - src/hello-world.md | 2 +- src/memory-management/stack.md | 26 +- src/modules/filesystem.md | 18 + src/modules/paths.md | 8 + src/ownership/borrowing.md | 2 +- src/pattern-matching/destructuring-arrays.md | 32 +- src/pattern-matching/destructuring-structs.md | 4 + src/running-the-course.md | 53 +- src/running-the-course/course-structure.md | 53 +- src/std/hashmap.md | 28 +- src/std/rc.md | 8 +- src/std/string.md | 4 +- src/structs/field-shorthand.md | 45 +- src/structs/tuple-structs.md | 4 +- src/testing/unit-tests.md | 2 +- src/testing/useful-crates.md | 9 + src/traits.md | 49 +- src/{generics => traits}/closures.md | 0 src/traits/default-methods.md | 32 + src/{generics => traits}/impl-trait.md | 10 +- src/traits/iterator.md | 7 +- src/{generics => traits}/trait-bounds.md | 0 src/traits/trait-objects.md | 83 + src/unsafe/raw-pointers.md | 9 +- src/welcome-day-4.md | 13 - src/welcome.md | 28 +- theme/index.hbs | 3 - 215 files changed, 112896 insertions(+), 19642 deletions(-) create mode 100644 STYLE.md delete mode 100644 i18n-helpers/Cargo.toml delete mode 100644 i18n-helpers/src/bin/mdbook-gettext.rs delete mode 100644 i18n-helpers/src/bin/mdbook-xgettext.rs delete mode 100644 i18n-helpers/src/lib.rs create mode 100644 mdbook-exerciser/Cargo.toml create mode 100644 mdbook-exerciser/README.md create mode 100644 mdbook-exerciser/src/lib.rs create mode 100644 mdbook-exerciser/src/main.rs create mode 100644 po/el.po create mode 100644 po/es.po create mode 100644 po/fr.po create mode 100644 po/it.po create mode 100644 src/async.md create mode 100644 src/async/async-await.md create mode 100644 src/async/channels.md create mode 100644 src/async/control-flow.md create mode 100644 src/async/control-flow/join.md create mode 100644 src/async/control-flow/select.md create mode 100644 src/async/futures.md create mode 100644 src/async/pitfalls.md create mode 100644 src/async/pitfalls/async-traits.md create mode 100644 src/async/pitfalls/blocking-executor.md create mode 100644 src/async/pitfalls/pin.md create mode 100644 src/async/runtimes.md create mode 100644 src/async/runtimes/tokio.md create mode 100644 src/async/tasks.md create mode 100644 src/bare-metal.md create mode 100644 src/bare-metal/alloc-example/.cargo/config.toml create mode 100644 src/bare-metal/alloc-example/Cargo.lock create mode 100644 src/bare-metal/alloc-example/Cargo.toml create mode 100644 src/bare-metal/alloc-example/src/main.rs create mode 100644 src/bare-metal/alloc.md create mode 100644 src/bare-metal/android.md create mode 100644 src/bare-metal/android/vmbase.md create mode 100644 src/bare-metal/aps.md create mode 100644 src/bare-metal/aps/better-uart.md create mode 100644 src/bare-metal/aps/better-uart/bitflags.md create mode 100644 src/bare-metal/aps/better-uart/driver.md create mode 100644 src/bare-metal/aps/better-uart/registers.md create mode 100644 src/bare-metal/aps/better-uart/using.md create mode 100644 src/bare-metal/aps/examples/.cargo/config.toml create mode 100644 src/bare-metal/aps/examples/Cargo.lock create mode 100644 src/bare-metal/aps/examples/Cargo.toml create mode 100644 src/bare-metal/aps/examples/Makefile create mode 100644 src/bare-metal/aps/examples/build.rs create mode 100644 src/bare-metal/aps/examples/entry.S create mode 100644 src/bare-metal/aps/examples/exceptions.S create mode 100644 src/bare-metal/aps/examples/idmap.S create mode 100644 src/bare-metal/aps/examples/image.ld create mode 100644 src/bare-metal/aps/examples/src/exceptions.rs create mode 100644 src/bare-metal/aps/examples/src/logger.rs create mode 100644 src/bare-metal/aps/examples/src/main_improved.rs create mode 100644 src/bare-metal/aps/examples/src/main_logger.rs create mode 100644 src/bare-metal/aps/examples/src/main_minimal.rs create mode 100644 src/bare-metal/aps/examples/src/main_psci.rs create mode 100644 src/bare-metal/aps/examples/src/pl011.rs create mode 100644 src/bare-metal/aps/examples/src/pl011_minimal.rs create mode 100644 src/bare-metal/aps/inline-assembly.md create mode 100644 src/bare-metal/aps/logging.md create mode 100644 src/bare-metal/aps/logging/using.md create mode 100644 src/bare-metal/aps/mmio.md create mode 100644 src/bare-metal/aps/other-projects.md create mode 100644 src/bare-metal/aps/uart.md create mode 100644 src/bare-metal/aps/uart/traits.md create mode 100644 src/bare-metal/microcontrollers.md create mode 100644 src/bare-metal/microcontrollers/board-support.md create mode 100644 src/bare-metal/microcontrollers/debugging.md create mode 100644 src/bare-metal/microcontrollers/embedded-hal.md create mode 100644 src/bare-metal/microcontrollers/examples/.cargo/config.toml create mode 100644 src/bare-metal/microcontrollers/examples/Cargo.lock create mode 100644 src/bare-metal/microcontrollers/examples/Cargo.toml create mode 100644 src/bare-metal/microcontrollers/examples/Embed.toml create mode 100644 src/bare-metal/microcontrollers/examples/src/bin/board_support.rs create mode 100644 src/bare-metal/microcontrollers/examples/src/bin/hal.rs create mode 100644 src/bare-metal/microcontrollers/examples/src/bin/interrupts/mod.rs create mode 100644 src/bare-metal/microcontrollers/examples/src/bin/minimal.rs create mode 100644 src/bare-metal/microcontrollers/examples/src/bin/mmio.rs create mode 100644 src/bare-metal/microcontrollers/examples/src/bin/pac.rs create mode 100644 src/bare-metal/microcontrollers/examples/src/bin/typestate.rs create mode 100644 src/bare-metal/microcontrollers/hals.md create mode 100644 src/bare-metal/microcontrollers/mmio.md create mode 100644 src/bare-metal/microcontrollers/other-projects.md create mode 100644 src/bare-metal/microcontrollers/pacs.md create mode 100644 src/bare-metal/microcontrollers/probe-rs.md create mode 100644 src/bare-metal/microcontrollers/type-state.md create mode 100644 src/bare-metal/minimal.md create mode 100644 src/bare-metal/no_std.md create mode 100644 src/bare-metal/useful-crates.md create mode 100644 src/bare-metal/useful-crates/aarch64-paging.md create mode 100644 src/bare-metal/useful-crates/allocator-example/Cargo.toml create mode 100644 src/bare-metal/useful-crates/allocator-example/src/main.rs create mode 100644 src/bare-metal/useful-crates/buddy_system_allocator.md create mode 100644 src/bare-metal/useful-crates/spin.md create mode 100644 src/bare-metal/useful-crates/tinyvec.md create mode 100644 src/bare-metal/useful-crates/zerocopy-example/Cargo.toml create mode 100644 src/bare-metal/useful-crates/zerocopy-example/src/main.rs create mode 100644 src/bare-metal/useful-crates/zerocopy.md create mode 100644 src/basic-syntax/rustdoc.md rename src/exercises/{day-4/afternoon.md => android/morning.md} (69%) create mode 100644 src/exercises/bare-metal/afternoon.md create mode 100644 src/exercises/bare-metal/compass.md create mode 100644 src/exercises/bare-metal/compass/.cargo/config.toml create mode 100644 src/exercises/bare-metal/compass/Cargo.lock create mode 100644 src/exercises/bare-metal/compass/Cargo.toml create mode 100644 src/exercises/bare-metal/compass/Embed.toml create mode 100644 src/exercises/bare-metal/compass/src/main.rs create mode 100644 src/exercises/bare-metal/morning.md create mode 100644 src/exercises/bare-metal/rtc.md create mode 100644 src/exercises/bare-metal/rtc/.cargo/config.toml create mode 100644 src/exercises/bare-metal/rtc/Cargo.lock create mode 100644 src/exercises/bare-metal/rtc/Cargo.toml create mode 100644 src/exercises/bare-metal/rtc/Makefile create mode 100644 src/exercises/bare-metal/rtc/build.rs create mode 100644 src/exercises/bare-metal/rtc/entry.S create mode 100644 src/exercises/bare-metal/rtc/exceptions.S create mode 100644 src/exercises/bare-metal/rtc/idmap.S create mode 100644 src/exercises/bare-metal/rtc/image.ld create mode 100644 src/exercises/bare-metal/rtc/src/exceptions.rs create mode 100644 src/exercises/bare-metal/rtc/src/logger.rs create mode 100644 src/exercises/bare-metal/rtc/src/main.rs create mode 100644 src/exercises/bare-metal/rtc/src/pl011.rs create mode 100644 src/exercises/bare-metal/rtc/src/pl031.rs create mode 100644 src/exercises/bare-metal/solutions-afternoon.md create mode 100644 src/exercises/bare-metal/solutions-morning.md create mode 100644 src/exercises/concurrency/afternoon.md create mode 100644 src/exercises/concurrency/chat-app.md create mode 100644 src/exercises/concurrency/chat-async/Cargo.toml create mode 100644 src/exercises/concurrency/chat-async/src/bin/client.rs create mode 100644 src/exercises/concurrency/chat-async/src/bin/server.rs create mode 100644 src/exercises/concurrency/dining-philosophers-async.md create mode 100644 src/exercises/concurrency/dining-philosophers-async.rs rename src/exercises/{day-4 => concurrency}/dining-philosophers.md (78%) rename src/exercises/{day-4 => concurrency}/dining-philosophers.rs (98%) rename src/exercises/{day-4 => concurrency}/link-checker.md (94%) rename src/exercises/{day-4 => concurrency}/link-checker.rs (100%) rename src/exercises/{day-4 => concurrency}/morning.md (100%) create mode 100644 src/exercises/concurrency/solutions-afternoon.md rename src/exercises/{day-4 => concurrency}/solutions-morning.md (79%) delete mode 100644 src/generics/trait-objects.md create mode 100644 src/testing/useful-crates.md rename src/{generics => traits}/closures.md (100%) rename src/{generics => traits}/impl-trait.md (76%) rename src/{generics => traits}/trait-bounds.md (100%) create mode 100644 src/traits/trait-objects.md delete mode 100644 src/welcome-day-4.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9920724..8b451a3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,5 +1,9 @@ # Translations -po/da.po @mgeisler +po/da.po @mgeisler @voss @thedataking po/de.po @ronaldfw @fechu +po/el.po @Mandragorian +po/es.po @deavid +po/fr.po @sakex @lb034582341 +po/it.po @detro @nicomazz @bznein po/ko.po @jiyongp @jooyunghan po/pt-BR.po @rastringer @hugojacob diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 660fbf9..5e9964a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,20 +10,19 @@ env: CARGO_TERM_COLOR: always jobs: - mdbook: + format: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - - name: Setup Rust cache - uses: ./.github/workflows/setup-rust-cache - - - name: Install mdbook - uses: ./.github/workflows/install-mdbook + - name: Install nightly rustfmt + run: | + rustup default nightly + rustup component add rustfmt - - name: Test code snippets - run: mdbook test + - name: Check Rust formatting + run: cargo fmt --all -- --check cargo: runs-on: ubuntu-latest @@ -40,8 +39,21 @@ jobs: - name: Test Rust code run: cargo test - i18n-helpers: + bare-metal: runs-on: ubuntu-latest + strategy: + matrix: + include: + - directory: src/bare-metal/alloc-example + target: aarch64-unknown-none + - directory: src/bare-metal/aps/examples + target: aarch64-unknown-none + - directory: src/bare-metal/microcontrollers/examples + target: thumbv7em-none-eabihf + - directory: src/exercises/bare-metal/compass + target: thumbv7em-none-eabihf + - directory: src/exercises/bare-metal/rtc + target: aarch64-unknown-none steps: - name: Checkout uses: actions/checkout@v3 @@ -49,59 +61,41 @@ jobs: - name: Setup Rust cache uses: ./.github/workflows/setup-rust-cache - - name: Install Gettext - run: sudo apt install gettext - - - name: Install mdbook - uses: ./.github/workflows/install-mdbook - - - name: Generate po/messages.pot - run: mdbook build -d po - env: - MDBOOK_OUTPUT: '{"xgettext": {"pot-file": "messages.pot"}}' - - - name: Test messages.pot - run: msgfmt --statistics -o /dev/null po/messages.pot - - - name: Expand includes without translation - run: mdbook build -d expanded - env: - MDBOOK_OUTPUT: '{"markdown": {}}' + - name: Install dependencies + run: sudo apt update && sudo apt install gcc-aarch64-linux-gnu - - name: Expand includes with no-op translation - run: mdbook build -d no-op - env: - MDBOOK_OUTPUT: '{"markdown": {}}' - MDBOOK_PREPROCESSOR__GETTEXT__PO_FILE: po/messages.pot + - name: Install toolchain + run: rustup target add ${{ matrix.target }} - - name: Compare no translation to no-op translation - run: diff --color=always --unified --recursive expanded no-op + - name: Build Rust code + working-directory: ${{ matrix.directory }} + run: cargo build - find-translations: + find-languages: runs-on: ubuntu-latest outputs: - languages: ${{ steps.find-translations.outputs.languages }} + languages: ${{ steps.find-languages.outputs.languages }} steps: - name: Checkout uses: actions/checkout@v3 - - name: Find translations - id: find-translations + - name: Find languages + id: find-languages shell: python run: | import os, json, pathlib - languages = [p.stem for p in pathlib.Path("po").iterdir() if p.suffix == ".po"] + languages = ["en"] + [p.stem for p in pathlib.Path("po").iterdir() if p.suffix == ".po"] github_output = open(os.environ["GITHUB_OUTPUT"], "a") github_output.write("languages=") json.dump(sorted(languages), github_output) - translations: + build: runs-on: ubuntu-latest needs: - - find-translations + - find-languages strategy: matrix: - language: ${{ fromJSON(needs.find-translations.outputs.languages) }} + language: ${{ fromJSON(needs.find-languages.outputs.languages) }} env: MDBOOK_BOOK__LANGUAGE: ${{ matrix.language }} steps: @@ -112,22 +106,34 @@ jobs: uses: ./.github/workflows/setup-rust-cache - name: Install Gettext + if: matrix.language != 'en' run: sudo apt install gettext - name: Install mdbook uses: ./.github/workflows/install-mdbook - name: Test ${{ matrix.language }} translation + if: matrix.language != 'en' run: msgfmt --statistics -o /dev/null po/${{ matrix.language }}.po - - name: Build course with ${{ matrix.language }} translation + - name: Build course run: mdbook build - - name: Upload ${{ matrix.language }} translation + - name: Zip exercise templates + run: zip --recurse-paths ../html/comprehensive-rust-exercises.zip comprehensive-rust-exercises/ + working-directory: book/exerciser + + - name: Prepare book for upload + run: | + mv book/html book/comprehensive-rust-${{ matrix.language }} + rm -r book/exerciser + + # Upload the book now to retain it in case mdbook test fails. + - name: Upload book uses: actions/upload-artifact@v3 with: name: comprehensive-rust-${{ matrix.language }} path: book/ - - name: Test code snippets with ${{ matrix.language }} translation + - name: Test code snippets run: mdbook test diff --git a/.github/workflows/install-mdbook/action.yml b/.github/workflows/install-mdbook/action.yml index 7723786..8fb31f6 100644 --- a/.github/workflows/install-mdbook/action.yml +++ b/.github/workflows/install-mdbook/action.yml @@ -1,6 +1,6 @@ name: Install mdbook and dependencies -description: Install the mdbook with the dependencies we need. +description: Install mdbook with the dependencies we need. runs: using: composite @@ -8,13 +8,17 @@ runs: # The --locked flag is important for reproducible builds. It also # avoids breakage due to skews between mdbook and mdbook-svgbob. - name: Install mdbook - run: cargo install mdbook --locked --version 0.4.25 + run: cargo install mdbook --locked --version 0.4.28 shell: bash - name: Install mdbook-svgbob run: cargo install mdbook-svgbob --locked --version 0.2.1 shell: bash - - name: Install i18n-helpers - run: cargo install --path i18n-helpers --locked + - name: Install mdbook-i18n-helpers + run: cargo install mdbook-i18n-helpers --locked --version 0.1.0 + shell: bash + + - name: Install exerciser + run: cargo install --path mdbook-exerciser --locked shell: bash diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6464840..b1f9bc9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -19,7 +19,7 @@ concurrency: env: CARGO_TERM_COLOR: always # Update the language picker in index.hbs to link new languages. - LANGUAGES: uz + LANGUAGES: da pt-BR ko jobs: publish: @@ -40,6 +40,9 @@ jobs: - name: Build course in English run: mdbook build -d book + - name: Zip exercise templates + run: cd book/exerciser && zip --recurse-paths ../html/comprehensive-rust-exercises.zip comprehensive-rust-exercises/ + - name: Build all translations run: | for po_lang in ${{ env.LANGUAGES }}; do @@ -47,6 +50,8 @@ jobs: MDBOOK_BOOK__LANGUAGE=$po_lang \ MDBOOK_OUTPUT__HTML__SITE_URL=/comprehensive-rust/$po_lang/ \ mdbook build -d book/$po_lang + (cd book/$po_lang/exerciser && zip --recurse-paths ../html/comprehensive-rust-exercises.zip comprehensive-rust-exercises/) + mv book/$po_lang/html book/html/$po_lang echo "::endgroup::" done @@ -56,7 +61,7 @@ jobs: - name: Upload artifact uses: actions/upload-pages-artifact@v1 with: - path: book + path: book/html - name: Deploy to GitHub Pages id: deployment diff --git a/.gitignore b/.gitignore index 7f818e3..aebb602 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,16 @@ +# Build artifacts /book/ target/ +*.bin + +# Translation artifacts po/messages.pot po/*.mo + +# macOS artifacts .DS_Store +# Jetbrains IDEs project files +.idea/ +.iml +.iws diff --git a/Cargo.lock b/Cargo.lock index 06d2897..966ff4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,13 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-example" +version = "0.1.0" +dependencies = [ + "buddy_system_allocator", +] + [[package]] name = "ammonia" version = "3.3.0" @@ -33,11 +40,62 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-wincon", + "concolor-override", + "concolor-query", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" + +[[package]] +name = "anstyle-parse" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-wincon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +dependencies = [ + "anstyle", + "windows-sys 0.45.0", +] + [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" + +[[package]] +name = "atty" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] [[package]] name = "autocfg" @@ -65,18 +123,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "bstr" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832" +checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" dependencies = [ "memchr", "once_cell", @@ -84,6 +142,15 @@ dependencies = [ "serde", ] +[[package]] +name = "buddy_system_allocator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f9365b6b0c9e1663ca4ca9440c00eda46bc85a3407070be8b5e0d8d1f29629" +dependencies = [ + "spin", +] + [[package]] name = "bumpalo" version = "3.12.0" @@ -114,53 +181,66 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chat-async" +version = "0.1.0" +dependencies = [ + "futures-util", + "http", + "tokio", + "tokio-websockets", +] + [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ "iana-time-zone", - "js-sys", "num-integer", "num-traits", - "time", - "wasm-bindgen", "winapi", ] [[package]] name = "clap" -version = "4.1.4" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" +checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" dependencies = [ + "anstream", + "anstyle", "bitflags", "clap_lex", - "is-terminal", "once_cell", "strsim", - "termcolor", "terminal_size", ] [[package]] name = "clap_complete" -version = "4.1.1" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6540eedc41f8a5a76cf3d8d458057dcdf817be4158a55b5f861f7a5483de75" +checksum = "01c22dcfb410883764b29953103d9ef7bb8fe21b3fa1158bc99986c2067294bd" dependencies = [ "clap", ] [[package]] name = "clap_lex" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" -dependencies = [ - "os_str_bytes", -] +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" [[package]] name = "codespan-reporting" @@ -178,9 +258,25 @@ version = "0.1.0" dependencies = [ "reqwest", "scraper", + "tempfile", "thiserror", ] +[[package]] +name = "concolor-override" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" + +[[package]] +name = "concolor-query" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" +dependencies = [ + "windows-sys 0.45.0", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -199,24 +295,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" dependencies = [ "libc", ] [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" dependencies = [ "cfg-if", "crossbeam-utils", @@ -224,9 +320,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", ] @@ -243,19 +339,19 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.27.2" +version = "0.29.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" dependencies = [ "cssparser-macros", "dtoa-short", - "itoa 0.4.8", + "itoa", "matches", - "phf 0.8.0", + "phf 0.10.1", "proc-macro2", "quote", "smallvec", - "syn", + "syn 1.0.109", ] [[package]] @@ -265,14 +361,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "cxx" -version = "1.0.88" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322296e2f2e5af4270b54df9e85a02ff037e271af20ba3e7fe1575515dc840b8" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" dependencies = [ "cc", "cxxbridge-flags", @@ -282,9 +378,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.88" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "017a1385b05d631e7875b1f151c9f012d37b53491e2a87f65bff5c262b2111d8" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" dependencies = [ "cc", "codespan-reporting", @@ -292,24 +388,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 2.0.13", ] [[package]] name = "cxxbridge-flags" -version = "1.0.88" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c26bbb078acf09bc1ecda02d4223f03bdd28bd4874edcb0379138efc499ce971" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" [[package]] name = "cxxbridge-macro" -version = "1.0.88" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357f40d1f06a24b60ae1fe122542c1fb05d28d32acb2aed064e84bc2ad1e252e" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] @@ -322,7 +418,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 1.0.109", ] [[package]] @@ -358,9 +454,9 @@ checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" [[package]] name = "elasticlunr-rs" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94d9c8df0fe6879ca12e7633fdfe467c503722cc981fc463703472d2b876448" +checksum = "41e83863a500656dfa214fee6682de9c5b9f03de6860fec531235ed2ae9f6571" dependencies = [ "regex", "serde", @@ -377,13 +473,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime 1.3.0", + "log", + "regex", + "termcolor", +] + [[package]] name = "env_logger" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ - "humantime", + "humantime 2.1.0", "is-terminal", "log", "regex", @@ -392,13 +501,13 @@ dependencies = [ [[package]] name = "errno" -version = "0.2.8" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" dependencies = [ "errno-dragonfly", "libc", - "winapi", + "windows-sys 0.45.0", ] [[package]] @@ -413,23 +522,23 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] name = "filetime" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if", "libc", - "redox_syscall", - "windows-sys", + "redox_syscall 0.2.16", + "windows-sys 0.45.0", ] [[package]] @@ -483,9 +592,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -493,44 +602,44 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-io" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] name = "futures-sink" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-core", "futures-io", @@ -554,9 +663,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -610,9 +719,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f" dependencies = [ "bytes", "fnv", @@ -672,6 +781,15 @@ dependencies = [ "http", ] +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.2.6" @@ -681,6 +799,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "html5ever" version = "0.26.0" @@ -692,18 +816,18 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", - "itoa 1.0.5", + "itoa", ] [[package]] @@ -729,6 +853,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + [[package]] name = "humantime" version = "2.1.0" @@ -737,9 +870,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.23" +version = "0.14.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" dependencies = [ "bytes", "futures-channel", @@ -750,7 +883,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.5", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -772,32 +905,18 @@ dependencies = [ "tokio-native-tls", ] -[[package]] -name = "i18n-helpers" -version = "0.1.0" -dependencies = [ - "anyhow", - "mdbook", - "once_cell", - "polib", - "regex", - "semver", - "serde_json", - "toml", -] - [[package]] name = "iana-time-zone" -version = "0.1.53" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "winapi", + "windows", ] [[package]] @@ -822,9 +941,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown", @@ -861,43 +980,38 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" +checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" dependencies = [ + "hermit-abi 0.3.1", "libc", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "ipnet" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" [[package]] name = "is-terminal" -version = "0.4.2" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "js-sys" @@ -936,9 +1050,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" [[package]] name = "link-cplusplus" @@ -951,9 +1065,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.1.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" [[package]] name = "lock_api" @@ -1008,9 +1122,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "mdbook" -version = "0.4.25" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ed28d5903dde77bd5182645078a37ee57014cac6ccb2d54e1d6496386648e4" +checksum = "764dcbfc2e5f868bc1b566eb179dff1a06458fd0cff846aae2579392dd3f01a0" dependencies = [ "ammonia", "anyhow", @@ -1018,7 +1132,7 @@ dependencies = [ "clap", "clap_complete", "elasticlunr-rs", - "env_logger", + "env_logger 0.10.0", "futures-util", "gitignore", "handlebars", @@ -1040,6 +1154,17 @@ dependencies = [ "warp", ] +[[package]] +name = "mdbook-exerciser" +version = "0.1.0" +dependencies = [ + "anyhow", + "log", + "mdbook", + "pretty_env_logger", + "pulldown-cmark", +] + [[package]] name = "memchr" version = "2.5.0" @@ -1048,9 +1173,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mime" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" @@ -1064,14 +1189,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1119,7 +1244,7 @@ dependencies = [ "libc", "mio", "walkdir", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1157,15 +1282,15 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "opener" @@ -1179,9 +1304,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.45" +version = "0.10.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" +checksum = "4d2f106ab837a24e03672c59b1239669a0596406ff657c3c0835b6b7f0f35a33" dependencies = [ "bitflags", "cfg-if", @@ -1194,13 +1319,13 @@ dependencies = [ [[package]] name = "openssl-macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] @@ -1211,23 +1336,16 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.80" +version = "0.9.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" +checksum = "3a20eace9dc2d82904039cb76dcf50fb1a0bba071cfd1629720b5d6f1ddba0fa" dependencies = [ - "autocfg", "cc", "libc", "pkg-config", "vcpkg", ] -[[package]] -name = "os_str_bytes" -version = "6.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1240,15 +1358,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1259,9 +1377,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f" +checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" dependencies = [ "thiserror", "ucd-trie", @@ -1269,9 +1387,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf026e2d0581559db66d837fe5242320f525d85c76283c61f4d51a1238d65ea" +checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" dependencies = [ "pest", "pest_generator", @@ -1279,22 +1397,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b27bd18aa01d91c8ed2b61ea23406a676b42d82609c6e2581fba42f0c15f17f" +checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] name = "pest_meta" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02b677c1859756359fc9983c2e56a0237f18624a3789528804406b7e915e5d" +checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" dependencies = [ "once_cell", "pest", @@ -1307,9 +1425,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", "phf_shared 0.8.0", - "proc-macro-hack", ] [[package]] @@ -1318,7 +1434,9 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ + "phf_macros", "phf_shared 0.10.0", + "proc-macro-hack", ] [[package]] @@ -1363,16 +1481,16 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", + "phf_generator 0.10.0", + "phf_shared 0.10.0", "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1410,7 +1528,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1431,12 +1549,6 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" -[[package]] -name = "polib" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17009af1604eef4137497a743594fbe8f37e52f004cb5d8f7cf5130dc74a5644" - [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1449,6 +1561,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "pretty_env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" +dependencies = [ + "env_logger 0.7.1", + "log", +] + [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -1457,9 +1579,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] @@ -1475,11 +1597,17 @@ dependencies = [ "unicase", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -1574,11 +1702,20 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" -version = "1.7.1" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", @@ -1593,24 +1730,15 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "reqwest" -version = "0.11.14" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" dependencies = [ "base64 0.21.0", "bytes", @@ -1654,32 +1782,32 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.7" +version = "0.37.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03" +checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "rustls-pemfile" -version = "0.2.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64 0.13.1", + "base64 0.21.0", ] [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "same-file" @@ -1696,7 +1824,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1713,9 +1841,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scraper" -version = "0.13.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5684396b456f3eb69ceeb34d1b5cb1a2f6acf7ca4452131efa3ba0ee2c2d0a70" +checksum = "4c557a9a03db98b0b298b497f0e16cd35a04a1fa9ee1130a6889c0714e0b73df" dependencies = [ "cssparser", "ego-tree", @@ -1729,9 +1857,9 @@ dependencies = [ [[package]] name = "scratch" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" [[package]] name = "security-framework" @@ -1758,57 +1886,55 @@ dependencies = [ [[package]] name = "selectors" -version = "0.22.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" dependencies = [ "bitflags", "cssparser", "derive_more", "fxhash", "log", - "matches", "phf 0.8.0", "phf_codegen 0.8.0", "precomputed-hash", "servo_arc", "smallvec", - "thin-slice", ] [[package]] name = "semver" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.152" +version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" dependencies = [ - "itoa 1.0.5", + "itoa", "ryu", "serde", ] @@ -1820,32 +1946,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.5", + "itoa", "ryu", "serde", ] [[package]] name = "servo_arc" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" dependencies = [ "nodrop", "stable_deref_trait", ] -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha1" version = "0.10.5" @@ -1857,6 +1972,12 @@ dependencies = [ "digest", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sha2" version = "0.10.6" @@ -1874,6 +1995,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "siphasher" version = "0.3.10" @@ -1882,9 +2012,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] @@ -1897,14 +2027,23 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", "winapi", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1913,9 +2052,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "string_cache" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", @@ -1945,9 +2084,20 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" dependencies = [ "proc-macro2", "quote", @@ -1956,16 +2106,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.3.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" dependencies = [ "cfg-if", "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.45.0", ] [[package]] @@ -1990,49 +2139,32 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" dependencies = [ "rustix", - "windows-sys", + "windows-sys 0.48.0", ] -[[package]] -name = "thin-slice" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" - [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "syn 2.0.13", ] [[package]] @@ -2046,44 +2178,45 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.25.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" dependencies = [ "autocfg", "bytes", "libc", - "memchr", "mio", "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] name = "tokio-native-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", @@ -2091,9 +2224,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" dependencies = [ "futures-core", "pin-project-lite", @@ -2102,9 +2235,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.17.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" +checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" dependencies = [ "futures-util", "log", @@ -2114,9 +2247,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", @@ -2126,6 +2259,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "tokio-websockets" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d1df20f31f428a351ec353699a82aad49360090e8f6320ac0dacf5def4f1573" +dependencies = [ + "base64 0.21.0", + "bytes", + "fastrand", + "futures-util", + "http", + "httparse", + "sha1_smol", + "tokio", + "tokio-util", +] + [[package]] name = "toml" version = "0.5.11" @@ -2176,9 +2326,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" -version = "0.17.3" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" +checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" dependencies = [ "base64 0.13.1", "byteorder", @@ -2187,7 +2337,7 @@ dependencies = [ "httparse", "log", "rand 0.8.5", - "sha-1", + "sha1", "thiserror", "url", "utf-8", @@ -2216,15 +2366,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.10" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" @@ -2258,6 +2408,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2272,12 +2428,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", - "winapi", "winapi-util", ] @@ -2293,9 +2448,9 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7b8be92646fc3d18b06147664ebc5f48d222686cb11a8755e561a735aacc6d" +checksum = "27e1a710288f0f91a98dd8a74f05b76a10768db245ce183edf64dc1afdc3016c" dependencies = [ "bytes", "futures-channel", @@ -2327,12 +2482,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2360,7 +2509,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -2394,7 +2543,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2446,62 +2595,161 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.0", +] + [[package]] name = "windows-sys" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winreg" @@ -2511,3 +2759,31 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] + +[[package]] +name = "zerocopy" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "zerocopy-example" +version = "0.1.0" +dependencies = [ + "zerocopy", +] diff --git a/Cargo.toml b/Cargo.toml index 272fcbd..7f1b06d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,8 @@ [workspace] members = [ - "i18n-helpers", + "mdbook-exerciser", "src/exercises", + "src/bare-metal/useful-crates/allocator-example", + "src/bare-metal/useful-crates/zerocopy-example", + "src/exercises/concurrency/chat-async", ] diff --git a/README.md b/README.md index 5eb4a9b..edcc7da 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,17 @@ # Comprehensive Rust 🦀 -This repository has the source code for Comprehensive Rust 🦀, a four day Rust +[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/google/comprehensive-rust/actions/workflows/build.yml?query=branch%3Amain) +[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/graphs/contributors) +[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/stargazers) + +This repository has the source code for Comprehensive Rust 🦀, a multi-day Rust course developed by the Android team. The course covers all aspects of Rust, -from basic syntax to generics and error handling. It also includes -Android-specific content on the last day. +from basic syntax to generics and error handling. It also includes deep dives on +[Android], [bare-metal], and [concurrency]. + +[Android]: https://google.github.io/comprehensive-rust/android.html +[bare-metal]: https://google.github.io/comprehensive-rust/bare-metal.html +[concurrency]: https://google.github.io/comprehensive-rust/concurrency.html Read the course at **https://google.github.io/comprehensive-rust/**. @@ -23,16 +31,18 @@ trigger when going through the code samples. We hope to improve on this via ## Building The course is built using a few tools: -- [mdBook](https://github.com/rust-lang/mdBook) -- [Svgbob plugin](https://github.com/boozook/mdbook-svgbob) -- [i18n-helpers](TRANSLATIONS.md#i18n-helpers) +- [mdbook](https://github.com/rust-lang/mdBook) +- [mdbook-svgbob](https://github.com/boozook/mdbook-svgbob) +- [mdbook-i18n-helpers](https://github.com/google/mdbook-i18n-helpers) +- [mdbook-exerciser](mdbook-exerciser/) -Install these tools with +Install these tools with: ```shell $ cargo install mdbook $ cargo install mdbook-svgbob -$ cargo install --path i18n-helpers +$ cargo install mdbook-i18n-helpers +$ cargo install --path mdbook-exerciser ``` Then run @@ -49,7 +59,8 @@ $ mdbook serve to start a web server with the course. You'll find the content on . You can use `mdbook build` to create a static version -of the course in the `book/` directory. +of the course in the `book/` directory. Note that you have to separately build +and zip exercises and add them to `book/html`. ## Contact diff --git a/STYLE.md b/STYLE.md new file mode 100644 index 0000000..c1f9eb5 --- /dev/null +++ b/STYLE.md @@ -0,0 +1,89 @@ +# Comprehensive Rust 🦀 Style Guide + +The course has been expanded and improved by tons of volunteers like you! Thank +you for that! To help ensure a consistent style throughout the course, we have +written down some guidelines for you to follow. + +## Course Slides + +Please take the following into account when updating the course material. + +### Vertical Space + +What looks like pages in a browser, are actually slides in a presentation. It is +important to keep this in mind when adding content: we only have limited +vertical space. Scrolling up and down should be avoided since it is very jarring +for people who attend the class. + +You can test the amount of space available using a simple tool. Uncomment these +lines in the `book.toml` file to have a red rectangle rendered on top of all +pages: + +```toml +[preprocessor.aspect-ratio-helper] +command = "./aspect-ratio-helper.py" +``` + +The rectangle has an aspect ratio similar to what you can see when you share +your screen on a 16:9 display or projector. + +Use the rectangle as a rough guide for how much you can fit on a single slide. +If you find yourself adding too much detail, move the details to the speaker +notes (see below). + +### Rust Code + +When showing Rust code, please use the same spacing as `rustfmt`: `3 * x` +instead of `3*x`. However, feel free to remove newlines when it can make the +code more compact and easier to understand, e.g., you can use + +```rust +struct Person { name: String } +``` + +if you like. + +## Speaker Notes + +We have extended `mdbook` with support for speaker notes: content added between +`
...
` tags is rendered in a special box that can be +collapsed or removed entirely from the slide. + +- The speaker notes should expand on the topic of the slide. Use them to provide + interesting background information for both the instructor and for students + who look at the material outside of a class. Remember that many more people + will read the course by themselves, so make the notes complete and useful even + when there is no Rust expert around. + +- Avoid using speaker notes as a script for the instructor. When teaching the + course, instructors will only have time to glance at the notes so it is not + useful to include full paragraphs which the instructor should read out loud. + +## Translations + +This section is about what you write in the translation. We describe [how to +create or update translations elsewhere](TRANSLATIONS.md). + +When translating the course, please take the following into account: + +- Do not translate the course name ("Comprehensive Rust 🦀"). If the name is not + easily understood in your language, please add the translated version after + the original name. + +- If the Rust Book has been [translated into your + language](https://doc.rust-lang.org/book/appendix-06-translation.html), please + use the same vocabulary. + +- Be careful to preserve the Markdown syntax of the original text. Pay special + attention to reference links in all their variations: `[foo][bar]`, `[foo][]` + (which means `[foo][foo]`), and `[foo]` (which also means `[foo][foo]`). + + As an example, if you translate `[foo]`, to `[FOO]`, you must also update the + corresponding link definition from `[foo]: https://example.net` to `[FOO]: + https://example.net`. If you forget to do this, you end up with a broken link + in the translation. + +- If you find mistakes or things that sound awkward in the original English + text, please submit PRs to fix them! Fixing typos in the translation is great, + but we want everybody to benefit from the fixes and that is why we need the + fix to be made in the English text too. diff --git a/TRANSLATIONS.md b/TRANSLATIONS.md index b2108d9..c192f29 100644 --- a/TRANSLATIONS.md +++ b/TRANSLATIONS.md @@ -21,7 +21,7 @@ GNU Gettext utilities below. [Gettext]: https://www.gnu.org/software/gettext/manual/html_node/index.html [ISO 639]: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes -## I18n Helpers +## Preparation We use two helpers for the translations: @@ -30,10 +30,10 @@ We use two helpers for the translations: * `mdbook-gettext`: This program translates the book into a target language. It is an mdbook preprocessor. -Install both helpers with the following command from the root of the course: +Install both helpers with: ```shell -$ cargo install --path i18n-helpers +$ cargo install mdbook-i18n-helpers ``` ## Creating and Updating Translations @@ -46,6 +46,9 @@ find mistakes, you need to update the original English text instead. The fixes to the English text will flow into the `.po` files the next time the translators update them. +> **Tip:** See our [style guide](STYLE.md) for some things to keep in mind when +> writing the translation. + ### Generating the PO Template To extract the original English text and generate a `messages.pot` file, you run @@ -70,6 +73,18 @@ $ msginit -i po/messages.pot -l xx -o po/xx.po You can also simply copy `po/messages.pot` to `po/xx.po`. Then update the file header (the first entry with `msgid ""`) to the correct language. +> **Tip:** You can use the +> [`cloud-translate`](https://github.com/mgeisler/cloud-translate) tool to +> quickly machine-translate a new translation. Install it with +> +> ```shell +> cargo install cloud-translate +> ``` +> +> Untranslated entries will be sent through GCP Cloud Translate. Some of the +> translations will be wrong after this, so you must inspect them by hand +> afterwards. + ### Updating an Existing Translation As the English text changes, translations gradually become outdated. To update @@ -90,10 +105,11 @@ remove the fuzzy marker. This will show you how to use the translations to generate localized HTML output. -Note: `mdbook` will use original untranslated entries for all entries marked as -"fuzzy" (visible as "Needs work" in Poedit). This is especially important when -using `cloud-translate` for initial translation as all entries will be marked -as "fuzzy". +> **Note:** `mdbook` will use original untranslated entries for all entries +> marked as "fuzzy" (visible as "Needs work" in Poedit). This is especially +> important when using +> [`cloud-translate`](https://github.com/mgeisler/cloud-translate) for initial +> translation as all entries will be marked as "fuzzy". ### Building a Translation @@ -115,3 +131,6 @@ it. You use the same command as with `mdbook build` above: ```shell $ MDBOOK_BOOK__LANGUAGE=xx mdbook serve -d book/xx ``` + +When you update the `po/xx.po` file, the translated book will automatically +reload. diff --git a/book.toml b/book.toml index b3e81ac..2716938 100644 --- a/book.toml +++ b/book.toml @@ -42,5 +42,26 @@ level = 0 editable = true [output.html.redirect] +# Redirects in the form of "old-path" = "new-path", where the new path +# is relative to the old path. +"async/concurrency/channels.html" = "../channels.html" +"exercises/day-4/afternoon.html" = "../android/morning.html" +"exercises/day-4/android.html" = "../android/morning.html" +"exercises/day-4/dining-philosophers.html" = "../concurrency/dining-philosophers.html" +"exercises/day-4/elevator.html" = "../concurrency/elevator.html" +"exercises/day-4/link-checker.html" = "../concurrency/link-checker.html" +"exercises/day-4/morning.html" = "../concurrency/morning.html" +"exercises/day-4/solutions-morning.html" = "../concurrency/solutions-morning.html" +"exercises/concurrency/elevator.html" = "chat-app.html" +"generics/closures.html" = "../traits/closures.html" +"generics/impl-trait.html" = "../traits/impl-trait.html" +"generics/trait-bounds.html" = "../traits/trait-bounds.html" +"generics/trait-objects.html" = "../traits/trait-objects.html" +"running-the-course/day-4.html" = "course-structure.html" "structure.html" = "running-the-course/course-structure.html" "unsafe/unsafe-functions.html" = "calling-unsafe-functions.html" +"welcome-bare-metal.html" = "bare-metal.html" +"welcome-day-4.html" = "concurrency.html" + +[output.exerciser] +output-directory = "comprehensive-rust-exercises" diff --git a/i18n-helpers/Cargo.toml b/i18n-helpers/Cargo.toml deleted file mode 100644 index 29118b2..0000000 --- a/i18n-helpers/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "i18n-helpers" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -anyhow = "1.0.68" -mdbook = "0.4.25" -once_cell = "1.17.0" -polib = "0.1.0" -regex = "1.7.0" -semver = "1.0.16" -serde_json = "1.0.91" -toml = "0.5.1" diff --git a/i18n-helpers/src/bin/mdbook-gettext.rs b/i18n-helpers/src/bin/mdbook-gettext.rs deleted file mode 100644 index 2325d67..0000000 --- a/i18n-helpers/src/bin/mdbook-gettext.rs +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! `gettext` for `mdbook` -//! -//! This program works like `gettext`, meaning it will translate -//! strings in your book. -//! -//! The translations come from GNU Gettext `xx.po` files. The PO file is -//! is found under `po` directory based on the `book.language`. -//! For example, `book.langauge` is set to `ko`, then `po/ko.po` is used. -//! You can set `preprocessor.gettext.po-dir` to specify where to find PO -//! files. If the PO file is not found, you'll get the untranslated book. -//! -//! See `TRANSLATIONS.md` in the repository root for more information. - -use anyhow::{anyhow, Context}; -use i18n_helpers::extract_paragraphs; -use mdbook::book::Book; -use mdbook::preprocess::{CmdPreprocessor, PreprocessorContext}; -use mdbook::BookItem; -use polib::catalog::Catalog; -use polib::po_file; -use semver::{Version, VersionReq}; -use std::io; -use std::process; -use toml::Value; - -fn translate(text: &str, catalog: &Catalog) -> String { - let mut output = String::with_capacity(text.len()); - let mut target_lineno = 1; - - for (lineno, paragraph) in extract_paragraphs(text) { - // Fill in blank lines between paragraphs. This is important - // for code blocks where blank lines are significant. - while target_lineno < lineno { - output.push('\n'); - target_lineno += 1; - } - // Subtract 1 because the paragraph is missing a final '\n' - // due to the splitting in `extract_paragraphs`. - target_lineno += paragraph.lines().count() - 1; - - let translated = catalog - .find_message(paragraph) - .filter(|msg| !msg.flags.contains("fuzzy")) - .and_then(|msg| msg.get_msgstr().ok()) - .filter(|msgstr| !msgstr.is_empty()) - .map(|msgstr| msgstr.as_str()) - .unwrap_or(paragraph); - output.push_str(translated); - } - - let suffix = &text[text.trim_end_matches('\n').len()..]; - output.push_str(suffix); - output -} - -fn translate_book(ctx: &PreprocessorContext, mut book: Book) -> anyhow::Result { - // no-op when the target language is not set - if ctx.config.book.language.is_none() { - return Ok(book); - } - - // the target language - let language = ctx.config.book.language.as_ref().unwrap(); - - // Find PO file for the target language - let cfg = ctx - .config - .get_preprocessor("gettext") - .ok_or_else(|| anyhow!("Could not read preprocessor.gettext configuration"))?; - let po_dir = cfg.get("po-dir").and_then(Value::as_str).unwrap_or("po"); - let path = ctx.root.join(po_dir).join(format!("{language}.po")); - - // no-op when PO file is missing - if !path.exists() { - return Ok(book); - } - - let catalog = po_file::parse(&path) - .map_err(|err| anyhow!("{err}")) - .with_context(|| format!("Could not parse {:?} as PO file", path))?; - book.for_each_mut(|item| match item { - BookItem::Chapter(ch) => { - ch.content = translate(&ch.content, &catalog); - ch.name = translate(&ch.name, &catalog); - } - BookItem::Separator => {} - BookItem::PartTitle(title) => { - *title = translate(title, &catalog); - } - }); - - Ok(book) -} - -fn preprocess() -> anyhow::Result<()> { - let (ctx, book) = CmdPreprocessor::parse_input(io::stdin())?; - let book_version = Version::parse(&ctx.mdbook_version)?; - let version_req = VersionReq::parse(mdbook::MDBOOK_VERSION)?; - if !version_req.matches(&book_version) { - eprintln!( - "Warning: The gettext preprocessor was built against \ - mdbook version {}, but we're being called from version {}", - mdbook::MDBOOK_VERSION, - ctx.mdbook_version - ); - } - - let translated_book = translate_book(&ctx, book)?; - serde_json::to_writer(io::stdout(), &translated_book)?; - - Ok(()) -} - -fn main() -> anyhow::Result<()> { - if std::env::args().len() == 3 { - assert_eq!(std::env::args().nth(1).as_deref(), Some("supports")); - if let Some("xgettext") = std::env::args().nth(2).as_deref() { - process::exit(1) - } else { - // Signal that we support all other renderers. - process::exit(0); - } - } - - preprocess() -} - -#[cfg(test)] -mod tests { - use super::*; - use polib::message::Message; - - fn create_catalog(translations: &[(&str, &str)]) -> Catalog { - let mut catalog = Catalog::new(); - for (msgid, msgstr) in translations { - let message = Message::new_singular("", "", "", "", msgid, msgstr); - catalog.add_message(message); - } - catalog - } - - #[test] - fn test_translate_single_line() { - let catalog = create_catalog(&[("foo bar", "FOO BAR")]); - assert_eq!(translate("foo bar", &catalog), "FOO BAR"); - } - - #[test] - fn test_translate_single_paragraph() { - let catalog = create_catalog(&[("foo bar", "FOO BAR")]); - assert_eq!(translate("foo bar\n", &catalog), "FOO BAR\n"); - } - - #[test] - fn test_translate_paragraph_with_leading_newlines() { - let catalog = create_catalog(&[("foo bar", "FOO BAR")]); - assert_eq!(translate("\n\n\nfoo bar\n", &catalog), "\n\n\nFOO BAR\n"); - } - - #[test] - fn test_translate_paragraph_with_trailing_newlines() { - let catalog = create_catalog(&[("foo bar", "FOO BAR")]); - assert_eq!(translate("foo bar\n\n\n", &catalog), "FOO BAR\n\n\n"); - } - - #[test] - fn test_translate_multiple_paragraphs() { - let catalog = create_catalog(&[("foo bar", "FOO BAR")]); - assert_eq!( - translate( - "first paragraph\n\ - \n\ - foo bar\n\ - \n\ - last paragraph\n", - &catalog - ), - "first paragraph\n\ - \n\ - FOO BAR\n\ - \n\ - last paragraph\n" - ); - } - - #[test] - fn test_translate_multiple_paragraphs_extra_newlines() { - // Notice how the translated paragraphs have more lines. - let catalog = create_catalog(&[ - ( - "first\n\ - paragraph", - "FIRST\n\ - TRANSLATED\n\ - PARAGRAPH", - ), - ( - "last\n\ - paragraph", - "LAST\n\ - TRANSLATED\n\ - PARAGRAPH", - ), - ]); - // Paragraph separation is kept intact while translating. - assert_eq!( - translate( - "\n\ - first\n\ - paragraph\n\ - \n\ - \n\ - \n\ - last\n\ - paragraph\n\ - \n\ - \n", - &catalog - ), - "\n\ - FIRST\n\ - TRANSLATED\n\ - PARAGRAPH\n\ - \n\ - \n\ - \n\ - LAST\n\ - TRANSLATED\n\ - PARAGRAPH\n\ - \n\ - \n" - ); - } -} diff --git a/i18n-helpers/src/bin/mdbook-xgettext.rs b/i18n-helpers/src/bin/mdbook-xgettext.rs deleted file mode 100644 index 630c8d9..0000000 --- a/i18n-helpers/src/bin/mdbook-xgettext.rs +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! `xgettext` for `mdbook` -//! -//! This program works like `xgettext`, meaning it will extract -//! translatable strings from your book. The strings are saved in a -//! GNU Gettext `messages.pot` file in your build directory (typically -//! `po/messages.pot`). -//! -//! See `TRANSLATIONS.md` in the repository root for more information. - -use anyhow::{anyhow, Context}; -use mdbook::renderer::RenderContext; -use mdbook::BookItem; -use polib::catalog::Catalog; -use polib::message::Message; -use std::fs; -use std::io; - -fn add_message(catalog: &mut Catalog, msgid: &str, source: &str) { - let sources = match catalog.find_message(msgid) { - Some(msg) => format!("{}\n{}", msg.source, source), - None => String::from(source), - }; - let message = Message::new_singular("", &sources, "", "", msgid, ""); - - // Carefully update the existing message or add a new one. It's an - // error to create a catalog with duplicate msgids. - match catalog.find_message_index(msgid) { - Some(&idx) => catalog.update_message_by_index(idx, message).unwrap(), - None => catalog.add_message(message), - } -} - -fn create_catalog(ctx: &RenderContext) -> anyhow::Result { - let mut catalog = Catalog::new(); - if let Some(title) = &ctx.config.book.title { - catalog.metadata.project_id_version = String::from(title); - } - if let Some(lang) = &ctx.config.book.language { - catalog.metadata.language = String::from(lang); - } - catalog.metadata.mime_version = String::from("1.0"); - catalog.metadata.content_type = String::from("text/plain; charset=UTF-8"); - catalog.metadata.content_transfer_encoding = String::from("8bit"); - - let summary_path = ctx.config.book.src.join("SUMMARY.md"); - let summary = std::fs::read_to_string(ctx.root.join(&summary_path))?; - - // First, add all chapter names and part titles from SUMMARY.md. - // The book items are in order of the summary, so we can assign - // correct line numbers for duplicate lines by tracking the index - // of our last search. - let mut last_idx = 0; - for item in ctx.book.iter() { - let line = match item { - BookItem::Chapter(chapter) => &chapter.name, - BookItem::PartTitle(title) => title, - BookItem::Separator => continue, - }; - - let idx = summary[last_idx..].find(line).ok_or_else(|| { - anyhow!( - "Could not find {line:?} in SUMMARY.md after line {} -- \ - please remove any formatting from SUMMARY.md", - summary[..last_idx].lines().count() - ) - })?; - last_idx += idx; - let lineno = summary[..last_idx].lines().count(); - let source = format!("{}:{}", summary_path.display(), lineno); - add_message(&mut catalog, line, &source); - } - - // Next, we add the chapter contents. - for item in ctx.book.iter() { - if let BookItem::Chapter(chapter) = item { - let path = match &chapter.path { - Some(path) => ctx.config.book.src.join(path), - None => continue, - }; - for (lineno, paragraph) in i18n_helpers::extract_paragraphs(&chapter.content) - { - let source = format!("{}:{}", path.display(), lineno); - add_message(&mut catalog, paragraph, &source); - } - } - } - - Ok(catalog) -} - -fn main() -> anyhow::Result<()> { - let ctx = RenderContext::from_json(&mut io::stdin()).context("Parsing stdin")?; - let cfg = ctx - .config - .get_renderer("xgettext") - .ok_or_else(|| anyhow!("Could not read output.xgettext configuration"))?; - let path = cfg - .get("pot-file") - .ok_or_else(|| anyhow!("Missing output.xgettext.pot-file config value"))? - .as_str() - .ok_or_else(|| anyhow!("Expected a string for output.xgettext.pot-file"))?; - fs::create_dir_all(&ctx.destination) - .with_context(|| format!("Could not create {}", ctx.destination.display()))?; - let output_path = ctx.destination.join(path); - if output_path.exists() { - fs::remove_file(&output_path) - .with_context(|| format!("Removing {}", output_path.display()))? - } - let catalog = create_catalog(&ctx).context("Extracting messages")?; - polib::po_file::write(&catalog, &output_path) - .with_context(|| format!("Writing messages to {}", output_path.display()))?; - - Ok(()) -} diff --git a/i18n-helpers/src/lib.rs b/i18n-helpers/src/lib.rs deleted file mode 100644 index fa3e6e6..0000000 --- a/i18n-helpers/src/lib.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use once_cell::sync::Lazy; -use regex::Regex; - -static PARAGRAPH_SEPARATOR: Lazy = Lazy::new(|| Regex::new(r"\n\n+").unwrap()); - -/// Extract paragraphs from text. -/// -/// Paragraphs are separated by at least two newlines. Returns an -/// iterator over line numbers (starting from 1) and paragraphs. -pub fn extract_paragraphs(text: &str) -> impl Iterator { - // TODO: This could be made more sophisticated by parsing the - // Markdown and stripping off the markup characters. - // - // As an example, a header like "## My heading" could become just - // "My heading" in the `.pot` file. Similarly, paragraphs could be - // unfolded and list items could be translated one-by-one. - - // Skip over leading empty lines. - let trimmed = text.trim_start_matches('\n'); - let mut matches = PARAGRAPH_SEPARATOR.find_iter(trimmed); - let mut lineno = 1 + text.len() - trimmed.len(); - let mut last = 0; - - std::iter::from_fn(move || match matches.next() { - Some(m) => { - let result = (lineno, &trimmed[last..m.start()]); - lineno += trimmed[last..m.end()].lines().count(); - last = m.end(); - Some(result) - } - None => { - if last < trimmed.len() { - let result = (lineno, trimmed[last..].trim_end_matches('\n')); - last = trimmed.len(); - Some(result) - } else { - None - } - } - }) -} - -#[cfg(test)] -mod tests { - use super::*; - - macro_rules! assert_iter_eq { - ($left_iter:expr, $right:expr) => { - assert_eq!($left_iter.collect::>(), $right) - }; - } - - #[test] - fn test_extract_paragraphs_empty() { - assert_iter_eq!(extract_paragraphs(""), vec![]); - } - - #[test] - fn test_extract_paragraphs_single_line() { - assert_iter_eq!( - extract_paragraphs("This is a paragraph."), - vec![(1, "This is a paragraph.")] - ); - } - - #[test] - fn test_extract_paragraphs_simple() { - assert_iter_eq!( - extract_paragraphs( - "This is\n\ - the first\n\ - paragraph.\n\ - \n\ - Second paragraph." - ), - vec![ - (1, "This is\nthe first\nparagraph."), - (5, "Second paragraph.") - ] - ); - } - - #[test] - fn test_extract_paragraphs_leading_newlines() { - assert_iter_eq!( - extract_paragraphs( - "\n\ - \n\ - \n\ - This is the\n\ - first paragraph." - ), - vec![(4, "This is the\nfirst paragraph.")] - ); - } - - #[test] - fn test_extract_paragraphs_trailing_newlines() { - assert_iter_eq!( - extract_paragraphs( - "This is\n\ - a paragraph.\n\ - \n\ - \n" - ), - vec![(1, "This is\na paragraph.")] - ); - } -} diff --git a/mdbook-exerciser/Cargo.toml b/mdbook-exerciser/Cargo.toml new file mode 100644 index 0000000..31195e9 --- /dev/null +++ b/mdbook-exerciser/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "mdbook-exerciser" +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" +authors = ["Andrew Walbran "] +description = "A tool for extracting starter code for exercises from Markdown files." +repository = "https://github.com/google/comprehensive-rust" + +[dependencies] +anyhow = "1.0.68" +log = "0.4.17" +mdbook = "0.4.25" +pretty_env_logger = "0.4.0" +pulldown-cmark = { version = "0.9.2", default-features = false } diff --git a/mdbook-exerciser/README.md b/mdbook-exerciser/README.md new file mode 100644 index 0000000..03db92b --- /dev/null +++ b/mdbook-exerciser/README.md @@ -0,0 +1,26 @@ +# exerciser + +This is an mdBook renderer to generate templates for exercises from the Markdown source. Given a +Markdown file `example.md` with one or more sections like: + +````markdown + + +```rust,compile_fail +{{#include example/src/main.rs:main}} + +fn some_more_code() { + // TODO: Write some Rust code here. +} +``` +```` + +and mdbook configuration in `book.toml` like: + +```toml +[output.exerciser] +output-directory = "comprehensive-rust-exercises" +``` + +It will create a file `book/exerciser/comprehensive-rust-exercises/example/src/main.rs` with the +appropriate contents. diff --git a/mdbook-exerciser/src/lib.rs b/mdbook-exerciser/src/lib.rs new file mode 100644 index 0000000..937eab4 --- /dev/null +++ b/mdbook-exerciser/src/lib.rs @@ -0,0 +1,73 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use log::{info, trace}; +use pulldown_cmark::{Event, Parser, Tag}; +use std::fs::{create_dir_all, File}; +use std::io::Write; +use std::path::Path; + +const FILENAME_START: &str = ""; + +pub fn process(output_directory: &Path, input_contents: &str) -> anyhow::Result<()> { + let parser = Parser::new(input_contents); + + // Find a specially-formatted comment followed by a code block, and then call `write_output` + // with the contents of the code block, to write to a file named by the comment. Code blocks + // without matching comments will be ignored, as will comments which are not followed by a code + // block. + let mut next_filename: Option = None; + let mut current_file: Option = None; + for event in parser { + trace!("{:?}", event); + match event { + Event::Html(html) => { + let html = html.trim(); + if html.starts_with(FILENAME_START) && html.ends_with(FILENAME_END) { + next_filename = Some( + html[FILENAME_START.len()..html.len() - FILENAME_END.len()] + .to_string(), + ); + info!("Next file: {:?}:", next_filename); + } + } + Event::Start(Tag::CodeBlock(x)) => { + info!("Start {:?}", x); + if let Some(filename) = &next_filename { + let full_filename = output_directory.join(filename); + info!("Opening {:?}", full_filename); + if let Some(directory) = full_filename.parent() { + create_dir_all(directory)?; + } + current_file = Some(File::create(full_filename)?); + next_filename = None; + } + } + Event::Text(text) => { + info!("Text: {:?}", text); + if let Some(output_file) = &mut current_file { + output_file.write(text.as_bytes())?; + } + } + Event::End(Tag::CodeBlock(x)) => { + info!("End {:?}", x); + current_file = None; + } + _ => {} + } + } + + Ok(()) +} diff --git a/mdbook-exerciser/src/main.rs b/mdbook-exerciser/src/main.rs new file mode 100644 index 0000000..398e472 --- /dev/null +++ b/mdbook-exerciser/src/main.rs @@ -0,0 +1,70 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::Context; +use log::trace; +use mdbook::book::Book; +use mdbook::renderer::RenderContext; +use mdbook::BookItem; +use mdbook_exerciser::process; +use std::fs::{create_dir, remove_dir_all}; +use std::io::stdin; +use std::path::Path; + +fn main() -> anyhow::Result<()> { + pretty_env_logger::init(); + + let context = RenderContext::from_json(&mut stdin()).context("Parsing stdin")?; + + let config = context + .config + .get_renderer("exerciser") + .context("Missing output.exerciser configuration")?; + + let output_directory = Path::new( + config + .get("output-directory") + .context("Missing output.exerciser.output-directory configuration value")? + .as_str() + .context("Expected a string for output.exerciser.output-directory")?, + ); + + let _ = remove_dir_all(output_directory); + create_dir(output_directory).with_context(|| { + format!("Failed to create output directory {:?}", output_directory) + })?; + + process_all(&context.book, output_directory)?; + + Ok(()) +} + +fn process_all(book: &Book, output_directory: &Path) -> anyhow::Result<()> { + for item in book.iter() { + if let BookItem::Chapter(chapter) = item { + trace!("Chapter {:?} / {:?}", chapter.path, chapter.source_path); + if let Some(chapter_path) = &chapter.path { + // Put the exercises in a subdirectory named after the chapter file, without its + // parent directories. + let chapter_output_directory = + output_directory.join(chapter_path.file_stem().with_context( + || format!("Chapter {:?} has no file stem", chapter_path), + )?); + process(&chapter_output_directory, &chapter.content)?; + } + } + } + + Ok(()) +} diff --git a/po/da.po b/po/da.po index 8919dbe..6d9c7b7 100644 --- a/po/da.po +++ b/po/da.po @@ -17,7 +17,7 @@ msgstr "Velkommen til Comprehensive Rust 🦀" #: src/SUMMARY.md:4 msgid "Running the Course" -msgstr "" +msgstr "Afvikling af kurset" #: src/SUMMARY.md:5 msgid "Course Structure" @@ -28,1997 +28,2398 @@ msgid "Keyboard Shortcuts" msgstr "Genvejstaster" #: src/SUMMARY.md:7 +msgid "Translations" +msgstr "" + +#: src/SUMMARY.md:8 msgid "Using Cargo" msgstr "Brug af Cargo" -#: src/SUMMARY.md:8 +#: src/SUMMARY.md:9 msgid "Rust Ecosystem" msgstr "Rust's økosystem" -#: src/SUMMARY.md:9 +#: src/SUMMARY.md:10 msgid "Code Samples" -msgstr "" +msgstr "Kodeeksempler" -#: src/SUMMARY.md:10 +#: src/SUMMARY.md:11 msgid "Running Cargo Locally" msgstr "" -#: src/SUMMARY.md:13 +#: src/SUMMARY.md:14 msgid "Day 1: Morning" msgstr "Dag 1: Formiddag" -#: src/SUMMARY.md:17 src/SUMMARY.md:73 src/SUMMARY.md:126 src/SUMMARY.md:176 +#: 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 "Velkommen" -#: src/SUMMARY.md:18 +#: src/SUMMARY.md:19 msgid "What is Rust?" msgstr "Hvad er Rust?" -#: src/SUMMARY.md:19 +#: src/SUMMARY.md:20 msgid "Hello World!" msgstr "Hej verden!" -#: src/SUMMARY.md:20 +#: src/SUMMARY.md:21 msgid "Small Example" msgstr "Et little eksempel" -#: src/SUMMARY.md:21 +#: src/SUMMARY.md:22 msgid "Why Rust?" msgstr "Hvorfor bruge Rust?" -#: src/SUMMARY.md:22 +#: src/SUMMARY.md:23 msgid "Compile Time Guarantees" -msgstr "" +msgstr "Garantier før programudføring" -#: src/SUMMARY.md:23 +#: src/SUMMARY.md:24 msgid "Runtime Guarantees" -msgstr "" +msgstr "Garantier under programudføring" -#: src/SUMMARY.md:24 +#: src/SUMMARY.md:25 msgid "Modern Features" -msgstr "Moderne features" +msgstr "Moderne faciliteter" -#: src/SUMMARY.md:25 +#: src/SUMMARY.md:26 msgid "Basic Syntax" -msgstr "Basal syntaks" +msgstr "Grundlæggende syntaks" -#: src/SUMMARY.md:26 +#: src/SUMMARY.md:27 msgid "Scalar Types" msgstr "Skalartyper" -#: src/SUMMARY.md:27 +#: src/SUMMARY.md:28 msgid "Compound Types" msgstr "Sammensatte typer" -#: src/SUMMARY.md:28 +#: src/SUMMARY.md:29 msgid "References" msgstr "Referencer" -#: src/SUMMARY.md:29 +#: src/SUMMARY.md:30 msgid "Dangling References" -msgstr "" +msgstr "Hængende referencer" -#: src/SUMMARY.md:30 +#: src/SUMMARY.md:31 msgid "Slices" -msgstr "" +msgstr "Arraysegmenter" -#: src/SUMMARY.md:31 +#: src/SUMMARY.md:32 msgid "String vs str" msgstr "String og str" -#: src/SUMMARY.md:32 +#: src/SUMMARY.md:33 msgid "Functions" msgstr "Funktioner" -#: src/SUMMARY.md:33 src/SUMMARY.md:80 +#: src/SUMMARY.md:34 +msgid "Rustdoc" +msgstr "" + +#: src/SUMMARY.md:35 src/SUMMARY.md:82 msgid "Methods" msgstr "Metoder" -#: src/SUMMARY.md:34 +#: src/SUMMARY.md:36 msgid "Overloading" msgstr "" -#: src/SUMMARY.md:35 src/SUMMARY.md:64 src/SUMMARY.md:88 src/SUMMARY.md:117 -#: src/SUMMARY.md:144 src/SUMMARY.md:168 src/SUMMARY.md:191 src/SUMMARY.md:218 +#: 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 "Øvelser" -#: src/SUMMARY.md:36 +#: src/SUMMARY.md:38 msgid "Implicit Conversions" msgstr "Implicitte konverteringer" -#: src/SUMMARY.md:37 +#: src/SUMMARY.md:39 msgid "Arrays and for Loops" -msgstr "Arrays of for-løkker" +msgstr "Arrays og for-løkker" -#: src/SUMMARY.md:39 +#: src/SUMMARY.md:41 msgid "Day 1: Afternoon" msgstr "Dag 1: Eftermiddag" -#: src/SUMMARY.md:41 +#: src/SUMMARY.md:43 msgid "Variables" msgstr "Variabler" -#: src/SUMMARY.md:42 +#: src/SUMMARY.md:44 msgid "Type Inference" -msgstr "" +msgstr "Typeudledning" -#: src/SUMMARY.md:43 +#: src/SUMMARY.md:45 msgid "static & const" msgstr "static & const" -#: src/SUMMARY.md:44 +#: src/SUMMARY.md:46 msgid "Scopes and Shadowing" msgstr "" -#: src/SUMMARY.md:45 +#: src/SUMMARY.md:47 msgid "Memory Management" msgstr "Håndtering af hukommelse" -#: src/SUMMARY.md:46 +#: src/SUMMARY.md:48 msgid "Stack vs Heap" msgstr "Stak og heap" -#: src/SUMMARY.md:47 +#: src/SUMMARY.md:49 msgid "Stack Memory" msgstr "Stakhukommelse" -#: src/SUMMARY.md:48 +#: src/SUMMARY.md:50 msgid "Manual Memory Management" msgstr "Manuel hukommelseshåndtering" -#: src/SUMMARY.md:49 +#: src/SUMMARY.md:51 msgid "Scope-Based Memory Management" msgstr "" -#: src/SUMMARY.md:50 +#: src/SUMMARY.md:52 msgid "Garbage Collection" -msgstr "" +msgstr "Automatisk hukommelseshåndtering" -#: src/SUMMARY.md:51 +#: src/SUMMARY.md:53 msgid "Rust Memory Management" msgstr "Hukommelseshåndtering i Rust" -#: src/SUMMARY.md:52 +#: src/SUMMARY.md:54 msgid "Comparison" msgstr "Sammenligning" -#: src/SUMMARY.md:53 +#: src/SUMMARY.md:55 msgid "Ownership" msgstr "Ejerskab" -#: src/SUMMARY.md:54 +#: src/SUMMARY.md:56 msgid "Move Semantics" msgstr "" -#: src/SUMMARY.md:55 +#: src/SUMMARY.md:57 msgid "Moved Strings in Rust" msgstr "" -#: src/SUMMARY.md:56 +#: src/SUMMARY.md:58 msgid "Double Frees in Modern C++" msgstr "" -#: src/SUMMARY.md:57 +#: src/SUMMARY.md:59 msgid "Moves in Function Calls" msgstr "" -#: src/SUMMARY.md:58 +#: src/SUMMARY.md:60 msgid "Copying and Cloning" msgstr "" -#: src/SUMMARY.md:59 +#: src/SUMMARY.md:61 msgid "Borrowing" msgstr "" -#: src/SUMMARY.md:60 +#: src/SUMMARY.md:62 msgid "Shared and Unique Borrows" msgstr "" -#: src/SUMMARY.md:61 +#: src/SUMMARY.md:63 msgid "Lifetimes" msgstr "" -#: src/SUMMARY.md:62 +#: src/SUMMARY.md:64 msgid "Lifetimes in Function Calls" msgstr "" -#: src/SUMMARY.md:63 +#: src/SUMMARY.md:65 msgid "Lifetimes in Data Structures" msgstr "" -#: src/SUMMARY.md:65 +#: src/SUMMARY.md:67 msgid "Designing a Library" msgstr "" -#: src/SUMMARY.md:66 +#: src/SUMMARY.md:68 msgid "Iterators and Ownership" msgstr "" -#: src/SUMMARY.md:69 +#: src/SUMMARY.md:71 msgid "Day 2: Morning" msgstr "" -#: src/SUMMARY.md:74 +#: src/SUMMARY.md:76 msgid "Structs" msgstr "" -#: src/SUMMARY.md:75 +#: src/SUMMARY.md:77 msgid "Tuple Structs" msgstr "" -#: src/SUMMARY.md:76 +#: src/SUMMARY.md:78 msgid "Field Shorthand Syntax" msgstr "" -#: src/SUMMARY.md:77 +#: src/SUMMARY.md:79 msgid "Enums" msgstr "" -#: src/SUMMARY.md:78 +#: src/SUMMARY.md:80 msgid "Variant Payloads" msgstr "" -#: src/SUMMARY.md:79 +#: src/SUMMARY.md:81 msgid "Enum Sizes" msgstr "" -#: src/SUMMARY.md:81 +#: src/SUMMARY.md:83 msgid "Method Receiver" msgstr "" -#: src/SUMMARY.md:82 src/SUMMARY.md:186 +#: src/SUMMARY.md:84 src/SUMMARY.md:159 src/SUMMARY.md:272 msgid "Example" msgstr "" -#: src/SUMMARY.md:83 +#: src/SUMMARY.md:85 msgid "Pattern Matching" msgstr "" -#: src/SUMMARY.md:84 +#: src/SUMMARY.md:86 msgid "Destructuring Enums" msgstr "" -#: src/SUMMARY.md:85 +#: src/SUMMARY.md:87 msgid "Destructuring Structs" msgstr "" -#: src/SUMMARY.md:86 +#: src/SUMMARY.md:88 msgid "Destructuring Arrays" msgstr "" -#: src/SUMMARY.md:87 +#: src/SUMMARY.md:89 msgid "Match Guards" msgstr "" -#: src/SUMMARY.md:89 +#: src/SUMMARY.md:91 msgid "Health Statistics" msgstr "" -#: src/SUMMARY.md:90 +#: src/SUMMARY.md:92 msgid "Points and Polygons" msgstr "" -#: src/SUMMARY.md:92 +#: src/SUMMARY.md:94 msgid "Day 2: Afternoon" msgstr "" -#: src/SUMMARY.md:94 +#: src/SUMMARY.md:96 src/SUMMARY.md:286 msgid "Control Flow" msgstr "" -#: src/SUMMARY.md:95 +#: src/SUMMARY.md:97 msgid "Blocks" msgstr "" -#: src/SUMMARY.md:96 +#: src/SUMMARY.md:98 msgid "if expressions" msgstr "" -#: src/SUMMARY.md:97 +#: src/SUMMARY.md:99 msgid "if let expressions" msgstr "" -#: src/SUMMARY.md:98 +#: src/SUMMARY.md:100 msgid "while expressions" msgstr "" -#: src/SUMMARY.md:99 +#: src/SUMMARY.md:101 msgid "while let expressions" msgstr "" -#: src/SUMMARY.md:100 +#: src/SUMMARY.md:102 msgid "for expressions" msgstr "" -#: src/SUMMARY.md:101 +#: src/SUMMARY.md:103 msgid "loop expressions" msgstr "" -#: src/SUMMARY.md:102 +#: src/SUMMARY.md:104 msgid "match expressions" msgstr "" -#: src/SUMMARY.md:103 +#: src/SUMMARY.md:105 msgid "break & continue" msgstr "" -#: src/SUMMARY.md:104 +#: src/SUMMARY.md:106 msgid "Standard Library" msgstr "" -#: src/SUMMARY.md:105 -msgid "String" +#: src/SUMMARY.md:107 +msgid "Option and Result" msgstr "" -#: src/SUMMARY.md:106 -msgid "Option and Result" +#: src/SUMMARY.md:108 +msgid "String" msgstr "" -#: src/SUMMARY.md:107 +#: src/SUMMARY.md:109 msgid "Vec" msgstr "" -#: src/SUMMARY.md:108 +#: src/SUMMARY.md:110 msgid "HashMap" msgstr "" -#: src/SUMMARY.md:109 +#: src/SUMMARY.md:111 msgid "Box" msgstr "" -#: src/SUMMARY.md:110 +#: src/SUMMARY.md:112 msgid "Recursive Data Types" msgstr "" -#: src/SUMMARY.md:111 +#: src/SUMMARY.md:113 msgid "Niche Optimization" msgstr "" -#: src/SUMMARY.md:112 +#: src/SUMMARY.md:114 msgid "Rc" msgstr "" -#: src/SUMMARY.md:113 +#: src/SUMMARY.md:115 msgid "Modules" msgstr "" -#: src/SUMMARY.md:114 +#: src/SUMMARY.md:116 msgid "Visibility" msgstr "" -#: src/SUMMARY.md:115 +#: src/SUMMARY.md:117 msgid "Paths" msgstr "" -#: src/SUMMARY.md:116 +#: src/SUMMARY.md:118 msgid "Filesystem Hierarchy" msgstr "" -#: src/SUMMARY.md:118 +#: src/SUMMARY.md:120 msgid "Luhn Algorithm" msgstr "" -#: src/SUMMARY.md:119 +#: src/SUMMARY.md:121 msgid "Strings and Iterators" msgstr "" -#: src/SUMMARY.md:122 +#: src/SUMMARY.md:124 msgid "Day 3: Morning" msgstr "" -#: src/SUMMARY.md:127 -msgid "Traits" -msgstr "" - -#: src/SUMMARY.md:128 -msgid "Deriving Traits" -msgstr "" - #: src/SUMMARY.md:129 -msgid "Default Methods" +msgid "Generics" msgstr "" #: src/SUMMARY.md:130 -msgid "Important Traits" +msgid "Generic Data Types" msgstr "" #: src/SUMMARY.md:131 -msgid "Iterator" +msgid "Generic Methods" msgstr "" #: src/SUMMARY.md:132 -msgid "FromIterator" +msgid "Monomorphization" msgstr "" #: src/SUMMARY.md:133 -msgid "Read and Write" +msgid "Traits" msgstr "" #: src/SUMMARY.md:134 -msgid "Add, Mul, ..." +msgid "Trait Objects" msgstr "" #: src/SUMMARY.md:135 -msgid "Drop" +msgid "Deriving Traits" msgstr "" #: src/SUMMARY.md:136 -msgid "Generics" +msgid "Default Methods" msgstr "" #: src/SUMMARY.md:137 -msgid "Generic Data Types" +msgid "Trait Bounds" msgstr "" #: src/SUMMARY.md:138 -msgid "Generic Methods" +msgid "impl Trait" msgstr "" #: src/SUMMARY.md:139 -msgid "Trait Bounds" +msgid "Important Traits" msgstr "" #: src/SUMMARY.md:140 -msgid "impl Trait" +msgid "Iterator" msgstr "" #: src/SUMMARY.md:141 -msgid "Closures" +msgid "FromIterator" msgstr "" #: src/SUMMARY.md:142 -msgid "Monomorphization" +msgid "From and Into" msgstr "" #: src/SUMMARY.md:143 -msgid "Trait Objects" +msgid "Read and Write" +msgstr "" + +#: src/SUMMARY.md:144 +msgid "Drop" msgstr "" #: src/SUMMARY.md:145 -msgid "A Simple GUI Library" +msgid "Default" +msgstr "" + +#: src/SUMMARY.md:146 +msgid "Operators: Add, Mul, ..." msgstr "" #: src/SUMMARY.md:147 -msgid "Day 3: Afternoon" +msgid "Closures: Fn, FnMut, FnOnce" msgstr "" #: src/SUMMARY.md:149 +msgid "A Simple GUI Library" +msgstr "" + +#: src/SUMMARY.md:151 +msgid "Day 3: Afternoon" +msgstr "" + +#: src/SUMMARY.md:153 msgid "Error Handling" msgstr "" -#: src/SUMMARY.md:150 +#: src/SUMMARY.md:154 msgid "Panics" msgstr "" -#: src/SUMMARY.md:151 +#: src/SUMMARY.md:155 msgid "Catching Stack Unwinding" msgstr "" -#: src/SUMMARY.md:152 +#: src/SUMMARY.md:156 msgid "Structured Error Handling" msgstr "" -#: src/SUMMARY.md:153 +#: src/SUMMARY.md:157 msgid "Propagating Errors with ?" msgstr "" -#: src/SUMMARY.md:154 +#: src/SUMMARY.md:158 msgid "Converting Error Types" msgstr "" -#: src/SUMMARY.md:155 +#: src/SUMMARY.md:160 msgid "Deriving Error Enums" msgstr "" -#: src/SUMMARY.md:156 +#: src/SUMMARY.md:161 +msgid "Dynamic Error Types" +msgstr "" + +#: src/SUMMARY.md:162 msgid "Adding Context to Errors" msgstr "" -#: src/SUMMARY.md:157 +#: src/SUMMARY.md:163 msgid "Testing" msgstr "" -#: src/SUMMARY.md:158 +#: src/SUMMARY.md:164 msgid "Unit Tests" msgstr "" -#: src/SUMMARY.md:159 +#: src/SUMMARY.md:165 msgid "Test Modules" msgstr "" -#: src/SUMMARY.md:160 +#: src/SUMMARY.md:166 msgid "Documentation Tests" msgstr "" -#: src/SUMMARY.md:161 +#: src/SUMMARY.md:167 msgid "Integration Tests" msgstr "" -#: src/SUMMARY.md:162 +#: src/SUMMARY.md:168 +msgid "Useful crates" +msgstr "" + +#: src/SUMMARY.md:169 msgid "Unsafe Rust" msgstr "" -#: src/SUMMARY.md:163 +#: src/SUMMARY.md:170 msgid "Dereferencing Raw Pointers" msgstr "" -#: src/SUMMARY.md:164 +#: src/SUMMARY.md:171 msgid "Mutable Static Variables" msgstr "" -#: src/SUMMARY.md:165 +#: src/SUMMARY.md:172 +msgid "Unions" +msgstr "" + +#: src/SUMMARY.md:173 msgid "Calling Unsafe Functions" msgstr "" -#: src/SUMMARY.md:166 +#: src/SUMMARY.md:174 +msgid "Writing Unsafe Functions" +msgstr "" + +#: src/SUMMARY.md:175 msgid "Extern Functions" msgstr "" -#: src/SUMMARY.md:167 -msgid "Unions" -msgstr "" - -#: src/SUMMARY.md:169 -msgid "Safe FFI Wrapper" -msgstr "" - -#: src/SUMMARY.md:172 -msgid "Day 4: Morning" -msgstr "" - -#: src/SUMMARY.md:177 -msgid "Concurrency" +#: src/SUMMARY.md:176 +msgid "Implementing Unsafe Traits" msgstr "" #: src/SUMMARY.md:178 -msgid "Threads" +msgid "Safe FFI Wrapper" msgstr "" -#: src/SUMMARY.md:179 -msgid "Scoped Threads" +#: src/SUMMARY.md:181 src/SUMMARY.md:249 +msgid "Android" msgstr "" -#: src/SUMMARY.md:180 -msgid "Channels" +#: src/SUMMARY.md:186 +msgid "Setup" msgstr "" -#: src/SUMMARY.md:181 -msgid "Unbounded Channels" +#: src/SUMMARY.md:187 +msgid "Build Rules" msgstr "" -#: src/SUMMARY.md:182 -msgid "Bounded Channels" +#: src/SUMMARY.md:188 +msgid "Binary" msgstr "" -#: src/SUMMARY.md:183 -msgid "Shared State" +#: src/SUMMARY.md:189 +msgid "Library" msgstr "" -#: src/SUMMARY.md:184 -msgid "Arc" +#: src/SUMMARY.md:190 +msgid "AIDL" msgstr "" -#: src/SUMMARY.md:185 -msgid "Mutex" +#: src/SUMMARY.md:191 +msgid "Interface" msgstr "" -#: src/SUMMARY.md:187 -msgid "Send and Sync" +#: src/SUMMARY.md:192 +msgid "Implementation" msgstr "" -#: src/SUMMARY.md:187 -msgid "Send" +#: src/SUMMARY.md:193 +msgid "Server" msgstr "" -#: src/SUMMARY.md:187 -msgid "Sync" +#: src/SUMMARY.md:194 +msgid "Deploy" msgstr "" -#: src/SUMMARY.md:190 -msgid "Examples" +#: src/SUMMARY.md:195 +msgid "Client" msgstr "" -#: src/SUMMARY.md:192 -msgid "Dining Philosophers" +#: src/SUMMARY.md:196 +msgid "Changing API" msgstr "" -#: src/SUMMARY.md:193 -msgid "Multi-threaded Link Checker" +#: src/SUMMARY.md:197 src/SUMMARY.md:240 +msgid "Logging" msgstr "" -#: src/SUMMARY.md:195 -msgid "Day 4: Afternoon" +#: src/SUMMARY.md:198 +msgid "Interoperability" msgstr "" #: src/SUMMARY.md:199 -msgid "Android" +msgid "With C" msgstr "" #: src/SUMMARY.md:200 -msgid "Setup" +msgid "Calling C with Bindgen" msgstr "" #: src/SUMMARY.md:201 -msgid "Build Rules" +msgid "Calling Rust from C" msgstr "" #: src/SUMMARY.md:202 -msgid "Binary" +msgid "With C++" msgstr "" #: src/SUMMARY.md:203 -msgid "Library" +msgid "With Java" msgstr "" -#: src/SUMMARY.md:204 -msgid "AIDL" -msgstr "" +#: src/SUMMARY.md:207 +#, fuzzy +msgid "Bare Metal: Morning" +msgstr "Dag 1: Formiddag" -#: src/SUMMARY.md:205 -msgid "Interface" +#: src/SUMMARY.md:212 +msgid "no_std" msgstr "" -#: src/SUMMARY.md:206 -msgid "Implementation" -msgstr "" +#: src/SUMMARY.md:213 +#, fuzzy +msgid "A Minimal Example" +msgstr "Et little eksempel" -#: src/SUMMARY.md:207 -msgid "Server" +#: src/SUMMARY.md:214 +msgid "alloc" msgstr "" -#: src/SUMMARY.md:208 -msgid "Deploy" +#: src/SUMMARY.md:215 +msgid "Microcontrollers" msgstr "" -#: src/SUMMARY.md:209 -msgid "Client" +#: src/SUMMARY.md:216 +msgid "Raw MMIO" msgstr "" -#: src/SUMMARY.md:210 -msgid "Changing API" +#: src/SUMMARY.md:217 +msgid "PACs" msgstr "" -#: src/SUMMARY.md:211 -msgid "Logging" +#: src/SUMMARY.md:218 +msgid "HAL Crates" msgstr "" -#: src/SUMMARY.md:212 -msgid "Interoperability" +#: src/SUMMARY.md:219 +msgid "Board Support Crates" msgstr "" -#: src/SUMMARY.md:213 -msgid "With C" +#: src/SUMMARY.md:220 +msgid "The Type State Pattern" msgstr "" -#: src/SUMMARY.md:214 -msgid "Calling C with Bindgen" +#: src/SUMMARY.md:221 +msgid "embedded-hal" msgstr "" -#: src/SUMMARY.md:215 -msgid "Calling Rust from C" +#: src/SUMMARY.md:222 +msgid "probe-rs, cargo-embed" msgstr "" -#: src/SUMMARY.md:216 -msgid "With C++" +#: src/SUMMARY.md:223 +msgid "Debugging" msgstr "" -#: src/SUMMARY.md:217 -msgid "With Java" +#: src/SUMMARY.md:224 src/SUMMARY.md:242 +msgid "Other Projects" msgstr "" -#: src/SUMMARY.md:220 -msgid "Final Words" -msgstr "" +#: src/SUMMARY.md:226 +#, fuzzy +msgid "Compass" +msgstr "Sammenligning" -#: src/SUMMARY.md:222 -msgid "Thanks!" -msgstr "" +#: src/SUMMARY.md:228 +#, fuzzy +msgid "Bare Metal: Afternoon" +msgstr "Dag 1: Eftermiddag" -#: src/SUMMARY.md:223 -msgid "Other Resources" +#: src/SUMMARY.md:230 +msgid "Application Processors" msgstr "" -#: src/SUMMARY.md:224 -msgid "Credits" +#: src/SUMMARY.md:231 +msgid "Inline Assembly" msgstr "" -#: src/SUMMARY.md:228 -msgid "Solutions" +#: src/SUMMARY.md:232 +msgid "MMIO" msgstr "" #: src/SUMMARY.md:233 -msgid "Day 1 Morning" +msgid "Let's Write a UART Driver" msgstr "" #: src/SUMMARY.md:234 -msgid "Day 1 Afternoon" +msgid "More Traits" msgstr "" #: src/SUMMARY.md:235 -msgid "Day 2 Morning" +msgid "A Better UART Driver" msgstr "" #: src/SUMMARY.md:236 -msgid "Day 2 Afternoon" +msgid "Bitflags" msgstr "" #: src/SUMMARY.md:237 -msgid "Day 3 Morning" +msgid "Multiple Registers" msgstr "" #: src/SUMMARY.md:238 -msgid "Day 3 Afternoon" -msgstr "" - -#: src/SUMMARY.md:239 -msgid "Day 4 Morning" +msgid "Driver" msgstr "" -#: src/welcome.md:1 -msgid "# Welcome to Comprehensive Rust 🦀" -msgstr "# Velkommen til Comprehensive Rust 🦀" +#: src/SUMMARY.md:239 src/SUMMARY.md:241 +#, fuzzy +msgid "Using It" +msgstr "Brug af Cargo" -#: src/welcome.md:3 -msgid "" -"This is a four 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." +#: src/SUMMARY.md:243 +msgid "Useful Crates" msgstr "" -"Dette er et fire dages Rust-kursus udviklet af Android-teamet. Kurset\n" -"dækker hele spektret af Rust, fra grundlæggende syntaks til avancerede\n" -"emner som generiske og fejlhåndtering. Det inkluderer også\n" -"Android-specifikt indhold på den sidste dag." -#: src/welcome.md:7 -msgid "" -"The goal of the course is to teach you Rust. We assume you don't know " -"anything\n" -"about Rust and hope to:" +#: src/SUMMARY.md:244 +msgid "zerocopy" msgstr "" -"Målet med kurset er at lære dig Rust. Vi antager, at du ikke ved noget\n" -"om Rust og håber at:" -#: src/welcome.md:10 -msgid "" -"* Give you a comprehensive understanding of the Rust syntax and language.\n" -"* Enable you to modify existing programs and write new programs in Rust.\n" -"* Show you common Rust idioms." +#: src/SUMMARY.md:245 +msgid "aarch64-paging" msgstr "" -"* Giver dig en omfattende forståelse af Rust-syntaksen og sproget.\n" -"* Gøre det muligt for dig at ændre eksisterende programmer og skrive\n" -" nye programmer i Rust.\n" -"* Vis dig almindelige Rust idiomer." -#: src/welcome.md:14 -msgid "On Day 4, we will cover Android-specific things such as:" -msgstr "På dag 4 vil vi dække Android-specifikke ting såsom:" - -#: src/welcome.md:16 -msgid "" -"* Building Android components in Rust.\n" -"* AIDL servers and clients.\n" -"* Interoperability with C, C++, and Java." +#: src/SUMMARY.md:246 +msgid "buddy_system_allocator" msgstr "" -"* Bygning af Android-komponenter i Rust\n" -"* AIDL servere og klienter.\n" -"* Interoperabilitet med C, C++ og Java." -#: src/welcome.md:20 -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. " +#: src/SUMMARY.md:247 +msgid "tinyvec" msgstr "" -"Det er vigtigt at bemærke, at dette kursus ikke dækker\n" -"Android-applikationsudvikling i Rust, og at de Android-specifikke dele\n" -"specifikt handler om at skrive kode til selve Android styresystemet." -#: src/welcome.md:24 -msgid "## Non-Goals" -msgstr "## Ting som ikke dækkes" - -#: src/welcome.md:26 -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:" +#: src/SUMMARY.md:248 +msgid "spin" msgstr "" -"Rust er et stort sprog og vi vil ikke være i stand til at dække det\n" -"hele på et par dage. Nogle af ting som vi ikke dækker er:" -#: src/welcome.md:29 -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." +#: src/SUMMARY.md:250 +msgid "vmbase" msgstr "" -#: src/welcome.md:37 -msgid "## Assumptions" +#: src/SUMMARY.md:252 +msgid "RTC Driver" msgstr "" -#: src/welcome.md:39 -msgid "" -"The course assumes that you already know how to program. Rust is a " -"statically\n" -"typed language and we will sometimes make comparisons with C and C++ to " -"better\n" -"explain or contrast the Rust approach." +#: src/SUMMARY.md:255 +msgid "Concurrency: Morning" msgstr "" -#: src/welcome.md:43 -msgid "" -"If you know how to program in a dynamically typed language such as Python " -"or\n" -"JavaScript, then you will be able to follow along just fine too." +#: src/SUMMARY.md:260 +msgid "Threads" msgstr "" -#: src/welcome.md:46 src/cargo/rust-ecosystem.md:19 -#: src/cargo/code-samples.md:22 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:17 src/basic-syntax/slices.md:18 -#: src/basic-syntax/string-slices.md:22 src/exercises/day-1/morning.md:9 -#: 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/enums/variant-payloads.md:33 -#: src/enums/sizes.md:31 src/exercises/day-2/morning.md:9 -#: src/control-flow/if-let-expressions.md:19 src/std/string.md:28 -#: src/std/option-result.md:16 src/std/box.md:32 src/std/rc.md:26 -#: src/exercises/day-2/afternoon.md:5 src/traits/iterator.md:30 -#: src/traits/from-iterator.md:12 src/generics/impl-trait.md:22 -#: src/generics/closures.md:23 src/exercises/day-3/morning.md:5 -#: src/error-handling/try-operator.md:48 -#: src/error-handling/converting-error-types.md:53 -#: src/exercises/day-3/afternoon.md:5 src/concurrency/threads.md:28 -#: src/exercises/day-4/morning.md:10 src/exercises/day-4/afternoon.md:10 -msgid "
" +#: src/SUMMARY.md:261 +msgid "Scoped Threads" msgstr "" -#: src/welcome.md:48 -msgid "" -"This is an example of a _speaker note_. We will use these to add additional\n" -"information to the slides. This could be key points which the instructor " -"should\n" -"cover as well as answers to typical questions which come up in class." +#: src/SUMMARY.md:262 +msgid "Channels" msgstr "" -#: src/welcome.md:52 src/cargo/rust-ecosystem.md:67 -#: src/cargo/code-samples.md:35 src/cargo/running-locally.md:74 -#: src/welcome-day-1.md:42 src/welcome-day-1/what-is-rust.md:27 -#: src/hello-world.md:36 src/hello-world/small-example.md:44 src/why-rust.md:24 -#: src/why-rust/compile-time.md:33 src/why-rust/runtime.md:22 -#: src/why-rust/modern.md:51 src/basic-syntax/compound-types.md:50 -#: src/basic-syntax/slices.md:30 src/exercises/day-1/morning.md:28 -#: src/basic-syntax/variables.md:20 src/basic-syntax/type-inference.md:44 -#: src/basic-syntax/static-and-const.md:52 -#: src/basic-syntax/scopes-shadowing.md:37 src/memory-management/stack.md:32 -#: src/memory-management/rust.md:18 src/ownership/move-semantics.md:26 -#: src/ownership/moves-function-calls.md:25 src/ownership/copy-clone.md:48 -#: src/ownership/borrowing.md:51 src/ownership/shared-unique-borrows.md:29 -#: src/ownership/lifetimes-function-calls.md:54 -#: src/ownership/lifetimes-data-structures.md:30 -#: src/exercises/day-1/afternoon.md:15 src/enums/variant-payloads.md:39 -#: src/enums/sizes.md:37 src/exercises/day-2/morning.md:15 -#: src/control-flow/if-let-expressions.md:25 src/std/string.md:34 -#: src/std/option-result.md:25 src/std/box.md:37 src/std/rc.md:32 -#: src/exercises/day-2/afternoon.md:11 src/traits/iterator.md:35 -#: src/traits/from-iterator.md:23 src/generics/impl-trait.md:31 -#: src/generics/closures.md:38 src/exercises/day-3/morning.md:11 -#: src/error-handling/try-operator.md:55 -#: src/error-handling/converting-error-types.md:60 -#: src/exercises/day-3/afternoon.md:11 src/concurrency/threads.md:45 -#: src/exercises/day-4/morning.md:16 src/exercises/day-4/afternoon.md:15 -msgid "
" +#: src/SUMMARY.md:263 +msgid "Unbounded Channels" msgstr "" -#: src/running-the-course.md:1 -msgid "# Running the Course" +#: src/SUMMARY.md:264 +msgid "Bounded Channels" msgstr "" -#: src/running-the-course.md:3 src/running-the-course/course-structure.md:3 -msgid "> This page is for the course instructor." +#: src/SUMMARY.md:265 +msgid "Send and Sync" msgstr "" -#: src/running-the-course.md:5 -msgid "" -"Here is a bit of background information about how we've been running the " -"course\n" -"internally at Google." +#: src/SUMMARY.md:265 +msgid "Send" msgstr "" -#: src/running-the-course.md:8 -msgid "To run the course, you need to:" +#: src/SUMMARY.md:265 +msgid "Sync" msgstr "" -#: src/running-the-course.md:10 -msgid "" -"1. Make yourself familiar with the course material. We've included speaker " -"notes\n" -" on some of the pages to help highlight the key points (please help us by\n" -" contributing more speaker notes!). You should make sure to open the " -"speaker\n" -" notes in a popup (click the link with a little arrow next to \"Speaker\n" -" Notes\"). This way you have a clean screen to present to the class." +#: src/SUMMARY.md:268 +msgid "Examples" msgstr "" -#: src/running-the-course.md:16 -msgid "" -"2. 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" -" they find it helpful to have a gap in the course since it helps them " -"process\n" -" all the information we give them." +#: src/SUMMARY.md:269 +msgid "Shared State" msgstr "" -#: src/running-the-course.md:21 -msgid "" -"3. 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" -" asking questions --- it's also small enough that one instructor will " -"have\n" -" time to answer the questions." +#: src/SUMMARY.md:270 +msgid "Arc" msgstr "" -#: src/running-the-course.md:26 -msgid "" -"4. On the day of your course, show up to the room a little early to set " -"things\n" -" up. We recommend presenting directly using `mdbook serve` running on " -"your\n" -" laptop. This ensures optimal performance with no lag as you change " -"pages.\n" -" Using your laptop will also allow you to fix typos as you or the course\n" -" participants spot them." +#: src/SUMMARY.md:271 +msgid "Mutex" msgstr "" -#: src/running-the-course.md:32 -msgid "" -"5. Let people solve the exercises by themselves or in small groups. 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 relvant\n" -" information in the standard library." +#: src/SUMMARY.md:274 src/SUMMARY.md:294 +msgid "Dining Philosophers" msgstr "" -#: src/running-the-course.md:38 -msgid "" -"6. If you don't skip the Android specific parts on Day 4, you will need an " -"[AOSP\n" -" checkout][1]. Make a checkout of the [course repository][2] on the same\n" -" machine and move the `src/android/` directory into the root of your AOSP\n" -" checkout. This will ensure that the Android build system sees the\n" -" `Android.bp` files in `src/android/`." +#: src/SUMMARY.md:275 +msgid "Multi-threaded Link Checker" msgstr "" -#: src/running-the-course.md:44 -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." +#: src/SUMMARY.md:277 +#, fuzzy +msgid "Concurrency: Afternoon" +msgstr "Dag 1: Eftermiddag" + +#: src/SUMMARY.md:279 +msgid "Async Basics" msgstr "" -#: src/running-the-course.md:48 -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!" +#: src/SUMMARY.md:280 +msgid "async/await" msgstr "" -#: src/running-the-course.md:51 -msgid "" -"Please [provide feedback][3] 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" -"better. Your students are also very welcome to [send us feedback][4]!" +#: src/SUMMARY.md:281 +msgid "Futures" msgstr "" -#: src/running-the-course.md:55 -msgid "" -"[1]: https://source.android.com/docs/setup/download/downloading\n" -"[2]: https://github.com/google/comprehensive-rust\n" -"[3]: https://github.com/google/comprehensive-rust/discussions/86\n" -"[4]: https://github.com/google/comprehensive-rust/discussions/100" +#: src/SUMMARY.md:282 +#, fuzzy +msgid "Runtimes" +msgstr "Garantier under programudføring" + +#: src/SUMMARY.md:283 +msgid "Tokio" msgstr "" -#: src/running-the-course/course-structure.md:1 -msgid "# Course Structure" +#: src/SUMMARY.md:284 +msgid "Tasks" msgstr "" -#: src/running-the-course/course-structure.md:5 -msgid "The course is fast paced and covers a lot of ground:" +#: src/SUMMARY.md:285 +msgid "Async Channels" msgstr "" -#: src/running-the-course/course-structure.md:7 -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 interoperability with other languages" +#: src/SUMMARY.md:287 +msgid "Join" msgstr "" -#: src/running-the-course/course-structure.md:12 -msgid "" -"> **Exercise for Day 4:** Do you interface with some C/C++ code in your " -"project\n" -"> which we could attempt to move to Rust? The fewer dependencies the " -"better.\n" -"> Parsing code would be ideal." +#: src/SUMMARY.md:288 +msgid "Select" msgstr "" -#: src/running-the-course/course-structure.md:16 -msgid "## Format" +#: src/SUMMARY.md:289 +msgid "Pitfalls" msgstr "" -#: src/running-the-course/course-structure.md:18 -msgid "" -"The course is meant to be very interactive and we recommend letting the\n" -"questions drive the exploration of Rust!" +#: src/SUMMARY.md:290 +msgid "Blocking the Executor" msgstr "" -#: src/running-the-course/keyboard-shortcuts.md:1 -msgid "# Keyboard Shortcuts" +#: src/SUMMARY.md:291 +msgid "Pin" msgstr "" -#: src/running-the-course/keyboard-shortcuts.md:3 -msgid "There are several useful keyboard shortcuts in mdBook:" +#: src/SUMMARY.md:292 +msgid "Async Traits" msgstr "" -#: src/running-the-course/keyboard-shortcuts.md:5 -msgid "" -"* Arrow-Left: Navigate to the previous page.\n" -"* Arrow-Right: Navigate to the next page.\n" -"* Ctrl + Enter: Execute the code sample that has focus.\n" -"* s: Activate the search bar." +#: src/SUMMARY.md:295 +msgid "Elevator Operations" msgstr "" -#: src/cargo.md:1 -msgid "# Using Cargo" +#: src/SUMMARY.md:298 +msgid "Final Words" msgstr "" -#: src/cargo.md:3 -msgid "" -"When you start reading about Rust, you will soon meet [Cargo](https://doc." -"rust-lang.org/cargo/), the standard tool\n" -"used in the Rust ecosystem to build and run Rust applications. Here we want " -"to\n" -"give a brief overview of what Cargo is and how it fits into the wider " -"ecosystem\n" -"and how it fits into this training." +#: src/SUMMARY.md:302 +msgid "Thanks!" msgstr "" -#: src/cargo.md:8 -msgid "## Installation" +#: src/SUMMARY.md:303 +msgid "Other Resources" msgstr "" -#: src/cargo.md:10 -msgid "### Rustup (Recommended)" +#: src/SUMMARY.md:304 +msgid "Credits" msgstr "" -#: src/cargo.md:12 -msgid "" -"You can follow the instructions to install cargo and rust compiler, among " -"other standard ecosystem tools with the [rustup][3] tool, which is " -"maintained by the Rust Foundation." +#: src/SUMMARY.md:307 +msgid "Solutions" msgstr "" -#: src/cargo.md:14 -msgid "" -"Along with cargo and rustc, Rustup will install itself as a command line " -"utility that you can use to install/switch toolchains, setup cross " -"compilation, etc." +#: src/SUMMARY.md:312 +msgid "Day 1 Morning" msgstr "" -#: src/cargo.md:16 -msgid "### Package Managers" +#: src/SUMMARY.md:313 +msgid "Day 1 Afternoon" msgstr "" -#: src/cargo.md:18 -msgid "#### Debian" +#: src/SUMMARY.md:314 +msgid "Day 2 Morning" msgstr "" -#: src/cargo.md:20 -msgid "On Debian/Ubuntu, you can install Cargo and the Rust source with" +#: src/SUMMARY.md:315 +msgid "Day 2 Afternoon" msgstr "" -#: src/cargo.md:22 -msgid "" -"```shell\n" -"$ sudo apt install cargo rust-src\n" -"```" +#: src/SUMMARY.md:316 +msgid "Day 3 Morning" msgstr "" -#: src/cargo.md:26 -msgid "" -"This will allow [rust-analyzer][1] to jump to the definitions. We suggest " -"using\n" -"[VS Code][2] to edit the code (but any LSP compatible editor works)." +#: src/SUMMARY.md:317 +msgid "Day 3 Afternoon" msgstr "" -#: src/cargo.md:29 -msgid "" -"Some folks also like to use the [Jetbrains][4] family of IDEs, which do " -"their own analysis but have their own tradeoffs. If you prefer them, you can " -"install the [Rust Plugin][5]. Please take note that as of January 2023 " -"debugging only works on the CLion version of the Jetbrains IDEA suite." +#: src/SUMMARY.md:318 +msgid "Bare Metal Rust Morning" msgstr "" -#: src/cargo.md:31 -msgid "" -"[1]: https://rust-analyzer.github.io/\n" -"[2]: https://code.visualstudio.com/\n" -"[3]: https://rustup.rs/\n" -"[4]: https://www.jetbrains.com/clion/\n" -"[5]: https://www.jetbrains.com/rust/" +#: src/SUMMARY.md:319 +msgid "Bare Metal Rust Afternoon" msgstr "" -#: src/cargo/rust-ecosystem.md:1 -msgid "# The Rust Ecosystem" +#: src/SUMMARY.md:320 +msgid "Concurrency Morning" msgstr "" -#: src/cargo/rust-ecosystem.md:3 -msgid "" -"The Rust ecosystem consists of a number of tools, of which the main ones are:" +#: src/SUMMARY.md:321 +msgid "Concurrency Afternoon" msgstr "" -#: src/cargo/rust-ecosystem.md:5 +#: src/welcome.md:1 +msgid "# Welcome to Comprehensive Rust 🦀" +msgstr "# Velkommen til Comprehensive Rust 🦀" + +#: src/welcome.md:3 msgid "" -"* `rustc`: the Rust compiler which turns `.rs` files into binaries and " -"other\n" -" intermediate formats[^rustc]." +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/" +"google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" +"google/comprehensive-rust/actions/workflows/build.yml)" msgstr "" -#: src/cargo/rust-ecosystem.md:8 -msgid "" -"* `cargo`: the Rust dependency manager and build tool. Cargo knows how to\n" -" download dependencies hosted on and it will pass them " -"to\n" -" `rustc` when building your project. Cargo also comes with a built-in test\n" -" runner which is used to execute unit tests[^cargo]." +#: src/welcome.md:3 +msgid "Build workflow" msgstr "" -#: src/cargo/rust-ecosystem.md:13 +#: src/welcome.md:3 msgid "" -"* `rustup`: the Rust toolchain installer and updater. This tool is used to\n" -" install and update `rustc` and `cargo` when new versions of Rust is " -"released.\n" -" In addition, `rustup` can also download documentation for the standard\n" -" library. You can have multiple versions of Rust installed at once and " -"`rustup`\n" -" will let you switch between them as needed." +"[![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" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/" +"comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)" msgstr "" -#: src/cargo/rust-ecosystem.md:21 src/hello-world.md:25 -#: src/hello-world/small-example.md:27 src/why-rust/runtime.md:10 -#: src/why-rust/modern.md:19 src/error-handling/try-operator.md:50 -#: src/error-handling/converting-error-types.md:55 -#: src/concurrency/threads.md:30 -msgid "Key points:" +#: src/welcome.md:4 +msgid "GitHub contributors" msgstr "" -#: src/cargo/rust-ecosystem.md:23 +#: src/welcome.md:4 msgid "" -"* Rust has a rapid release schedule with a new release coming out\n" -" every six weeks. New releases maintain backwards compatibility with\n" -" old releases --- plus they enable new functionality." +"[![GitHub contributors](https://img.shields.io/github/contributors/google/" +"comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)\n" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" +"rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers)" msgstr "" -#: src/cargo/rust-ecosystem.md:27 -msgid "" -"* There are three release channels: \"stable\", \"beta\", and \"nightly\"." +#: src/welcome.md:5 +msgid "GitHub stars" msgstr "" -#: src/cargo/rust-ecosystem.md:29 +#: src/welcome.md:5 msgid "" -"* New features are being tested on \"nightly\", \"beta\" is what becomes\n" -" \"stable\" every six weeks." +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" +"rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers)" msgstr "" -#: src/cargo/rust-ecosystem.md:32 +#: src/welcome.md:7 +#, fuzzy msgid "" -"* Rust also has [editions]: the current edition is Rust 2021. Previous\n" -" editions were Rust 2015 and Rust 2018." +"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 "" +"Dette er et fire dages Rust-kursus udviklet af Android-teamet. Kurset\n" +"dækker hele spektret af Rust, fra grundlæggende syntaks til avancerede\n" +"emner som generiske og fejlhåndtering. Det inkluderer også\n" +"Android-specifikt indhold på den sidste dag." -#: src/cargo/rust-ecosystem.md:35 +#: src/welcome.md:11 msgid "" -" * The editions are allowed to make backwards incompatible changes to\n" -" the language." +"The goal of the course is to teach you Rust. We assume you don't know " +"anything\n" +"about Rust and hope to:" msgstr "" +"Målet med kurset er at lære dig Rust. Vi antager, at du ikke ved noget\n" +"om Rust og håber at:" -#: src/cargo/rust-ecosystem.md:38 +#: src/welcome.md:14 msgid "" -" * To prevent breaking code, editions are opt-in: you select the\n" -" edition for your crate via the `Cargo.toml` file." +"* Give you a comprehensive understanding of the Rust syntax and language.\n" +"* Enable you to modify existing programs and write new programs in Rust.\n" +"* Show you common Rust idioms." msgstr "" +"* Giver dig en omfattende forståelse af Rust-syntaksen og sproget.\n" +"* Gøre det muligt for dig at ændre eksisterende programmer og skrive\n" +" nye programmer i Rust.\n" +"* Vis dig almindelige Rust idiomer." -#: src/cargo/rust-ecosystem.md:41 +#: src/welcome.md:18 msgid "" -" * To avoid splitting the ecosystem, Rust compilers can mix code\n" -" written for different editions." +"The first three days show you the fundamentals of Rust. Following this, " +"you're\n" +"invited to dive into one or more spezialized topics:" msgstr "" -#: src/cargo/rust-ecosystem.md:44 +#: src/welcome.md:21 msgid "" -" * Mention that it is quite rare to ever use the compiler directly not " -"through `cargo` (most users never do)." +"* [Android](android.md): a half-day course on using Rust for Android " +"platform\n" +" development (AOSP). This includes interoperability wtih 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" +" mutextes) and async/await concurrency (cooperative multitasking using\n" +" futures)." msgstr "" -#: src/cargo/rust-ecosystem.md:46 +#: src/welcome.md:32 +msgid "## Non-Goals" +msgstr "## Ting som ikke dækkes" + +#: src/welcome.md:34 msgid "" -" * It might be worth alluding that Cargo itself is an extremely powerful " -"and comprehensive tool. It is capable of many advanced features including " -"but not limited to: \n" -" * Project/package structure\n" -" * [workspaces]\n" -" * Dev Dependencies and Runtime Dependency management/caching\n" -" * [build scripting]\n" -" * [global installation]\n" -" * It is also extensible with sub command plugins as well (such as " -"[cargo clippy]).\n" -" * Read more from the [official Cargo Book]" +"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:" msgstr "" +"Rust er et stort sprog og vi vil ikke være i stand til at dække det\n" +"hele på et par dage. Nogle af ting som vi ikke dækker er:" -#: src/cargo/rust-ecosystem.md:55 -msgid "[editions]: https://doc.rust-lang.org/edition-guide/" +#: src/welcome.md:37 +msgid "" +"* 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 "" -#: src/cargo/rust-ecosystem.md:57 -msgid "[workspaces]: https://doc.rust-lang.org/cargo/reference/workspaces.html" +#: src/welcome.md:41 +msgid "## Assumptions" msgstr "" -#: src/cargo/rust-ecosystem.md:59 +#: src/welcome.md:43 msgid "" -"[build scripting]: https://doc.rust-lang.org/cargo/reference/build-scripts." -"html" +"The course assumes that you already know how to program. Rust is a " +"statically\n" +"typed language and we will sometimes make comparisons with C and C++ to " +"better\n" +"explain or contrast the Rust approach." msgstr "" -#: src/cargo/rust-ecosystem.md:61 +#: src/welcome.md:47 msgid "" -"[global installation]: https://doc.rust-lang.org/cargo/commands/cargo-" -"install.html" +"If you know how to program in a dynamically typed language such as Python " +"or\n" +"JavaScript, then you will be able to follow along just fine too." msgstr "" -#: src/cargo/rust-ecosystem.md:63 -msgid "[cargo clippy]: https://github.com/rust-lang/rust-clippy" +#: src/welcome.md:50 src/cargo/rust-ecosystem.md:19 +#: src/cargo/code-samples.md:22 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/scalar-types.md:19 +#: src/basic-syntax/compound-types.md:28 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/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/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: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: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/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 +#: src/bare-metal/microcontrollers/type-state.md:30 +#: src/bare-metal/microcontrollers/embedded-hal.md:17 +#: src/bare-metal/microcontrollers/probe-rs.md:14 +#: src/bare-metal/microcontrollers/debugging.md:25 +#: src/bare-metal/microcontrollers/other-projects.md:16 +#: src/exercises/bare-metal/morning.md:5 src/bare-metal/aps.md:7 +#: src/bare-metal/aps/inline-assembly.md:41 src/bare-metal/aps/mmio.md:7 +#: 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: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 "" -#: src/cargo/rust-ecosystem.md:65 -msgid "[official Cargo Book]: https://doc.rust-lang.org/cargo/" +#: src/welcome.md:52 +msgid "" +"This is an example of a _speaker note_. We will use these to add additional\n" +"information to the slides. This could be key points which the instructor " +"should\n" +"cover as well as answers to typical questions which come up in class." msgstr "" -#: src/cargo/code-samples.md:1 -msgid "# Code Samples in This Training" +#: src/welcome.md:56 src/cargo/rust-ecosystem.md:67 +#: src/cargo/code-samples.md:35 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/scalar-types.md:43 +#: 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:41 src/basic-syntax/rustdoc.md:33 +#: src/basic-syntax/methods.md:45 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 +#: src/memory-management/rust.md:18 src/ownership/move-semantics.md:26 +#: 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:104 +#: src/structs.md:41 src/structs/tuple-structs.md:43 +#: src/structs/field-shorthand.md:72 src/enums.md:41 +#: 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: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: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: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:41 +#: 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/exercises/day-3/morning.md:11 src/error-handling/result.md:33 +#: 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: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/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 +#: src/bare-metal/microcontrollers/other-projects.md:26 +#: src/exercises/bare-metal/morning.md:11 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: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 "" -#: src/cargo/code-samples.md:3 -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" -"ensures a consistent experience for everyone." +#: src/running-the-course.md:1 +msgid "# Running the Course" msgstr "" -#: src/cargo/code-samples.md:7 -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." +#: src/running-the-course.md:3 src/running-the-course/course-structure.md:3 +msgid "> This page is for the course instructor." msgstr "" -#: src/cargo/code-samples.md:11 -msgid "The code blocks in this course are fully interactive:" +#: src/running-the-course.md:5 +msgid "" +"Here is a bit of background information about how we've been running the " +"course\n" +"internally at Google." msgstr "" -#: src/cargo/code-samples.md:13 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"Edit me!\");\n" -"}\n" -"```" +#: src/running-the-course.md:8 +msgid "Before you run the course, you will want to:" msgstr "" -#: src/cargo/code-samples.md:19 +#: src/running-the-course.md:10 msgid "" -"You can use Ctrl + Enter to execute the code when focus is in " -"the\n" -"text box." +"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" +" notes!). When presenting, you should make sure to open the speaker notes " +"in a\n" +" 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. 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-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" +" In particular, you will be doing a lot of live-coding as an instructor, " +"so a lectern won't\n" +" be very helpful for you.\n" +"\n" +"1. On the day of your course, show up to the room a little early to set " +"things\n" +" up. We recommend presenting directly using `mdbook serve` running on " +"your\n" +" laptop (see the [installation instructions][3]). This ensures optimal " +"performance with no lag as you change pages.\n" +" 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.\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." msgstr "" -#: src/cargo/code-samples.md:24 +#: src/running-the-course.md:43 msgid "" -"Most code samples are editable like shown above. A few code samples\n" -"are not editable for various reasons:" +"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!" msgstr "" -#: src/cargo/code-samples.md:27 +#: src/running-the-course.md:46 msgid "" -"* The embedded playgrounds cannot execute unit tests. Copy-paste the\n" -" code and open it in the real Playground to demonstrate unit tests." +"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" +"better. Your students are also very welcome to [send us feedback][2]!" msgstr "" -#: src/cargo/code-samples.md:30 -msgid "" -"* The embedded playgrounds lose their state the moment you navigate\n" -" away from the page! This is the reason that the students should\n" -" solve the exercises using a local Rust installation or via the\n" -" Playground." +#: src/running-the-course/course-structure.md:1 +msgid "# Course Structure" msgstr "" -#: src/cargo/running-locally.md:1 -msgid "# Running Code Locally with Cargo" +#: src/running-the-course/course-structure.md:5 +msgid "The course is fast paced and covers a lot of ground:" msgstr "" -#: src/cargo/running-locally.md:3 +#: src/running-the-course/course-structure.md:7 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:" +"* 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." msgstr "" -#: src/cargo/running-locally.md:8 -msgid "" -"```shell\n" -"% rustc --version\n" -"rustc 1.61.0 (fe5b13d68 2022-05-18)\n" -"% cargo --version\n" -"cargo 1.61.0 (a028ae4 2022-04-29)\n" -"```" +#: src/running-the-course/course-structure.md:11 +msgid "## Deep Dives" msgstr "" -#: src/cargo/running-locally.md:15 +#: src/running-the-course/course-structure.md:13 msgid "" -"With this is in place, then follow these steps to build a Rust binary from " -"one\n" -"of the examples in this training:" +"In addition to the 3-day class on Rust Fundamentals, we cover some more\n" +"specialized topics:" msgstr "" -#: src/cargo/running-locally.md:18 -msgid "" -"1. Click the \"Copy to clipboard\" button on the example you want to copy." +#: src/running-the-course/course-structure.md:16 +msgid "### Android" msgstr "" -#: src/cargo/running-locally.md:20 +#: src/running-the-course/course-structure.md:18 msgid "" -"2. Use `cargo new exercise` to create a new `exercise/` directory for your " -"code:" +"The [Android Deep Dive](../android.md) is a half-day course on using Rust " +"for\n" +"Android platform development. This includes interoperability wtih C, C++, " +"and\n" +"Java." msgstr "" -#: src/cargo/running-locally.md:22 +#: src/running-the-course/course-structure.md:22 msgid "" -" ```shell\n" -" $ cargo new exercise\n" -" Created binary (application) `exercise` package\n" -" ```" +"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 "" -#: src/cargo/running-locally.md:27 +#: src/running-the-course/course-structure.md:27 msgid "" -"3. Navigate into `exercise/` and use `cargo run` to build and run your " -"binary:" +"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 "" -#: src/cargo/running-locally.md:29 -msgid "" -" ```shell\n" -" $ cd exercise\n" -" $ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" -" Running `target/debug/exercise`\n" -" Hello, world!\n" -" ```" +#: src/running-the-course/course-structure.md:34 +msgid "### Bare-Metal" msgstr "" -#: src/cargo/running-locally.md:38 +#: src/running-the-course/course-structure.md:36 msgid "" -"4. Replace the boiler-plate code in `src/main.rs` with your own code. For\n" -" example, using the example on the previous page, make `src/main.rs` look " -"like" +"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 "" -#: src/cargo/running-locally.md:41 +#: src/running-the-course/course-structure.md:40 msgid "" -" ```rust\n" -" fn main() {\n" -" println!(\"Edit me!\");\n" -" }\n" -" ```" +"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 "" -#: src/cargo/running-locally.md:47 -msgid "5. Use `cargo run` to build and run your updated binary:" +#: src/running-the-course/course-structure.md:45 +msgid "### Concurrency" msgstr "" -#: src/cargo/running-locally.md:49 +#: src/running-the-course/course-structure.md:47 msgid "" -" ```shell\n" -" $ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" -" Running `target/debug/exercise`\n" -" Edit me!\n" -" ```" +"The [Concurrency Deep Dive](../concurrency.md) is a full day class on " +"classical\n" +"as well as `async`/`await` concurrency." msgstr "" -#: src/cargo/running-locally.md:57 +#: src/running-the-course/course-structure.md:50 msgid "" -"6. Use `cargo check` to quickly check your project for errors, use `cargo " -"build`\n" -" to compile it without running it. You will find the output in `target/" -"debug/`\n" -" for a normal debug build. Use `cargo build --release` to produce an " -"optimized\n" -" release build in `target/release/`." +"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 "" -#: src/cargo/running-locally.md:62 +#: src/running-the-course/course-structure.md:54 msgid "" -"7. You can add dependencies for your project by editing `Cargo.toml`. When " -"you\n" -" run `cargo` commands, it will automatically download and compile missing\n" -" dependencies for you." +"```shell\n" +"cargo init concurrency\n" +"cd concurrency\n" +"cargo add tokio --features full\n" +"cargo run\n" +"```" msgstr "" -#: src/cargo/running-locally.md:66 -msgid "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" +#: src/running-the-course/course-structure.md:61 +msgid "## Format" msgstr "" -#: src/cargo/running-locally.md:70 +#: src/running-the-course/course-structure.md:63 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." +"The course is meant to be very interactive and we recommend letting the\n" +"questions drive the exploration of Rust!" msgstr "" -#: src/welcome-day-1.md:1 -msgid "# Welcome to Day 1" +#: src/running-the-course/keyboard-shortcuts.md:1 +msgid "# Keyboard Shortcuts" msgstr "" -#: src/welcome-day-1.md:3 -msgid "" -"This is the first day of Comprehensive Rust. We will cover a lot of ground\n" -"today:" +#: src/running-the-course/keyboard-shortcuts.md:3 +msgid "There are several useful keyboard shortcuts in mdBook:" msgstr "" -#: src/welcome-day-1.md:6 +#: src/running-the-course/keyboard-shortcuts.md:5 msgid "" -"* Basic Rust syntax: variables, scalar and compound types, enums, structs,\n" -" references, functions, and methods." +"* Arrow-Left: Navigate to the previous page.\n" +"* Arrow-Right: Navigate to the next page.\n" +"* Ctrl + Enter: Execute the code sample that has focus.\n" +"* s: Activate the search bar." msgstr "" -#: src/welcome-day-1.md:9 -msgid "" -"* Memory management: stack vs heap, manual memory management, scope-based " -"memory\n" -" management, and garbage collection." +#: src/running-the-course/translations.md:1 +msgid "# Translations" msgstr "" -#: src/welcome-day-1.md:12 +#: src/running-the-course/translations.md:3 msgid "" -"* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." -msgstr "" - -#: src/welcome-day-1.md:16 -msgid "Please remind the students that:" +"The course has been translated into other languages by a set of wonderful\n" +"volunteers:" msgstr "" -#: src/welcome-day-1.md:18 +#: src/running-the-course/translations.md:6 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" -"* The questions will likely mean that we about things ahead of the slides.\n" -" * This is perfectly okay! Repetition is an important part of leaning. " -"Remember\n" -" that the slides are just a support and you are free to skip them as you\n" -" like." +"* [Brazilian Portuguese][pt-BR] by [@rastringer] and [@hugojacob].\n" +"* [Korean][ko] by [@keispace], [@jiyongp] and [@jooyunghan]." msgstr "" -#: src/welcome-day-1.md:29 +#: src/running-the-course/translations.md:9 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." +"Use the language picker in the top-right corner to switch between languages." msgstr "" -#: src/welcome-day-1.md:33 +#: src/running-the-course/translations.md:11 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):" +"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]." msgstr "" -#: src/welcome-day-1.md:36 -msgid "" -"* Morning: 9:00 to 12:00,\n" -"* Afternoon: 13:00 to 16:00." +#: src/cargo.md:1 +msgid "# Using Cargo" msgstr "" -#: src/welcome-day-1.md:39 +#: src/cargo.md:3 msgid "" -"You can of course adjust this as necessary. Please make sure to include " -"breaks,\n" -"we recommend a break every hour!" +"When you start reading about Rust, you will soon meet [Cargo](https://doc." +"rust-lang.org/cargo/), the standard tool\n" +"used in the Rust ecosystem to build and run Rust applications. Here we want " +"to\n" +"give a brief overview of what Cargo is and how it fits into the wider " +"ecosystem\n" +"and how it fits into this training." msgstr "" -#: src/welcome-day-1/what-is-rust.md:1 -msgid "# What is Rust?" +#: src/cargo.md:8 +msgid "## Installation" msgstr "" -#: src/welcome-day-1/what-is-rust.md:3 -msgid "Rust is a new programming language which had its 1.0 release in 2015:" +#: src/cargo.md:10 +msgid "### Rustup (Recommended)" msgstr "" -#: src/welcome-day-1/what-is-rust.md:5 +#: src/cargo.md:12 msgid "" -"* Rust is a statically compiled language in a similar role as C++\n" -" * `rustc` uses LLVM as its backend.\n" -"* Rust supports many [platforms and\n" -" architectures](https://doc.rust-lang.org/nightly/rustc/platform-support." -"html):\n" -" * x86, ARM, WebAssembly, ...\n" -" * Linux, Mac, Windows, ...\n" -"* Rust is used for a wide range of devices:\n" -" * firmware and boot loaders,\n" -" * smart displays,\n" -" * mobile phones,\n" -" * desktops,\n" -" * servers." +"You can follow the instructions to install cargo and rust compiler, among " +"other standard ecosystem tools with the [rustup][3] tool, which is " +"maintained by the Rust Foundation." msgstr "" -#: src/welcome-day-1/what-is-rust.md:21 -msgid "Rust fits in the same area as C++:" +#: src/cargo.md:14 +msgid "" +"Along with cargo and rustc, Rustup will install itself as a command line " +"utility that you can use to install/switch toolchains, setup cross " +"compilation, etc." msgstr "" -#: src/welcome-day-1/what-is-rust.md:23 -msgid "" -"* High flexibility.\n" -"* High level of control.\n" -"* Can be scaled down to very constrained devices like mobile phones." +#: src/cargo.md:16 +msgid "### Package Managers" msgstr "" -#: src/hello-world.md:1 -msgid "# Hello World!" +#: src/cargo.md:18 +msgid "#### Debian" msgstr "" -#: src/hello-world.md:3 +#: src/cargo.md:20 msgid "" -"Let us jump into the simplest possible Rust program, a classic Hello World\n" -"program:" +"On Debian/Ubuntu, you can install Cargo, the Rust source and the [Rust " +"formatter][6] with" msgstr "" -#: src/hello-world.md:6 +#: src/cargo.md:22 msgid "" -"```rust\n" -"fn main() {\n" -" println!(\"Hello 🌍!\");\n" -"}\n" +"```shell\n" +"$ sudo apt install cargo rust-src rustfmt\n" "```" msgstr "" -#: src/hello-world.md:12 -msgid "What you see:" -msgstr "" - -#: src/hello-world.md:14 +#: src/cargo.md:26 msgid "" -"* Functions are introduced with `fn`.\n" -"* Blocks are delimited by curly braces like in C and C++.\n" -"* The `main` function is the entry point of the program.\n" -"* Rust has hygienic macros, `println!` is an example of this.\n" -"* Rust strings are UTF-8 encoded and can contain any Unicode character." +"This will allow [rust-analyzer][1] to jump to the definitions. We suggest " +"using\n" +"[VS Code][2] to edit the code (but any LSP compatible editor works)." msgstr "" -#: src/hello-world.md:22 +#: src/cargo.md:29 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." +"Some folks also like to use the [JetBrains][4] family of IDEs, which do " +"their own analysis but have their own tradeoffs. If you prefer them, you can " +"install the [Rust Plugin][5]. Please take note that as of January 2023 " +"debugging only works on the CLion version of the JetBrains IDEA suite." msgstr "" -#: src/hello-world.md:27 -msgid "" -"* Rust is very much like other languages in the C/C++/Java tradition. It is\n" -" imperative (not functional) and it doesn't try to reinvent things unless\n" -" absolutely necessary." +#: src/cargo/rust-ecosystem.md:1 +msgid "# The Rust Ecosystem" msgstr "" -#: src/hello-world.md:31 -msgid "* Rust is modern with full support for things like Unicode." +#: src/cargo/rust-ecosystem.md:3 +msgid "" +"The Rust ecosystem consists of a number of tools, of which the main ones are:" msgstr "" -#: src/hello-world.md:33 +#: src/cargo/rust-ecosystem.md:5 msgid "" -"* Rust uses macros for situations where you want to have a variable number " -"of\n" -" arguments (no function [overloading](basic-syntax/functions-interlude.md))." +"* `rustc`: the Rust compiler which turns `.rs` files into binaries and " +"other\n" +" intermediate formats.\n" +"\n" +"* `cargo`: the Rust dependency manager and build tool. Cargo knows how to\n" +" download dependencies hosted on and it will pass them " +"to\n" +" `rustc` when building your project. Cargo also comes with a built-in test\n" +" runner which is used to execute unit tests.\n" +"\n" +"* `rustup`: the Rust toolchain installer and updater. This tool is used to\n" +" install and update `rustc` and `cargo` when new versions of Rust is " +"released.\n" +" In addition, `rustup` can also download documentation for the standard\n" +" library. You can have multiple versions of Rust installed at once and " +"`rustup`\n" +" will let you switch between them as needed." msgstr "" -#: src/hello-world/small-example.md:1 -msgid "# Small Example" +#: 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: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 "" -#: src/hello-world/small-example.md:3 -msgid "Here is a small example program in Rust:" +#: src/cargo/rust-ecosystem.md:23 +msgid "" +"* Rust has a rapid release schedule with a new release coming out\n" +" every six weeks. New releases maintain backwards compatibility with\n" +" old releases --- plus they enable new functionality.\n" +"\n" +"* There are three release channels: \"stable\", \"beta\", and \"nightly\".\n" +"\n" +"* New features are being tested on \"nightly\", \"beta\" is what becomes\n" +" \"stable\" every six weeks.\n" +"\n" +"* Rust also has [editions]: the current edition is Rust 2021. Previous\n" +" editions were Rust 2015 and Rust 2018.\n" +"\n" +" * The editions are allowed to make backwards incompatible changes to\n" +" the language.\n" +"\n" +" * To prevent breaking code, editions are opt-in: you select the\n" +" edition for your crate via the `Cargo.toml` file.\n" +"\n" +" * To avoid splitting the ecosystem, Rust compilers can mix code\n" +" written for different editions.\n" +"\n" +" * Mention that it is quite rare to ever use the compiler directly not " +"through `cargo` (most users never do).\n" +"\n" +" * It might be worth alluding that Cargo itself is an extremely powerful " +"and comprehensive tool. It is capable of many advanced features including " +"but not limited to: \n" +" * Project/package structure\n" +" * [workspaces]\n" +" * Dev Dependencies and Runtime Dependency management/caching\n" +" * [build scripting]\n" +" * [global installation]\n" +" * It is also extensible with sub command plugins as well (such as " +"[cargo clippy]).\n" +" * Read more from the [official Cargo Book]" msgstr "" -#: src/hello-world/small-example.md:5 -msgid "" -"```rust,editable\n" -"fn main() { // Program entry point\n" -" let mut x: i32 = 6; // Mutable variable binding\n" -" print!(\"{x}\"); // Macro for printing, like printf\n" -" while x != 1 { // No parenthesis around expression\n" -" if x % 2 == 0 { // Math like in other languages\n" -" x = x / 2;\n" -" } else {\n" -" x = 3 * x + 1;\n" -" }\n" -" print!(\" -> {x}\");\n" -" }\n" -" println!();\n" -"}\n" -"```" +#: src/cargo/code-samples.md:1 +msgid "# Code Samples in This Training" msgstr "" -#: src/hello-world/small-example.md:23 +#: src/cargo/code-samples.md:3 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." +"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" +"ensures a consistent experience for everyone." msgstr "" -#: src/hello-world/small-example.md:29 +#: src/cargo/code-samples.md:7 msgid "" -"* Explain that all variables are statically typed. Try removing `i32` to " -"trigger\n" -" type inference. Try with `i8` instead and trigger a runtime integer " -"overflow." +"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 "" -#: src/hello-world/small-example.md:32 -msgid "* Change `let mut x` to `let x`, discuss the compiler error." +#: src/cargo/code-samples.md:11 +msgid "The code blocks in this course are fully interactive:" msgstr "" -#: src/hello-world/small-example.md:34 +#: src/cargo/code-samples.md:13 msgid "" -"* Show how `print!` gives a compilation error if the arguments don't match " -"the\n" -" format string." +"```rust,editable\n" +"fn main() {\n" +" println!(\"Edit me!\");\n" +"}\n" +"```" msgstr "" -#: src/hello-world/small-example.md:37 +#: src/cargo/code-samples.md:19 msgid "" -"* Show how you need to use `{}` as a placeholder if you want to print an\n" -" expression which is more complex than just a single variable." +"You can use Ctrl + Enter to execute the code when focus is in " +"the\n" +"text box." msgstr "" -#: src/hello-world/small-example.md:40 +#: src/cargo/code-samples.md:24 msgid "" -"* Show the students the standard library, show them how to search for `std::" -"fmt`\n" -" which has the rules of the formatting mini-language. It's important that " -"the\n" -" students become familiar with searching in the standard library." +"Most code samples are editable like shown above. A few code samples\n" +"are not editable for various reasons:" msgstr "" -#: src/why-rust.md:1 -msgid "# Why Rust?" +#: src/cargo/code-samples.md:27 +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" +"\n" +"* The embedded playgrounds lose their state the moment you navigate\n" +" away from the page! This is the reason that the students should\n" +" solve the exercises using a local Rust installation or via the\n" +" Playground." msgstr "" -#: src/why-rust.md:3 -msgid "Some unique selling points of Rust:" +#: src/cargo/running-locally.md:1 +msgid "# Running Code Locally with Cargo" msgstr "" -#: src/why-rust.md:5 +#: src/cargo/running-locally.md:3 msgid "" -"* Compile time memory safety.\n" -"* Lack of undefined runtime behavior.\n" -"* Modern language features." +"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 "" -#: src/why-rust.md:11 +#: src/cargo/running-locally.md:8 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:" +"```shell\n" +"% rustc --version\n" +"rustc 1.61.0 (fe5b13d68 2022-05-18)\n" +"% cargo --version\n" +"cargo 1.61.0 (a028ae4 2022-04-29)\n" +"```" msgstr "" -#: src/why-rust.md:14 +#: src/cargo/running-locally.md:15 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" -" have the memory unsafety issues. In addition, you get a modern language " -"with\n" -" constructs like pattern matching and built-in dependency management." +"With this is in place, then follow these steps to build a Rust binary from " +"one\n" +"of the examples in this training:" msgstr "" -#: src/why-rust.md:19 +#: src/cargo/running-locally.md:18 msgid "" -"* Experience with Java, Go, Python, JavaScript...: You get the same memory " -"safety\n" -" as in those languages, plus a similar high-level language feeling. In " -"addition\n" -" 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)" +"1. Click the \"Copy to clipboard\" button on the example you want to copy.\n" +"\n" +"2. Use `cargo new exercise` to create a new `exercise/` directory for your " +"code:\n" +"\n" +" ```shell\n" +" $ cargo new exercise\n" +" Created binary (application) `exercise` package\n" +" ```\n" +"\n" +"3. Navigate into `exercise/` and use `cargo run` to build and run your " +"binary:\n" +"\n" +" ```shell\n" +" $ cd exercise\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +" Running `target/debug/exercise`\n" +" Hello, world!\n" +" ```\n" +"\n" +"4. Replace the boiler-plate code in `src/main.rs` with your own code. For\n" +" example, using the example on the previous page, make `src/main.rs` look " +"like\n" +"\n" +" ```rust\n" +" fn main() {\n" +" println!(\"Edit me!\");\n" +" }\n" +" ```\n" +"\n" +"5. Use `cargo run` to build and run your updated binary:\n" +"\n" +" ```shell\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +" Running `target/debug/exercise`\n" +" Edit me!\n" +" ```\n" +"\n" +"6. Use `cargo check` to quickly check your project for errors, use `cargo " +"build`\n" +" to compile it without running it. You will find the output in `target/" +"debug/`\n" +" for a normal debug build. Use `cargo build --release` to produce an " +"optimized\n" +" release build in `target/release/`.\n" +"\n" +"7. You can add dependencies for your project by editing `Cargo.toml`. When " +"you\n" +" run `cargo` commands, it will automatically download and compile missing\n" +" dependencies for you." msgstr "" -#: src/why-rust/compile-time.md:1 -msgid "# Compile Time Guarantees" +#: src/cargo/running-locally.md:70 +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 "" -#: src/why-rust/compile-time.md:3 -msgid "Static memory management at compile time:" +#: src/welcome-day-1.md:1 +msgid "# Welcome to Day 1" msgstr "" -#: src/why-rust/compile-time.md:5 +#: src/welcome-day-1.md:3 msgid "" -"* No uninitialized variables.\n" -"* No memory leaks (_mostly_, see notes).\n" -"* No double-frees.\n" -"* No use-after-free.\n" -"* No `NULL` pointers.\n" -"* No forgotten locked mutexes.\n" -"* No data races between threads.\n" -"* No iterator invalidation." +"This is the first day of Comprehensive Rust. We will cover a lot of ground\n" +"today:" msgstr "" -#: src/why-rust/compile-time.md:16 +#: src/welcome-day-1.md:6 msgid "" -"It is possible to produce memory leaks in (safe) Rust. Some examples\n" -"are:" +"* Basic Rust syntax: variables, scalar and compound types, enums, structs,\n" +" references, functions, and methods.\n" +"\n" +"* Memory management: stack vs heap, manual memory management, scope-based " +"memory\n" +" management, and garbage collection.\n" +"\n" +"* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." msgstr "" -#: src/why-rust/compile-time.md:19 -msgid "" -"* You can for 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" -"* You can also accidentally create a [reference cycle] with `Rc` or\n" -" `Arc`." +#: src/welcome-day-1.md:16 +msgid "Please remind the students that:" msgstr "" -#: src/why-rust/compile-time.md:26 +#: src/welcome-day-1.md:18 msgid "" -"For the purpose of this course, \"No memory leaks\" should be understood\n" -"as \"Pretty much no *accidental* memory leaks\"." +"* 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" +"* 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 "" -#: src/why-rust/compile-time.md:29 +#: src/welcome-day-1.md:29 msgid "" -"[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method." -"leak\n" -"[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" -"[reference cycle]: https://doc.rust-lang.org/book/ch15-06-reference-cycles." -"html" +"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 "" -#: src/why-rust/runtime.md:1 -msgid "# Runtime Guarantees" +#: src/welcome-day-1.md:33 +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 "" -#: src/why-rust/runtime.md:3 -msgid "No undefined behavior at runtime:" +#: src/welcome-day-1.md:36 +msgid "" +"* Morning: 9:00 to 12:00,\n" +"* Afternoon: 13:00 to 16:00." msgstr "" -#: src/why-rust/runtime.md:5 +#: src/welcome-day-1.md:39 msgid "" -"* Array access is bounds checked.\n" -"* Integer overflow is defined." +"You can of course adjust this as necessary. Please make sure to include " +"breaks,\n" +"we recommend a break every hour!" msgstr "" -#: src/why-rust/runtime.md:12 +#: src/welcome-day-1/what-is-rust.md:1 +msgid "# What is Rust?" +msgstr "" + +#: src/welcome-day-1/what-is-rust.md:3 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" -" semantics. By default, you get panics in debug mode (`cargo build`)\n" -" and wrap-around in release mode (`cargo build --release`)." +"Rust is a new programming language which had its [1.0 release in 2015][1]:" msgstr "" -#: src/why-rust/runtime.md:17 +#: src/welcome-day-1/what-is-rust.md:5 msgid "" -"* Bounds checking cannot be disabled with a compiler flag. It can also\n" -" not be disabled directly with the `unsafe` keyword. However,\n" -" `unsafe` allows you to call functions such as `slice::get_unchecked`\n" -" which does not do bounds checking." +"* Rust is a statically compiled language in a similar role as C++\n" +" * `rustc` uses LLVM as its backend.\n" +"* Rust supports many [platforms and\n" +" architectures](https://doc.rust-lang.org/nightly/rustc/platform-support." +"html):\n" +" * x86, ARM, WebAssembly, ...\n" +" * Linux, Mac, Windows, ...\n" +"* Rust is used for a wide range of devices:\n" +" * firmware and boot loaders,\n" +" * smart displays,\n" +" * mobile phones,\n" +" * desktops,\n" +" * servers." msgstr "" -#: src/why-rust/modern.md:1 -msgid "# Modern Features" +#: src/welcome-day-1/what-is-rust.md:21 +msgid "Rust fits in the same area as C++:" msgstr "" -#: src/why-rust/modern.md:3 -msgid "Rust is built with all the experience gained in the last 40 years." +#: src/welcome-day-1/what-is-rust.md:23 +msgid "" +"* High flexibility.\n" +"* High level of control.\n" +"* Can be scaled down to very constrained devices like mobile phones.\n" +"* Has no runtime or garbage collection.\n" +"* Focuses on reliability and safety without sacrificing performance." msgstr "" -#: src/why-rust/modern.md:5 -msgid "## Language Features" +#: src/hello-world.md:1 +msgid "# Hello World!" msgstr "" -#: src/why-rust/modern.md:7 +#: src/hello-world.md:3 msgid "" -"* Enums and pattern matching.\n" -"* Generics.\n" -"* No overhead FFI." +"Let us jump into the simplest possible Rust program, a classic Hello World\n" +"program:" msgstr "" -#: src/why-rust/modern.md:11 -msgid "## Tooling" +#: src/hello-world.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" println!(\"Hello 🌍!\");\n" +"}\n" +"```" msgstr "" -#: src/why-rust/modern.md:13 -msgid "" -"* Great compiler errors.\n" -"* Built-in dependency manager.\n" -"* Built-in support for testing." +#: src/hello-world.md:12 +msgid "What you see:" msgstr "" -#: src/why-rust/modern.md:21 +#: src/hello-world.md:14 msgid "" -"* Remind people to read the errors --- many developers have gotten used to\n" -" ignore lengthly compiler output. The Rust compiler is significantly more\n" -" talkative than other compilers. It will often provide you with " -"_actionable_\n" -" feedback, ready to copy-paste into your code." +"* Functions are introduced with `fn`.\n" +"* Blocks are delimited by curly braces like in C and C++.\n" +"* The `main` function is the entry point of the program.\n" +"* Rust has hygienic macros, `println!` is an example of this.\n" +"* Rust strings are UTF-8 encoded and can contain any Unicode character." msgstr "" -#: src/why-rust/modern.md:26 +#: src/hello-world.md:22 msgid "" -"* The Rust standard library is small compared to languages like Java, " -"Python,\n" -" and Go. Rust does not come with several things you might consider standard " -"and\n" -" essential:" +"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 "" -#: src/why-rust/modern.md:30 +#: src/hello-world.md:27 msgid "" -" * a random number generator, but see [rand].\n" -" * support for SSL or TLS, but see [rusttls].\n" -" * support for JSON, but see [serde_json]." +"* Rust is very much like other languages in the C/C++/Java tradition. It is\n" +" imperative (not functional) and it doesn't try to reinvent things unless\n" +" absolutely necessary.\n" +"\n" +"* Rust is modern with full support for things like Unicode.\n" +"\n" +"* Rust uses macros for situations where you want to have a variable number " +"of\n" +" arguments (no function [overloading](basic-syntax/functions-interlude." +"md)).\n" +"\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)." msgstr "" -#: src/why-rust/modern.md:34 -msgid "" -" The reasoning behind this is that functionality in the standard library " -"cannot\n" -" go away, so it has to be very stable. For the examples above, the Rust\n" -" community is still working on finding the best solution --- and perhaps " -"there\n" -" isn't a single \"best solution\" for some of these things." +#: src/hello-world/small-example.md:1 +msgid "# Small Example" +msgstr "" + +#: src/hello-world/small-example.md:3 +msgid "Here is a small example program in Rust:" msgstr "" -#: src/why-rust/modern.md:39 +#: src/hello-world/small-example.md:5 msgid "" -" Rust comes with a built-in package manager in the form of Cargo and this " -"makes\n" -" it trivial to download and compile third-party crates. A consequence of " -"this\n" -" is that the standard library can be smaller." +"```rust,editable\n" +"fn main() { // Program entry point\n" +" let mut x: i32 = 6; // Mutable variable binding\n" +" print!(\"{x}\"); // Macro for printing, like printf\n" +" while x != 1 { // No parenthesis around expression\n" +" if x % 2 == 0 { // Math like in other languages\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +" print!(\" -> {x}\");\n" +" }\n" +" println!();\n" +"}\n" +"```" msgstr "" -#: src/why-rust/modern.md:43 +#: src/hello-world/small-example.md:23 msgid "" -" Discovering good third-party crates can be a problem. Sites like\n" -" help with this by letting you compare health metrics " -"for\n" -" crates to find a good and trusted one." +"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 "" -#: src/why-rust/modern.md:47 +#: src/hello-world/small-example.md:29 msgid "" -"[rand]: https://docs.rs/rand/\n" -"[rusttls]: https://docs.rs/rustls/\n" -"[serde_json]: https://docs.rs/serde_json/" +"* Explain that all variables are statically typed. Try removing `i32` to " +"trigger\n" +" type inference. Try with `i8` instead and trigger a runtime integer " +"overflow.\n" +"\n" +"* Change `let mut x` to `let x`, discuss the compiler error.\n" +"\n" +"* Show how `print!` gives a compilation error if the arguments don't match " +"the\n" +" format string.\n" +"\n" +"* Show how you need to use `{}` as a placeholder if you want to print an\n" +" expression which is more complex than just a single variable.\n" +"\n" +"* Show the students the standard library, show them how to search for `std::" +"fmt`\n" +" 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 "" -#: src/basic-syntax.md:1 -msgid "# Basic Syntax" +#: src/why-rust.md:1 +msgid "# Why Rust?" msgstr "" -#: src/basic-syntax.md:3 -msgid "Much of the Rust syntax will be familiar to you from C or C++:" +#: src/why-rust.md:3 +msgid "Some unique selling points of Rust:" msgstr "" -#: src/basic-syntax.md:5 +#: src/why-rust.md:5 msgid "" -"* Blocks and scopes are delimited by curly braces.\n" -"* Line comments are started with `//`, block comments are delimited by `/" -"* ...\n" -" */`.\n" -"* Keywords like `if` and `while` work the same.\n" -"* Variable assignment is done with `=`, comparison is done with `==`." +"* Compile time memory safety.\n" +"* Lack of undefined runtime behavior.\n" +"* Modern language features." msgstr "" -#: src/basic-syntax/scalar-types.md:1 -msgid "# Scalar Types" +#: src/why-rust.md:11 +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 "" -#: src/basic-syntax/scalar-types.md:3 +#: src/why-rust.md:14 msgid "" -"| | Types | " -"Literals |\n" -"|------------------------|--------------------------------------------|-------------------------------|\n" -"| Signed integers | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | " -"`-10`, `0`, `1_000`, `123i64` |\n" -"| Unsigned integers | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, " -"`123`, `10u16` |\n" -"| Floating point numbers | `f32`, `f64` | " -"`3.14`, `-10.0e20`, `2f32` |\n" -"| Strings | `&str` | " -"`\"foo\"`, `r#\"\\\\\"#` |\n" -"| Unicode scalar values | `char` | " -"`'a'`, `'α'`, `'∞'` |\n" -"| Byte strings | `&[u8]` | " -"`b\"abc\"`, `br#\" \" \"#` |\n" -"| Booleans | `bool` | " -"`true`, `false` |" +"* 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" +" have the memory unsafety issues. In addition, you get a modern language " +"with\n" +" constructs like pattern matching and built-in dependency management.\n" +"\n" +"* Experience with Java, Go, Python, JavaScript...: You get the same memory " +"safety\n" +" as in those languages, plus a similar high-level language feeling. In " +"addition\n" +" 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 "" -#: src/basic-syntax/scalar-types.md:13 -msgid "The types have widths as follows:" +#: src/why-rust/compile-time.md:1 +msgid "# Compile Time Guarantees" msgstr "" -#: src/basic-syntax/scalar-types.md:15 -msgid "" -"* `iN`, `uN`, and `fN` are _N_ bits wide,\n" -"* `isize` and `usize` are the width of a pointer,\n" -"* `char` is 32 bit wide,\n" -"* `bool` is 8 bit wide." +#: src/why-rust/compile-time.md:3 +msgid "Static memory management at compile time:" msgstr "" -#: src/basic-syntax/compound-types.md:1 -msgid "# Compound Types" +#: src/why-rust/compile-time.md:5 +msgid "" +"* No uninitialized variables.\n" +"* No memory leaks (_mostly_, see notes).\n" +"* No double-frees.\n" +"* No use-after-free.\n" +"* No `NULL` pointers.\n" +"* No forgotten locked mutexes.\n" +"* No data races between threads.\n" +"* No iterator invalidation." msgstr "" -#: src/basic-syntax/compound-types.md:3 +#: src/why-rust/compile-time.md:16 +msgid "" +"It is possible to produce memory leaks in (safe) Rust. Some examples\n" +"are:" +msgstr "" + +#: src/why-rust/compile-time.md:19 +msgid "" +"* You can for 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" +"* You can also accidentally create a [reference cycle] with `Rc` or\n" +" `Arc`.\n" +"* In fact, some will consider infinitely populating a collection a memory\n" +" leak and Rust does not protect from those." +msgstr "" + +#: src/why-rust/compile-time.md:28 +msgid "" +"For the purpose of this course, \"No memory leaks\" should be understood\n" +"as \"Pretty much no *accidental* memory leaks\"." +msgstr "" + +#: src/why-rust/runtime.md:1 +msgid "# Runtime Guarantees" +msgstr "" + +#: src/why-rust/runtime.md:3 +msgid "No undefined behavior at runtime:" +msgstr "" + +#: src/why-rust/runtime.md:5 +msgid "" +"* Array access is bounds checked.\n" +"* Integer overflow is defined." +msgstr "" + +#: src/why-rust/runtime.md:12 +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" +" semantics. By default, you get panics in debug mode (`cargo build`)\n" +" and wrap-around in release mode (`cargo build --release`).\n" +"\n" +"* Bounds checking cannot be disabled with a compiler flag. It can also\n" +" not be disabled directly with the `unsafe` keyword. However,\n" +" `unsafe` allows you to call functions such as `slice::get_unchecked`\n" +" which does not do bounds checking." +msgstr "" + +#: src/why-rust/modern.md:1 +msgid "# Modern Features" +msgstr "" + +#: src/why-rust/modern.md:3 +msgid "Rust is built with all the experience gained in the last 40 years." +msgstr "" + +#: src/why-rust/modern.md:5 +msgid "## Language Features" +msgstr "" + +#: src/why-rust/modern.md:7 +msgid "" +"* Enums and pattern matching.\n" +"* Generics.\n" +"* No overhead FFI.\n" +"* Zero-cost abstractions." +msgstr "" + +#: src/why-rust/modern.md:12 +msgid "## Tooling" +msgstr "" + +#: src/why-rust/modern.md:14 +msgid "" +"* Great compiler errors.\n" +"* Built-in dependency manager.\n" +"* Built-in support for testing.\n" +"* Excellent Language Server Protocol support." +msgstr "" + +#: src/why-rust/modern.md:23 +msgid "" +"* Zero-cost abstractions, similar to C++, means that you don't have to " +"'pay'\n" +" for higher-level programming constructs with memory or CPU. For example,\n" +" writing a loop using `for` should result in roughly the same low level\n" +" instructions as using the `.iter().fold()` construct.\n" +"\n" +"* It may be worth mentioning that Rust enums are 'Algebraic Data Types', " +"also\n" +" known as 'sum types', which allow the type system to express things like\n" +" `Option` and `Result`.\n" +"\n" +"* Remind people to read the errors --- many developers have gotten used to\n" +" ignore lengthy compiler output. The Rust compiler is significantly more\n" +" talkative than other compilers. It will often provide you with " +"_actionable_\n" +" feedback, ready to copy-paste into your code.\n" +"\n" +"* The Rust standard library is small compared to languages like Java, " +"Python,\n" +" and Go. Rust does not come with several things you might consider standard " +"and\n" +" essential:\n" +"\n" +" * a random number generator, but see [rand].\n" +" * support for SSL or TLS, but see [rusttls].\n" +" * support for JSON, but see [serde_json].\n" +"\n" +" The reasoning behind this is that functionality in the standard library " +"cannot\n" +" go away, so it has to be very stable. For the examples above, the Rust\n" +" community is still working on finding the best solution --- and perhaps " +"there\n" +" isn't a single \"best solution\" for some of these things.\n" +"\n" +" Rust comes with a built-in package manager in the form of Cargo and this " +"makes\n" +" it trivial to download and compile third-party crates. A consequence of " +"this\n" +" is that the standard library can be smaller.\n" +"\n" +" Discovering good third-party crates can be a problem. Sites like\n" +" help with this by letting you compare health metrics " +"for\n" +" crates to find a good and trusted one.\n" +" \n" +"* [rust-analyzer] is a well supported LSP implementation used in major\n" +" IDEs and text editors." +msgstr "" + +#: src/basic-syntax.md:1 +msgid "# Basic Syntax" +msgstr "" + +#: src/basic-syntax.md:3 +msgid "Much of the Rust syntax will be familiar to you from C, C++ or Java:" +msgstr "" + +#: src/basic-syntax.md:5 +msgid "" +"* Blocks and scopes are delimited by curly braces.\n" +"* Line comments are started with `//`, block comments are delimited by `/" +"* ...\n" +" */`.\n" +"* Keywords like `if` and `while` work the same.\n" +"* Variable assignment is done with `=`, comparison is done with `==`." +msgstr "" + +#: src/basic-syntax/scalar-types.md:1 +msgid "# Scalar Types" +msgstr "" + +#: src/basic-syntax/scalar-types.md:3 +msgid "" +"| | Types | " +"Literals |\n" +"|------------------------|--------------------------------------------|-------------------------------|\n" +"| Signed integers | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | " +"`-10`, `0`, `1_000`, `123i64` |\n" +"| Unsigned integers | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, " +"`123`, `10u16` |\n" +"| Floating point numbers | `f32`, `f64` | " +"`3.14`, `-10.0e20`, `2f32` |\n" +"| Strings | `&str` | " +"`\"foo\"`, `\"two\\nlines\"` |\n" +"| Unicode scalar values | `char` | " +"`'a'`, `'α'`, `'∞'` |\n" +"| Booleans | `bool` | " +"`true`, `false` |" +msgstr "" + +#: src/basic-syntax/scalar-types.md:12 +msgid "The types have widths as follows:" +msgstr "" + +#: 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" +"* `char` is 32 bit wide,\n" +"* `bool` is 8 bit wide." +msgstr "" + +#: src/basic-syntax/scalar-types.md:21 +msgid "There are a few syntaxes which are not shown above:" +msgstr "" + +#: 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 "" + +#: src/basic-syntax/compound-types.md:1 +msgid "# Compound Types" +msgstr "" + +#: src/basic-syntax/compound-types.md:3 msgid "" "| | Types | Literals " "|\n" @@ -2059,51 +2460,54 @@ msgid "" "```" msgstr "" -#: src/basic-syntax/compound-types.md:28 -msgid "" -"
\n" -" \n" -"Key points:\n" -" \n" -"Arrays:\n" -" \n" -"* Arrays have elements of the same type, `T`, and length, `N`, which is a " -"compile-time constant." -msgstr "" - -#: src/basic-syntax/compound-types.md:36 -msgid "* We can use literals to assign values to arrays." +#: src/basic-syntax/compound-types.md:32 +msgid "Arrays:" msgstr "" -#: src/basic-syntax/compound-types.md:38 +#: src/basic-syntax/compound-types.md:34 msgid "" +"* Arrays have elements of the same type, `T`, and length, `N`, which is a " +"compile-time constant.\n" +" Note that the length of the array is *part of its type*, which means that " +"`[u8; 3]` and\n" +" `[u8; 4]` are considered two different types.\n" +"\n" +"* We can use literals to assign values to arrays.\n" +"\n" "* In the main function, the print statement asks for the debug " -"implementation with the `?` format parameter: `{a}` gives the default " -"output, `{a:?}` gives the debug output." -msgstr "" - -#: src/basic-syntax/compound-types.md:40 -msgid "" +"implementation with the `?` format\n" +" parameter: `{}` gives the default output, `{:?}` gives the debug output. " +"We\n" +" could also have used `{a}` and `{a:?}` without specifying the value after " +"the\n" +" format string.\n" +"\n" "* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can " "be easier to read." msgstr "" -#: src/basic-syntax/compound-types.md:42 +#: src/basic-syntax/compound-types.md:47 msgid "Tuples:" msgstr "" -#: src/basic-syntax/compound-types.md:44 -msgid "* Like arrays, tuples have a fixed length." -msgstr "" - -#: src/basic-syntax/compound-types.md:46 -msgid "* Tuples group together values of different types into a compound type." -msgstr "" - -#: src/basic-syntax/compound-types.md:48 +#: src/basic-syntax/compound-types.md:49 msgid "" -"* Fields that can be accessed by the period and the index of the value, e.g. " -"`t.0`, `t.1`." +"* Like arrays, tuples have a fixed length.\n" +"\n" +"* Tuples group together values of different types into a compound type.\n" +"\n" +"* Fields of a tuple can be accessed by the period and the index of the " +"value, e.g. `t.0`, `t.1`.\n" +"\n" +"* The empty tuple `()` is also known as the \"unit type\". It is both a " +"type, and\n" +" the only valid value of that type - that is to say both the type and its " +"value\n" +" are expressed as `()`. It is used to indicate, for example, that a " +"function or\n" +" expression has no return value, as we'll see in a future slide. \n" +" * You can think of it as `void` that can be familiar to you from other \n" +" programming languages." msgstr "" #: src/basic-syntax/references.md:1 @@ -2127,18 +2531,35 @@ msgid "" msgstr "" #: src/basic-syntax/references.md:14 -msgid "Some differences from C++:" +msgid "Some notes:" msgstr "" #: src/basic-syntax/references.md:16 msgid "" -"* We must dereference `ref_x` when assigning to it, similar to C pointers,\n" +"* 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 `count_ones`).\n" +" methods (try `ref_x.count_ones()`).\n" "* References that are declared as `mut` can be bound to different values " "over their lifetime." msgstr "" +#: src/basic-syntax/references.md:21 +msgid "" +"
\n" +"Key points:" +msgstr "" + +#: src/basic-syntax/references.md:24 +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 "" + #: src/basic-syntax/references-dangling.md:1 msgid "# Dangling References" msgstr "" @@ -2182,11 +2603,8 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" -" println!(\"a: {a:?}\");" -msgstr "" - -#: src/basic-syntax/slices.md:10 -msgid "" +" println!(\"a: {a:?}\");\n" +"\n" " let s: &[i32] = &a[2..4];\n" " println!(\"s: {s:?}\");\n" "}\n" @@ -2202,26 +2620,30 @@ msgstr "" #: src/basic-syntax/slices.md:20 msgid "" "* We create a slice by borrowing `a` and specifying the starting and ending " -"indexes in brackets." -msgstr "" - -#: src/basic-syntax/slices.md:22 -msgid "" -"* If the slice starts at index 0, Rust’s range syntax means we can drop the " -"starting index. \n" +"indexes in brackets.\n" +"\n" +"* If the slice starts at index 0, Rust’s range syntax allows us to drop the " +"starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are " +"identical.\n" " \n" "* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are " -"equal." -msgstr "" - -#: src/basic-syntax/slices.md:26 -msgid "" -"* `s` is a reference to a slice of `i32`s. Notice that the type of `s` no " -"longer mentions the array length. This allows us to performing computations " -"on slices of different sizes.\n" +"identical.\n" +"\n" +"* To easily create a slice of the full array, we can therefore use " +"`&a[..]`.\n" +"\n" +"* `s` is a reference to a slice of `i32`s. Notice that the type of `s` " +"(`&[i32]`) no longer mentions the array length. This allows us to perform " +"computation on slices of different sizes.\n" " \n" "* Slices always borrow from another object. In this example, `a` has to " -"remain 'alive' so we can take a slice from it. " +"remain 'alive' (in scope) for at least as long as our slice. \n" +" \n" +"* The question about modifying `a[3]` can spark an interesting discussion, " +"but the answer is that for memory safety reasons\n" +" you cannot do it through `a` after you created a slice, but you can read " +"the data from both `a` and `s` safely. \n" +" More details will be explained in the borrow checker section." msgstr "" #: src/basic-syntax/string-slices.md:1 @@ -2236,55 +2658,59 @@ msgstr "" msgid "" "```rust,editable\n" "fn main() {\n" -" let s1: &str = \"Hello\";\n" -" println!(\"s1: {s1}\");" -msgstr "" - -#: src/basic-syntax/string-slices.md:10 -msgid "" +" let s1: &str = \"World\";\n" +" println!(\"s1: {s1}\");\n" +"\n" " let mut s2: String = String::from(\"Hello \");\n" " println!(\"s2: {s2}\");\n" " s2.push_str(s1);\n" " println!(\"s2: {s2}\");\n" +" \n" +" let s3: &str = &s2[6..];\n" +" println!(\"s3: {s3}\");\n" "}\n" "```" msgstr "" -#: src/basic-syntax/string-slices.md:17 +#: src/basic-syntax/string-slices.md:20 msgid "Rust terminology:" msgstr "" -#: src/basic-syntax/string-slices.md:19 +#: src/basic-syntax/string-slices.md:22 msgid "" "* `&str` an immutable reference to a string slice.\n" "* `String` a mutable string buffer." msgstr "" -#: src/basic-syntax/string-slices.md:24 +#: src/basic-syntax/string-slices.md:27 msgid "" "* `&str` introduces a string slice, which is an immutable reference to UTF-8 " -"encoded string data stored in a block of memory. String literals " -"(`”Hello”`), are stored in the program’s binary." -msgstr "" - -#: src/basic-syntax/string-slices.md:26 -msgid "" +"encoded string data \n" +" stored in a block of memory. String literals (`”Hello”`), are stored in " +"the program’s binary.\n" +"\n" "* Rust’s `String` type is a wrapper around a vector of bytes. As with a " -"`Vec`, it is mutable and owned." -msgstr "" - -#: src/basic-syntax/string-slices.md:28 -msgid "" -"* `String::from` creates a string from a string literal; `String::new` " -"creates a new empty string, to which string data can be added using the " -"`to_string` method." -msgstr "" - -#: src/basic-syntax/string-slices.md:30 -msgid "" -"* The `push_str` method appends a string slice to the string.\n" +"`Vec`, it is owned.\n" +" \n" +"* As with many other types `String::from()` creates a string from a string " +"literal; `String::new()` \n" +" creates a new empty string, to which string data can be added using the " +"`push()` and `push_str()` methods.\n" +"\n" +"* The `format!()` macro is a convenient way to generate an owned string from " +"dynamic values. It \n" +" accepts the same format specification as `println!()`.\n" +" \n" +"* You can borrow `&str` slices from `String` via `&` and optionally range " +"selection.\n" " \n" -"
" +"* For C++ programmers: think of `&str` as `const char*` from C++, but the " +"one that always points \n" +" to a valid string in memory. Rust `String` is a rough equivalent of `std::" +"string` from C++ \n" +" (main difference: it can only contain UTF-8 encoded bytes and will never " +"use a small-string optimization).\n" +" " msgstr "" #: src/basic-syntax/functions.md:1 @@ -2301,41 +2727,94 @@ msgstr "" 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(n: u32, divisor: u32) -> bool {\n" +" if divisor == 0 {\n" +" return false;\n" +" }\n" +" n % divisor == 0\n" +"}\n" +"\n" +"fn fizzbuzz(n: u32) -> String {\n" +" let fizz = if is_divisible(n, 3) { \"fizz\" } else { \"\" };\n" +" let buzz = if is_divisible(n, 5) { \"buzz\" } else { \"\" };\n" +" if fizz.is_empty() && buzz.is_empty() {\n" +" return format!(\"{n}\");\n" +" }\n" +" format!(\"{fizz}{buzz}\")\n" +"}\n" +"\n" +"fn print_fizzbuzz_to(n: u32) {\n" +" for i in 1..=n {\n" +" println!(\"{}\", fizzbuzz(i));\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/functions.md:35 +msgid "" +"* We refer in `main` to a function written below. Neither forward " +"declarations nor headers are necessary. \n" +"* Declaration parameters are followed by a type (the reverse of some " +"programming languages), then a return type.\n" +"* The last expression in a function body (or any block) becomes the return " +"value. Simply omit the `;` 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 `print_fizzbuzz_to()` contains " +"`=n`, which causes it to include the upper bound." +msgstr "" + +#: src/basic-syntax/rustdoc.md:1 +msgid "# Rustdoc" +msgstr "" + +#: src/basic-syntax/rustdoc.md:3 +msgid "" +"All language items in Rust can be documented using special `///` syntax." msgstr "" -#: src/basic-syntax/functions.md:10 +#: src/basic-syntax/rustdoc.md:5 msgid "" +"```rust,editable\n" +"/// Determine whether the first argument is divisible by the second " +"argument.\n" +"///\n" +"/// If the second argument is zero, the result is false.\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 is the return value\n" -"}" +" lhs % rhs == 0 // The last expression in a block is the return " +"value\n" +"}\n" +"```" msgstr "" -#: src/basic-syntax/functions.md:17 +#: src/basic-syntax/rustdoc.md:17 msgid "" -"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" -"}" +"The contents are treated as Markdown. All published Rust library crates are\n" +"automatically documented at [`docs.rs`](https://docs.rs) using the\n" +"[rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It " +"is\n" +"idiomatic to document all public items in an API using this pattern." msgstr "" -#: src/basic-syntax/functions.md:26 +#: src/basic-syntax/rustdoc.md:24 msgid "" -"fn fizzbuzz_to(n: u32) { // `-> ()` is normally omitted\n" -" for n in 1..=n {\n" -" fizzbuzz(n);\n" -" }\n" -"}\n" -"```" +"* Show students the generated docs for the `rand` crate at\n" +" [`docs.rs/rand`](https://docs.rs/rand).\n" +"\n" +"* This course does not include rustdoc on slides, just to save space, but " +"in\n" +" real code they should be present.\n" +"\n" +"* Inner doc comments are discussed later (in the page on modules) and need " +"not\n" +" be addressed here." msgstr "" #: src/basic-syntax/methods.md:1 src/methods.md:1 @@ -2344,9 +2823,9 @@ msgstr "" #: src/basic-syntax/methods.md:3 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 "" #: src/basic-syntax/methods.md:6 @@ -2355,27 +2834,18 @@ msgid "" "struct Rectangle {\n" " width: u32,\n" " height: u32,\n" -"}" -msgstr "" - -#: src/basic-syntax/methods.md:12 -msgid "" +"}\n" +"\n" "impl Rectangle {\n" " fn area(&self) -> u32 {\n" " self.width * self.height\n" -" }" -msgstr "" - -#: src/basic-syntax/methods.md:17 -msgid "" +" }\n" +"\n" " fn inc_width(&mut self, delta: u32) {\n" " self.width += delta;\n" " }\n" -"}" -msgstr "" - -#: src/basic-syntax/methods.md:22 -msgid "" +"}\n" +"\n" "fn main() {\n" " let mut rect = Rectangle { width: 10, height: 5 };\n" " println!(\"old area: {}\", rect.area());\n" @@ -2391,6 +2861,20 @@ msgid "" "class." msgstr "" +#: 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 msgid "# Function Overloading" msgstr "" @@ -2418,11 +2902,8 @@ msgid "" "```rust,editable\n" "fn pick_one(a: T, b: T) -> T {\n" " if std::process::id() % 2 == 0 { a } else { b }\n" -"}" -msgstr "" - -#: src/basic-syntax/functions-interlude.md:19 -msgid "" +"}\n" +"\n" "fn main() {\n" " println!(\"coin toss: {}\", pick_one(\"heads\", \"tails\"));\n" " println!(\"cash prize: {}\", pick_one(500, 1000));\n" @@ -2430,6 +2911,18 @@ msgid "" "```" msgstr "" +#: src/basic-syntax/functions-interlude.md:27 +msgid "" +"* When using generics, the standard library's `Into` can provide a kind " +"of limited\n" +" polymorphism on argument types. We will see more details in a later " +"section." +msgstr "" + +#: src/basic-syntax/functions-interlude.md:30 +msgid "" +msgstr "" + #: src/exercises/day-1/morning.md:1 msgid "# Day 1: Morning Exercises" msgstr "" @@ -2439,11 +2932,10 @@ msgid "In these exercises, we will explore two parts of Rust:" msgstr "" #: src/exercises/day-1/morning.md:5 -msgid "* Implicit conversions between types." -msgstr "" - -#: src/exercises/day-1/morning.md:7 -msgid "* Arrays and `for` loops." +msgid "" +"* Implicit conversions between types.\n" +"\n" +"* Arrays and `for` loops." msgstr "" #: src/exercises/day-1/morning.md:11 @@ -2455,11 +2947,9 @@ msgid "" "* Use a local Rust installation, if possible. This way you can get\n" " auto-completion in your editor. See the page about [Using Cargo] for " "details\n" -" on installing Rust." -msgstr "" - -#: src/exercises/day-1/morning.md:17 -msgid "* Alternatively, use the Rust Playground." +" on installing Rust.\n" +"\n" +"* Alternatively, use the Rust Playground." msgstr "" #: src/exercises/day-1/morning.md:19 @@ -2471,20 +2961,14 @@ 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/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 msgid "" "After looking at the exercises, you can look at the [solutions] provided." msgstr "" -#: src/exercises/day-1/morning.md:24 src/exercises/day-2/morning.md:13 -#: src/exercises/day-3/morning.md:9 src/exercises/day-4/morning.md:14 -msgid "[solutions]: solutions-morning.md" -msgstr "" - -#: src/exercises/day-1/morning.md:26 -msgid "[Using Cargo]: ../../cargo.md" -msgstr "" - #: src/exercises/day-1/implicit-conversions.md:1 msgid "# Implicit Conversions" msgstr "" @@ -2501,18 +2985,12 @@ msgid "" "```rust,editable,compile_fail\n" "fn multiply(x: i16, y: i16) -> i16 {\n" " x * y\n" -"}" -msgstr "" - -#: src/exercises/day-1/implicit-conversions.md:11 -msgid "" +"}\n" +"\n" "fn main() {\n" " let x: i8 = 15;\n" -" let y: i16 = 1000;" -msgstr "" - -#: src/exercises/day-1/implicit-conversions.md:15 -msgid "" +" let y: i16 = 1000;\n" +"\n" " println!(\"{x} * {y} = {}\", multiply(x, y));\n" "}\n" "```" @@ -2539,15 +3017,19 @@ msgid "" msgstr "" #: src/exercises/day-1/implicit-conversions.md:30 -msgid "1. Execute the above program and look at the compiler error." -msgstr "" - -#: src/exercises/day-1/implicit-conversions.md:32 -msgid "2. Update the code above to use `into()` to do the conversion." +msgid "" +"The same applies for your own `From` implementations for your own types, so " +"it is\n" +"sufficient to only implement `From` to get a respective `Into` " +"implementation automatically." msgstr "" -#: src/exercises/day-1/implicit-conversions.md:34 +#: src/exercises/day-1/implicit-conversions.md:33 msgid "" +"1. Execute the above program and look at the compiler error.\n" +"\n" +"2. Update the code above to use `into()` to do the conversion.\n" +"\n" "3. Change the types of `x` and `y` to other things (such as `f32`, `bool`,\n" " `i128`) to see which types you can convert to which other types. Try\n" " converting small types to big types and the other way around. Check the\n" @@ -2556,13 +3038,6 @@ msgid "" " the pairs you check." msgstr "" -#: src/exercises/day-1/implicit-conversions.md:40 -msgid "" -"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" -"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" -"[3]: https://en.cppreference.com/w/cpp/language/implicit_conversion" -msgstr "" - #: src/exercises/day-1/for-loops.md:1 msgid "# Arrays and `for` Loops" msgstr "" @@ -2609,11 +3084,8 @@ msgid "" " for n in array {\n" " print!(\" {n}\");\n" " }\n" -" println!();" -msgstr "" - -#: src/exercises/day-1/for-loops.md:30 -msgid "" +" println!();\n" +"\n" " print!(\"Iterating over range:\");\n" " for i in 0..3 {\n" " print!(\" {}\", array[i]);\n" @@ -2655,47 +3127,30 @@ msgid "" "functions:" msgstr "" -#: src/exercises/day-1/for-loops.md:52 src/exercises/day-1/book-library.md:20 -#: src/exercises/day-2/health-statistics.md:13 +#: src/exercises/day-1/for-loops.md:52 msgid "" "```rust,should_panic\n" "// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]" -msgstr "" - -#: src/exercises/day-1/for-loops.md:56 -msgid "" +"#![allow(unused_variables, dead_code)]\n" +"\n" "fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" " unimplemented!()\n" -"}" -msgstr "" - -#: src/exercises/day-1/for-loops.md:60 -msgid "" +"}\n" +"\n" "fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" " unimplemented!()\n" -"}" -msgstr "" - -#: src/exercises/day-1/for-loops.md:64 -msgid "" +"}\n" +"\n" "fn main() {\n" " let matrix = [\n" " [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" " [201, 202, 203],\n" " [301, 302, 303],\n" -" ];" -msgstr "" - -#: src/exercises/day-1/for-loops.md:71 -#: src/exercises/day-1/solutions-morning.md:70 -msgid "" +" ];\n" +"\n" " println!(\"matrix:\");\n" -" pretty_print(&matrix);" -msgstr "" - -#: src/exercises/day-1/for-loops.md:74 -msgid "" +" pretty_print(&matrix);\n" +"\n" " let transposed = transpose(matrix);\n" " println!(\"transposed:\");\n" " pretty_print(&transposed);\n" @@ -2721,6 +3176,12 @@ msgid "" "implementation." msgstr "" +#: src/exercises/day-1/for-loops.md:92 +msgid "" +"The solution and the answer to the bonus section are available in the \n" +"[Solution](solutions-morning.md#arrays-and-for-loops) section." +msgstr "" + #: src/basic-syntax/variables.md:1 msgid "# Variables" msgstr "" @@ -2747,7 +3208,7 @@ msgstr "" #: src/basic-syntax/variables.md:17 msgid "" "* Due to type inference the `i32` is optional. We will gradually show the " -"types less and less as the type progresses.\n" +"types less and less as the course progresses.\n" "* Note that since `println!` is a macro, `x` is not moved, even using the " "function like syntax of `println!(\"x: {}\", x)`" msgstr "" @@ -2765,25 +3226,16 @@ msgid "" "```rust,editable\n" "fn takes_u32(x: u32) {\n" " println!(\"u32: {x}\");\n" -"}" -msgstr "" - -#: src/basic-syntax/type-inference.md:10 -msgid "" +"}\n" +"\n" "fn takes_i8(y: i8) {\n" " println!(\"i8: {y}\");\n" -"}" -msgstr "" - -#: src/basic-syntax/type-inference.md:14 -msgid "" +"}\n" +"\n" "fn main() {\n" " let x = 10;\n" -" let y = 20;" -msgstr "" - -#: src/basic-syntax/type-inference.md:18 -msgid "" +" let y = 20;\n" +"\n" " takes_u32(x);\n" " takes_i8(y);\n" " // takes_u32(y);\n" @@ -2799,30 +3251,36 @@ msgstr "" #: src/basic-syntax/type-inference.md:28 msgid "" +"It is very important to emphasize that variables declared like this are not " +"of some sort of dynamic \"any type\" that can\n" +"hold any data. The machine code generated by such declaration is identical " +"to the explicit declaration of a type.\n" +"The compiler does the job for us and helps us write more concise code." +msgstr "" + +#: src/basic-syntax/type-inference.md:32 +msgid "" "The following code tells the compiler to copy into a certain generic " "container without the code ever explicitly specifying the contained type, " "using `_` as a placeholder:" msgstr "" -#: src/basic-syntax/type-inference.md:30 +#: src/basic-syntax/type-inference.md:34 msgid "" "```rust,editable\n" "fn main() {\n" " let mut v = Vec::new();\n" " v.push((10, false));\n" " v.push((20, true));\n" -" println!(\"v: {v:?}\");" -msgstr "" - -#: src/basic-syntax/type-inference.md:37 -msgid "" +" println!(\"v: {v:?}\");\n" +"\n" " let vv = v.iter().collect::>();\n" " println!(\"vv: {vv:?}\");\n" "}\n" "```" msgstr "" -#: src/basic-syntax/type-inference.md:42 +#: src/basic-syntax/type-inference.md:46 msgid "" "[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator." "html#method.collect) relies on `FromIterator`, which [`HashSet`](https://doc." @@ -2849,11 +3307,8 @@ msgstr "" msgid "" "```rust,editable\n" "const DIGEST_SIZE: usize = 3;\n" -"const ZERO: Option = Some(42);" -msgstr "" - -#: src/basic-syntax/static-and-const.md:13 -msgid "" +"const ZERO: Option = Some(42);\n" +"\n" "fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {\n" " let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];\n" " for (idx, &b) in text.as_bytes().iter().enumerate() {\n" @@ -2861,11 +3316,8 @@ msgid "" "wrapping_add(b);\n" " }\n" " digest\n" -"}" -msgstr "" - -#: src/basic-syntax/static-and-const.md:21 -msgid "" +"}\n" +"\n" "fn main() {\n" " let digest = compute_digest(\"Hello\");\n" " println!(\"Digest: {digest:?}\");\n" @@ -2888,11 +3340,8 @@ msgstr "" #: src/basic-syntax/static-and-const.md:33 msgid "" "```rust,editable\n" -"static BANNER: &str = \"Welcome to RustOS 3.14\";" -msgstr "" - -#: src/basic-syntax/static-and-const.md:36 -msgid "" +"static BANNER: &str = \"Welcome to RustOS 3.14\";\n" +"\n" "fn main() {\n" " println!(\"{BANNER}\");\n" "}\n" @@ -2903,7 +3352,8 @@ msgstr "" msgid "" "As noted in the [Rust RFC Book][1], these are not inlined upon use and have " "an actual associated memory location. This is useful for unsafe and " -"embedded code, and have a `'static` lifetime." +"embedded code, and the variable lives through the entirety of the program " +"execution." msgstr "" #: src/basic-syntax/static-and-const.md:44 @@ -2921,10 +3371,6 @@ msgid "" "but it is helpful and safer than using a static." msgstr "" -#: src/basic-syntax/static-and-const.md:54 -msgid "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" -msgstr "" - #: src/basic-syntax/scopes-shadowing.md:1 msgid "# Scopes and Shadowing" msgstr "" @@ -2941,25 +3387,16 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let a = 10;\n" -" println!(\"before: {a}\");" -msgstr "" - -#: src/basic-syntax/scopes-shadowing.md:11 -msgid "" +" println!(\"before: {a}\");\n" +"\n" " {\n" " let a = \"hello\";\n" -" println!(\"inner scope: {a}\");" -msgstr "" - -#: src/basic-syntax/scopes-shadowing.md:15 -msgid "" +" println!(\"inner scope: {a}\");\n" +"\n" " let a = true;\n" " println!(\"shadowed in inner scope: {a}\");\n" -" }" -msgstr "" - -#: src/basic-syntax/scopes-shadowing.md:19 -msgid "" +" }\n" +"\n" " println!(\"after: {a}\");\n" "}\n" "```" @@ -2967,6 +3404,10 @@ msgstr "" #: src/basic-syntax/scopes-shadowing.md:25 msgid "" +"* Definition: Shadowing is different from mutation, because after shadowing " +"both variable's memory locations exist at the same time. Both are available " +"under the same name, depending where you use it in the code. \n" +"* A shadowing variable can have a different type. \n" "* Shadowing looks obscure at first, but is convenient for holding on to " "values after `.unwrap()`.\n" "* The following code demonstrates why the compiler can't simply reuse memory " @@ -2974,7 +3415,7 @@ msgid "" "does not change." msgstr "" -#: src/basic-syntax/scopes-shadowing.md:28 +#: src/basic-syntax/scopes-shadowing.md:30 msgid "" "```rust,editable\n" "fn main() {\n" @@ -3029,11 +3470,8 @@ msgid "" " * Values have fixed sizes known at compile time.\n" " * Extremely fast: just move a stack pointer.\n" " * Easy to manage: follows function calls.\n" -" * Great memory locality." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:9 -msgid "" +" * Great memory locality.\n" +"\n" "* Heap: Storage of values outside of function calls.\n" " * Values have dynamic sizes determined at runtime.\n" " * Slightly slower than the stack: some book-keeping needed.\n" @@ -3093,20 +3531,32 @@ msgstr "" #: src/memory-management/stack.md:28 msgid "" "* Mention that a `String` is backed by a `Vec`, so it has a capacity and " -"length and can grow if mutable via reallocation on the heap." -msgstr "" - -#: src/memory-management/stack.md:30 -msgid "" +"length and can grow if mutable via reallocation on the heap.\n" +"\n" "* If students ask about it, you can mention that the underlying memory is " "heap allocated using the [System Allocator] and custom allocators can be " -"implemented using the [Allocator API]" -msgstr "" - -#: src/memory-management/stack.md:34 -msgid "" -"[System Allocator]: https://doc.rust-lang.org/std/alloc/struct.System.html\n" -"[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html" +"implemented using the [Allocator API]\n" +"\n" +"* We can inspect the memory layout with `unsafe` code. However, you should " +"point out that this is rightfully unsafe!\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could " +"lead to\n" +" // undefined behavior.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::" +"transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = " +"{capacity}\");\n" +" }\n" +" }\n" +" ```" msgstr "" #: src/memory-management/manual.md:1 @@ -3252,7365 +3702,12893 @@ msgstr "" msgid "Memory management in Rust is a mix:" msgstr "" -#: src/memory-management/rust.md:5 -msgid "" -"* Safe and correct like Java, but without a garbage collector.\n" -"* Depending on which abstraction (or combination of abstractions) you " -"choose, can be a single unique pointer, reference counted, or atomically " -"reference counted.\n" -"* Scope-based like C++, but the compiler enforces full adherence.\n" -"* A Rust user can choose the right abstraction for the situation, some even " -"have no cost at runtime like C." +#: src/memory-management/rust.md:5 +msgid "" +"* Safe and correct like Java, but without a garbage collector.\n" +"* Depending on which abstraction (or combination of abstractions) you " +"choose, can be a single unique pointer, reference counted, or atomically " +"reference counted.\n" +"* Scope-based like C++, but the compiler enforces full adherence.\n" +"* A Rust user can choose the right abstraction for the situation, some even " +"have no cost at runtime like C." +msgstr "" + +#: src/memory-management/rust.md:10 +msgid "It achieves this by modeling _ownership_ explicitly." +msgstr "" + +#: src/memory-management/rust.md:14 +msgid "" +"* If asked how at this point, you can mention that in Rust this is usually " +"handled by RAII wrapper types such as [Box], [Vec], [Rc], or [Arc]. These " +"encapsulate ownership and memory allocation via various means, and prevent " +"the potential errors in C.\n" +"\n" +"* You may be asked about destructors here, the [Drop] trait is the Rust " +"equivalent." +msgstr "" + +#: src/memory-management/comparison.md:1 +msgid "# Comparison" +msgstr "" + +#: src/memory-management/comparison.md:3 +msgid "Here is a rough comparison of the memory management techniques." +msgstr "" + +#: src/memory-management/comparison.md:5 +msgid "## Pros of Different Memory Management Techniques" +msgstr "" + +#: src/memory-management/comparison.md:7 +msgid "" +"* Manual like C:\n" +" * No runtime overhead.\n" +"* Automatic like Java:\n" +" * Fully automatic.\n" +" * Safe and correct.\n" +"* Scope-based like C++:\n" +" * Partially automatic.\n" +" * No runtime overhead.\n" +"* Compiler-enforced scope-based like Rust:\n" +" * Enforced by compiler.\n" +" * No runtime overhead.\n" +" * Safe and correct." +msgstr "" + +#: src/memory-management/comparison.md:20 +msgid "## Cons of Different Memory Management Techniques" +msgstr "" + +#: src/memory-management/comparison.md:22 +msgid "" +"* Manual like C:\n" +" * Use-after-free.\n" +" * Double-frees.\n" +" * Memory leaks.\n" +"* Automatic like Java:\n" +" * Garbage collection pauses.\n" +" * Destructor delays.\n" +"* Scope-based like C++:\n" +" * Complex, opt-in by programmer.\n" +" * Potential for use-after-free.\n" +"* Compiler-enforced and scope-based like Rust:\n" +" * Some upfront complexity.\n" +" * Can reject valid programs." +msgstr "" + +#: src/ownership.md:1 +msgid "# Ownership" +msgstr "" + +#: src/ownership.md:3 +msgid "" +"All variable bindings have a _scope_ where they are valid and it is an error " +"to\n" +"use a variable outside its scope:" +msgstr "" + +#: src/ownership.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" {\n" +" let p = Point(3, 4);\n" +" println!(\"x: {}\", p.0);\n" +" }\n" +" println!(\"y: {}\", p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership.md:18 +msgid "" +"* At the end of the scope, the variable is _dropped_ and the data is freed.\n" +"* A destructor can run here to free up resources.\n" +"* We say that the variable _owns_ the value." +msgstr "" + +#: src/ownership/move-semantics.md:1 +msgid "# Move Semantics" +msgstr "" + +#: src/ownership/move-semantics.md:3 +msgid "An assignment will transfer ownership between variables:" +msgstr "" + +#: src/ownership/move-semantics.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Hello!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/move-semantics.md:14 +msgid "" +"* The assignment of `s1` to `s2` transfers ownership.\n" +"* The data was _moved_ from `s1` and `s1` is no longer accessible.\n" +"* When `s1` goes out of scope, nothing happens: it has no ownership.\n" +"* When `s2` goes out of scope, the string data is freed.\n" +"* There is always _exactly_ one variable binding which owns a value." +msgstr "" + +#: src/ownership/move-semantics.md:22 +msgid "" +"* Mention that this is the opposite of the defaults in C++, which copies by " +"value unless you use `std::move` (and the move constructor is defined!).\n" +"\n" +"* In Rust, clones are explicit (by using `clone`)." +msgstr "" + +#: src/ownership/moved-strings-rust.md:1 +msgid "# Moved Strings in Rust" +msgstr "" + +#: src/ownership/moved-strings-rust.md:3 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Rust\");\n" +" let s2: String = s1;\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:10 +msgid "" +"* The heap data from `s1` is reused for `s2`.\n" +"* When `s1` goes out of scope, nothing happens (it has been moved from)." +msgstr "" + +#: src/ownership/moved-strings-rust.md:13 +msgid "Before move to `s2`:" +msgstr "" + +#: src/ownership/moved-strings-rust.md:15 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| R | u | s | t | :\n" +": | len | 4 | : : +----+----+----+----+ :\n" +": | capacity | 4 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - -'\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:30 +msgid "After move to `s2`:" +msgstr "" + +#: src/ownership/moved-strings-rust.md:32 +#, fuzzy +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 \"(inaccessible)\" : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" +": | len | 4 | : | : +----+----+----+----+ :\n" +": | capacity | 4 | : | : :\n" +": +-----------+-------+ : | : :\n" +": : | `- - - - - - - - - - - - - -'\n" +": s2 : |\n" +": +-----------+-------+ : |\n" +": | ptr | o---+---+--'\n" +": | len | 4 | :\n" +": | capacity | 4 | :\n" +": +-----------+-------+ :\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" +"```bob\n" +" Stak Bunke\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | a | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" + +#: src/ownership/double-free-modern-cpp.md:1 +msgid "# Double Frees in Modern C++" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:3 +msgid "Modern C++ solves this differently:" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:5 +msgid "" +"```c++\n" +"std::string s1 = \"Cpp\";\n" +"std::string s2 = s1; // Duplicate the data in s1.\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:10 +msgid "" +"* The heap data from `s1` is duplicated and `s2` gets its own independent " +"copy.\n" +"* When `s1` and `s2` go out of scope, they each free their own memory." +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:13 +msgid "Before copy-assignment:" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:16 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:30 +msgid "After copy-assignment:" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:32 +#, fuzzy +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : : :\n" +": s2 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+-----+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" +"```bob\n" +" Stak Bunke\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | a | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" + +#: src/ownership/moves-function-calls.md:1 +msgid "# Moves in Function Calls" +msgstr "" + +#: src/ownership/moves-function-calls.md:3 +msgid "" +"When you pass a value to a function, the value is assigned to the function\n" +"parameter. This transfers ownership:" +msgstr "" + +#: src/ownership/moves-function-calls.md:6 +msgid "" +"```rust,editable\n" +"fn say_hello(name: String) {\n" +" println!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let name = String::from(\"Alice\");\n" +" say_hello(name);\n" +" // say_hello(name);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:20 +msgid "" +"* With the first call to `say_hello`, `main` gives up ownership of `name`. " +"Afterwards, `name` cannot be used anymore within `main`.\n" +"* The heap memory allocated for `name` will be freed at the end of the " +"`say_hello` function.\n" +"* `main` can retain ownership if it passes `name` as a reference (`&name`) " +"and if `say_hello` accepts a reference as a parameter.\n" +"* Alternatively, `main` can pass a clone of `name` in the first call (`name." +"clone()`).\n" +"* Rust makes it harder than C++ to inadvertently create copies by making " +"move semantics the default, and by forcing programmers to make clones " +"explicit." +msgstr "" + +#: src/ownership/copy-clone.md:1 +msgid "# Copying and Cloning" +msgstr "" + +#: src/ownership/copy-clone.md:3 +msgid "" +"While move semantics are the default, certain types are copied by default:" +msgstr "" + +#: src/ownership/copy-clone.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = 42;\n" +" let y = x;\n" +" println!(\"x: {x}\");\n" +" println!(\"y: {y}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:14 +msgid "These types implement the `Copy` trait." +msgstr "" + +#: src/ownership/copy-clone.md:16 +msgid "You can opt-in your own types to use copy semantics:" +msgstr "" + +#: src/ownership/copy-clone.md:18 +msgid "" +"```rust,editable\n" +"#[derive(Copy, Clone, Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = p1;\n" +" println!(\"p1: {p1:?}\");\n" +" println!(\"p2: {p2:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:30 +msgid "" +"* After the assignment, both `p1` and `p2` own their own data.\n" +"* We can also use `p1.clone()` to explicitly copy the data." +msgstr "" + +#: src/ownership/copy-clone.md:35 +msgid "Copying and cloning are not the same thing:" +msgstr "" + +#: src/ownership/copy-clone.md:37 +msgid "" +"* Copying refers to bitwise copies of memory regions and does not work on " +"arbitrary objects.\n" +"* Copying does not allow for custom logic (unlike copy constructors in C+" +"+).\n" +"* Cloning is a more general operation and also allows for custom behavior by " +"implementing the `Clone` trait.\n" +"* Copying does not work on types that implement the `Drop` trait." +msgstr "" + +#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 +msgid "In the above example, try the following:" +msgstr "" + +#: src/ownership/copy-clone.md:44 +msgid "" +"* Add a `String` field to `struct Point`. It will not compile because " +"`String` is not a `Copy` type.\n" +"* Remove `Copy` from the `derive` attribute. The compiler error is now in " +"the `println!` for `p1`.\n" +"* Show that it works if you clone `p1` instead." +msgstr "" + +#: src/ownership/copy-clone.md:48 +msgid "" +"If students ask about `derive`, it is sufficient to say that this is a way " +"to generate code in Rust\n" +"at compile time. In this case the default implementations of `Copy` and " +"`Clone` traits are generated." +msgstr "" + +#: src/ownership/borrowing.md:1 +msgid "# Borrowing" +msgstr "" + +#: src/ownership/borrowing.md:3 +msgid "" +"Instead of transferring ownership when calling a function, you can let a\n" +"function _borrow_ the value:" +msgstr "" + +#: src/ownership/borrowing.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn add(p1: &Point, p2: &Point) -> Point {\n" +" Point(p1.0 + p2.0, p1.1 + p2.1)\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/borrowing.md:22 +msgid "" +"* The `add` function _borrows_ two points and returns a new point.\n" +"* The caller retains ownership of the inputs." +msgstr "" + +#: src/ownership/borrowing.md:27 +msgid "Notes on stack returns:" +msgstr "" + +#: src/ownership/borrowing.md:28 +msgid "" +"* Demonstrate that the return from `add` is cheap because the compiler can " +"eliminate the copy operation. Change the above code to print stack addresses " +"and run it on the [Playground]. In the \"DEBUG\" optimization level, the " +"addresses should change, while they stay the same when changing to the " +"\"RELEASE\" setting:\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn add(p1: &Point, p2: &Point) -> Point {\n" +" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" +" println!(\"&p.0: {:p}\", &p.0);\n" +" p\n" +" }\n" +"\n" +" fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"&p3.0: {:p}\", &p3.0);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +" }\n" +" ```\n" +"* The Rust compiler can do return value optimization (RVO).\n" +"* In C++, copy elision has to be defined in the language specification " +"because constructors can have side effects. In Rust, this is not an issue at " +"all. If RVO did not happen, Rust will always performs a simple and efficient " +"`memcpy` copy." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:1 +msgid "# Shared and Unique Borrows" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:3 +msgid "Rust puts constraints on the ways you can borrow values:" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:5 +msgid "" +"* You can have one or more `&T` values at any given time, _or_\n" +"* You can have exactly one `&mut T` value." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let mut a: i32 = 10;\n" +" let b: &i32 = &a;\n" +"\n" +" {\n" +" let c: &mut i32 = &mut a;\n" +" *c = 20;\n" +" }\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:25 +msgid "" +"* The above code does not compile because `a` is borrowed as mutable " +"(through `c`) and as immutable (through `b`) at the same time.\n" +"* Move the `println!` statement for `b` before the scope that introduces `c` " +"to make the code compile.\n" +"* After that change, the compiler realizes that `b` is only ever used before " +"the new mutable borrow of `a` through `c`. This is a feature of the borrow " +"checker called \"non-lexical lifetimes\"." +msgstr "" + +#: src/ownership/lifetimes.md:1 +msgid "# Lifetimes" +msgstr "" + +#: src/ownership/lifetimes.md:3 +msgid "A borrowed value has a _lifetime_:" +msgstr "" + +#: src/ownership/lifetimes.md:5 +msgid "" +"* The lifetime can be elided: `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." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:1 +msgid "# Lifetimes in Function Calls" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:3 +msgid "" +"In addition to borrowing its arguments, a function can return a borrowed " +"value:" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p2: Point = Point(20, 20);\n" +" let p3: &Point = left_most(&p1, &p2);\n" +" println!(\"left-most point: {:?}\", p3);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:21 +msgid "" +"* `'a` is a generic parameter, it is inferred by the compiler.\n" +"* Lifetimes start with `'` and `'a` is a typical default name.\n" +"* Read `&'a Point` as \"a borrowed `Point` which is valid for at least the\n" +" lifetime `a`\".\n" +" * The _at least_ part is important when parameters are in different scopes." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:31 +msgid "" +"* Move the declaration of `p2` and `p3` into a a new scope (`{ ... }`), " +"resulting in the following code:\n" +" ```rust,ignore\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +" }\n" +"\n" +" fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p3: &Point;\n" +" {\n" +" let p2: Point = Point(20, 20);\n" +" p3 = left_most(&p1, &p2);\n" +" }\n" +" println!(\"left-most point: {:?}\", p3);\n" +" }\n" +" ```\n" +" Note how this does not compile since `p3` outlives `p2`.\n" +"\n" +"* Reset the workspace and change the function signature to `fn left_most<'a, " +"'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " +"because the relationship between the lifetimes `'a` and `'b` is unclear.\n" +"* Another way to explain it:\n" +" * 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" +" for longer than a variable from where the reference came from." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:1 +msgid "# Lifetimes in Data Structures" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:3 +msgid "" +"If a data type stores borrowed data, it must be annotated with a lifetime:" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Highlight<'doc>(&'doc str);\n" +"\n" +"fn erase(text: String) {\n" +" println!(\"Bye {text}!\");\n" +"}\n" +"\n" +"fn main() {\n" +" let text = String::from(\"The quick brown fox jumps over the lazy dog." +"\");\n" +" let fox = Highlight(&text[4..19]);\n" +" let dog = Highlight(&text[35..43]);\n" +" // erase(text);\n" +" println!(\"{fox:?}\");\n" +" println!(\"{dog:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:25 +msgid "" +"* In the above example, the annotation on `Highlight` enforces that the data " +"underlying the contained `&str` lives at least as long as any instance of " +"`Highlight` that uses that data.\n" +"* If `text` is consumed before the end of the lifetime of `fox` (or `dog`), " +"the borrow checker throws an error.\n" +"* Types with borrowed data force users to hold on to the original data. This " +"can be useful for creating lightweight views, but it generally makes them " +"somewhat harder to use.\n" +"* When possible, make data structures own their data directly.\n" +"* Some structs with multiple references inside can have more than one " +"lifetime annotation. This can be necessary if there is a need to describe " +"lifetime relationships between the references themselves, in addition to the " +"lifetime of the struct itself. Those are very advanced use cases." +msgstr "" + +#: src/exercises/day-1/afternoon.md:1 +msgid "# Day 1: Afternoon Exercises" +msgstr "" + +#: src/exercises/day-1/afternoon.md:3 +msgid "We will look at two things:" +msgstr "" + +#: src/exercises/day-1/afternoon.md:5 +msgid "" +"* A small book library,\n" +"\n" +"* Iterators and ownership (hard)." +msgstr "" + +#: src/exercises/day-1/book-library.md:1 +msgid "# Designing a Library" +msgstr "" + +#: src/exercises/day-1/book-library.md:3 +msgid "" +"We will learn much more about structs and the `Vec` type tomorrow. For " +"now,\n" +"you just need to know part of its API:" +msgstr "" + +#: src/exercises/day-1/book-library.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut vec = vec![10, 20];\n" +" vec.push(30);\n" +" let midpoint = vec.len() / 2;\n" +" println!(\"middle value: {}\", vec[midpoint]);\n" +" for item in &vec {\n" +" println!(\"item: {item}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:18 +msgid "" +"Use this to create a library application. Copy the code below to\n" +" and update the types to make it compile:" +msgstr "" + +#: src/exercises/day-1/book-library.md:21 +msgid "" +"```rust,should_panic\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// Implement the methods below. Update the `self` parameter to\n" +"// indicate the method's required level of ownership over the object:\n" +"//\n" +"// - `&self` for shared read-only access,\n" +"// - `&mut self` for unique and mutable access,\n" +"// - `self` for unique access by value.\n" +"impl Library {\n" +" fn new() -> Library {\n" +" todo!(\"Initialize and return a `Library` value\")\n" +" }\n" +"\n" +" //fn len(self) -> usize {\n" +" // todo!(\"Return the length of `self.books`\")\n" +" //}\n" +"\n" +" //fn is_empty(self) -> bool {\n" +" // todo!(\"Return `true` if `self.books` is empty\")\n" +" //}\n" +"\n" +" //fn add_book(self, book: Book) {\n" +" // todo!(\"Add a new book to `self.books`\")\n" +" //}\n" +"\n" +" //fn print_books(self) {\n" +" // todo!(\"Iterate over `self.books` and each book's title and " +"year\")\n" +" //}\n" +"\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // todo!(\"Return a reference to the oldest book (if any)\")\n" +" //}\n" +"}\n" +"\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();\n" +"\n" +" //println!(\"The library is empty: {}\", library.is_empty());\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!(\"The oldest book is {}\", book.title),\n" +" // None => println!(\"The library is empty!\"),\n" +" //}\n" +" //\n" +" //println!(\"The library has {} books\", library.len());\n" +" //library.print_books();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:102 +msgid "[Solution](solutions-afternoon.md#designing-a-library)" msgstr "" -#: src/memory-management/rust.md:10 -msgid "It achieves this by modeling _ownership_ explicitly." +#: src/exercises/day-1/iterators-and-ownership.md:1 +msgid "# Iterators and Ownership" msgstr "" -#: src/memory-management/rust.md:14 +#: src/exercises/day-1/iterators-and-ownership.md:3 msgid "" -"* If asked how at this point, you can mention that in Rust this is usually " -"handled by RAII wrapper types such as [Box], [Vec], [Rc], or [Arc]. These " -"encapsulate ownership and memory allocation via various means, and prevent " -"the potential errors in C." +"The ownership model of Rust affects many APIs. An example of this is the\n" +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and\n" +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator." +"html)\n" +"traits." msgstr "" -#: src/memory-management/rust.md:16 -msgid "" -"* You may be asked about destructors here, the [Drop] trait is the Rust " -"equivalent." +#: src/exercises/day-1/iterators-and-ownership.md:8 +msgid "## `Iterator`" msgstr "" -#: src/memory-management/rust.md:20 +#: src/exercises/day-1/iterators-and-ownership.md:10 msgid "" -"[Box]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" -"[Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" -"[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" -"[Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" -"[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html" -msgstr "" - -#: src/memory-management/comparison.md:1 -msgid "# Comparison" -msgstr "" - -#: src/memory-management/comparison.md:3 -msgid "Here is a rough comparison of the memory management techniques." -msgstr "" - -#: src/memory-management/comparison.md:5 -msgid "## Pros of Different Memory Management Techniques" +"Traits are like interfaces: they describe behavior (methods) for a type. " +"The\n" +"`Iterator` trait simply says that you can call `next` until you get `None` " +"back:" msgstr "" -#: src/memory-management/comparison.md:7 +#: src/exercises/day-1/iterators-and-ownership.md:13 msgid "" -"* Manual like C:\n" -" * No runtime overhead.\n" -"* Automatic like Java:\n" -" * Fully automatic.\n" -" * Safe and correct.\n" -"* Scope-based like C++:\n" -" * Partially automatic.\n" -" * No runtime overhead.\n" -"* Compiler-enforced scope-based like Rust:\n" -" * Enforced by compiler.\n" -" * No runtime overhead.\n" -" * Safe and correct." +"```rust\n" +"pub trait Iterator {\n" +" type Item;\n" +" fn next(&mut self) -> Option;\n" +"}\n" +"```" msgstr "" -#: src/memory-management/comparison.md:20 -msgid "## Cons of Different Memory Management Techniques" +#: src/exercises/day-1/iterators-and-ownership.md:20 +msgid "You use this trait like this:" msgstr "" -#: src/memory-management/comparison.md:22 +#: src/exercises/day-1/iterators-and-ownership.md:22 msgid "" -"* Manual like C:\n" -" * Use-after-free.\n" -" * Double-frees.\n" -" * Memory leaks.\n" -"* Automatic like Java:\n" -" * Garbage collection pauses.\n" -" * Destructor delays.\n" -"* Scope-based like C++:\n" -" * Complex, opt-in by programmer.\n" -" * Potential for use-after-free.\n" -"* Compiler-enforced and scope-based like Rust:\n" -" * Some upfront complexity.\n" -" * Can reject valid programs." -msgstr "" - -#: src/ownership.md:1 -msgid "# Ownership" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" println!(\"v[0]: {:?}\", iter.next());\n" +" println!(\"v[1]: {:?}\", iter.next());\n" +" println!(\"v[2]: {:?}\", iter.next());\n" +" println!(\"No more items: {:?}\", iter.next());\n" +"}\n" +"```" msgstr "" -#: src/ownership.md:3 -msgid "" -"All variable bindings have a _scope_ where they are valid and it is an error " -"to\n" -"use a variable outside its scope:" +#: src/exercises/day-1/iterators-and-ownership.md:34 +msgid "What is the type returned by the iterator? Test your answer here:" msgstr "" -#: src/ownership.md:6 +#: src/exercises/day-1/iterators-and-ownership.md:36 msgid "" "```rust,editable,compile_fail\n" -"struct Point(i32, i32);" -msgstr "" - -#: src/ownership.md:9 -msgid "" "fn main() {\n" -" {\n" -" let p = Point(3, 4);\n" -" println!(\"x: {}\", p.0);\n" -" }\n" -" println!(\"y: {}\", p.1);\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" "}\n" "```" msgstr "" -#: src/ownership.md:18 -msgid "" -"* At the end of the scope, the variable is _dropped_ and the data is freed.\n" -"* A destructor can run here to free up resources.\n" -"* We say that the variable _owns_ the value." +#: src/exercises/day-1/iterators-and-ownership.md:46 +msgid "Why is this type used?" msgstr "" -#: src/ownership/move-semantics.md:1 -msgid "# Move Semantics" +#: src/exercises/day-1/iterators-and-ownership.md:48 +msgid "## `IntoIterator`" msgstr "" -#: src/ownership/move-semantics.md:3 -msgid "An assignment will transfer ownership between variables:" +#: src/exercises/day-1/iterators-and-ownership.md:50 +msgid "" +"The `Iterator` trait tells you how to _iterate_ once you have created an\n" +"iterator. The related trait `IntoIterator` tells you how to create the " +"iterator:" msgstr "" -#: src/ownership/move-semantics.md:5 +#: src/exercises/day-1/iterators-and-ownership.md:53 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1: String = String::from(\"Hello!\");\n" -" let s2: String = s1;\n" -" println!(\"s2: {s2}\");\n" -" // println!(\"s1: {s1}\");\n" +"```rust\n" +"pub trait IntoIterator {\n" +" type Item;\n" +" type IntoIter: Iterator;\n" +"\n" +" fn into_iter(self) -> Self::IntoIter;\n" "}\n" "```" msgstr "" -#: src/ownership/move-semantics.md:14 +#: src/exercises/day-1/iterators-and-ownership.md:62 msgid "" -"* The assignment of `s1` to `s2` transfers ownership.\n" -"* The data was _moved_ from `s1` and `s1` is no longer accessible.\n" -"* When `s1` goes out of scope, nothing happens: it has no ownership.\n" -"* When `s2` goes out of scope, the string data is freed.\n" -"* There is always _exactly_ one variable binding which owns a value." +"The syntax here means that every implementation of `IntoIterator` must\n" +"declare two types:" msgstr "" -#: src/ownership/move-semantics.md:22 +#: src/exercises/day-1/iterators-and-ownership.md:65 msgid "" -"* Mention that this is the opposite of the defaults in C++, which copies by " -"value unless you use `std::move` (and the move constructor is defined!)." +"* `Item`: the type we iterate over, such as `i8`,\n" +"* `IntoIter`: the `Iterator` type returned by the `into_iter` method." msgstr "" -#: src/ownership/move-semantics.md:24 -msgid "* In Rust, you clones are explicit (by using `clone`)." +#: src/exercises/day-1/iterators-and-ownership.md:68 +msgid "" +"Note that `IntoIter` and `Item` are linked: the iterator must have the same\n" +"`Item` type, which means that it returns `Option`" msgstr "" -#: src/ownership/moved-strings-rust.md:1 -msgid "# Moved Strings in Rust" +#: src/exercises/day-1/iterators-and-ownership.md:71 +msgid "Like before, what is the type returned by the iterator?" msgstr "" -#: src/ownership/moved-strings-rust.md:3 +#: src/exercises/day-1/iterators-and-ownership.md:73 msgid "" -"```rust,editable\n" +"```rust,editable,compile_fail\n" "fn main() {\n" -" let s1: String = String::from(\"Rust\");\n" -" let s2: String = s1;\n" +" let v: Vec = vec![String::from(\"foo\"), String::" +"from(\"bar\")];\n" +" let mut iter = v.into_iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" "}\n" "```" msgstr "" -#: src/ownership/moved-strings-rust.md:10 -msgid "" -"* The heap data from `s1` is reused for `s2`.\n" -"* When `s1` goes out of scope, nothing happens (it has been moved from)." -msgstr "" - -#: src/ownership/moved-strings-rust.md:13 -msgid "Before move to `s2`:" +#: src/exercises/day-1/iterators-and-ownership.md:83 +msgid "## `for` Loops" msgstr "" -#: src/ownership/moved-strings-rust.md:15 +#: src/exercises/day-1/iterators-and-ownership.md:85 msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| R | u | s | t | :\n" -": | len | 4 | : : +----+----+----+----+ :\n" -": | capacity | 4 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - -'\n" -": :\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/ownership/moved-strings-rust.md:30 -msgid "After move to `s2`:" +"Now that we know both `Iterator` and `IntoIterator`, we can build `for` " +"loops.\n" +"They call `into_iter()` on an expression and iterates over the resulting\n" +"iterator:" msgstr "" -#: src/ownership/moved-strings-rust.md:32 -#, fuzzy +#: src/exercises/day-1/iterators-and-ownership.md:89 msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 \"(inaccessible)\" : : :\n" -": +-----------+-------+ : : +----+----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" -": | len | 4 | : | : +----+----+----+----+ :\n" -": | capacity | 4 | : | : :\n" -": +-----------+-------+ : | : :\n" -": : | `- - - - - - - - - - - - - -'\n" -": s2 : |\n" -": +-----------+-------+ : |\n" -": | ptr | o---+---+--'\n" -": | len | 4 | :\n" -": | capacity | 4 | :\n" -": +-----------+-------+ :\n" -": :\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" -"```bob\n" -" Stak Bunke\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| H | a | l | l | o | :\n" -": | len | 5 | : : +----+----+----+----+----+ :\n" -": | capacity | 5 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::" +"from(\"bar\")];\n" +"\n" +" for word in &v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"\n" +" for word in v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"}\n" "```" - -#: src/ownership/double-free-modern-cpp.md:1 -msgid "# Double Frees in Modern C++" msgstr "" -#: src/ownership/double-free-modern-cpp.md:3 -msgid "Modern C++ solves this differently:" +#: src/exercises/day-1/iterators-and-ownership.md:103 +msgid "What is the type of `word` in each loop?" msgstr "" -#: src/ownership/double-free-modern-cpp.md:5 +#: src/exercises/day-1/iterators-and-ownership.md:105 msgid "" -"```c++\n" -"std::string s1 = \"Cpp\";\n" -"std::string s2 = s1; // Duplicate the data in s1.\n" -"```" +"Experiment with the code above and then consult the documentation for " +"[`impl\n" +"IntoIterator for\n" +"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-" +"IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E)\n" +"and [`impl IntoIterator for\n" +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-" +"for-Vec%3CT%2C%20A%3E)\n" +"to check your answers." msgstr "" -#: src/ownership/double-free-modern-cpp.md:10 -msgid "" -"* The heap data from `s1` is duplicated and `s2` gets its own independent " -"copy.\n" -"* When `s1` and `s2` go out of scope, they each free their own memory." +#: src/welcome-day-2.md:1 +msgid "# Welcome to Day 2" msgstr "" -#: src/ownership/double-free-modern-cpp.md:13 -msgid "Before copy-assignment:" +#: src/welcome-day-2.md:3 +msgid "Now that we have seen a fair amount of Rust, we will continue with:" msgstr "" -#: src/ownership/double-free-modern-cpp.md:16 +#: src/welcome-day-2.md:5 msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" +"* Structs, enums, methods.\n" +"\n" +"* Pattern matching: destructuring enums, structs, and arrays.\n" +"\n" +"* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, " +"and\n" +" `continue`.\n" +"\n" +"* The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, " +"`Rc`\n" +" and `Arc`.\n" +"\n" +"* Modules: visibility, paths, and filesystem hierarchy." msgstr "" -#: src/ownership/double-free-modern-cpp.md:30 -msgid "After copy-assignment:" +#: src/structs.md:1 +msgid "# Structs" msgstr "" -#: src/ownership/double-free-modern-cpp.md:32 -#, fuzzy +#: src/structs.md:3 +msgid "Like C and C++, Rust has support for custom structs:" +msgstr "" + +#: src/structs.md:5 msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : : :\n" -": s2 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+-----+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" +"```rust,editable\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" peter.age = 28;\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" let jackie = Person {\n" +" name: String::from(\"Jackie\"),\n" +" ..peter\n" +" };\n" +" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" +"}\n" "```" msgstr "" -"```bob\n" -" Stak Bunke\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| H | a | l | l | o | :\n" -": | len | 5 | : : +----+----+----+----+----+ :\n" -": | capacity | 5 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -#: src/ownership/moves-function-calls.md:1 -msgid "# Moves in Function Calls" +#: src/structs.md:29 +msgid "" +"
\n" +"Key Points: " msgstr "" -#: src/ownership/moves-function-calls.md:3 +#: src/structs.md:32 msgid "" -"When you pass a value to a function, the value is assigned to the function\n" -"parameter. This transfers ownership:" +"* Structs work like in C or C++.\n" +" * Like in C++, and unlike in C, no typedef is needed to define a type.\n" +" * Unlike in C++, there is no inheritance between structs.\n" +"* Methods are defined in an `impl` block, which we will see in following " +"slides.\n" +"* This may be a good time to let people know there are different types of " +"structs. \n" +" * Zero-sized structs `e.g., struct Foo;` might be used when implementing a " +"trait on some type but don’t have any data that you want to store in the " +"value itself. \n" +" * The next slide will introduce Tuple structs, used when the field names " +"are not important.\n" +"* The syntax `..peter` allows us to copy the majority of the fields from the " +"old struct without having to explicitly type it all out. It must always be " +"the last element." msgstr "" -#: src/ownership/moves-function-calls.md:6 -msgid "" -"```rust,editable\n" -"fn say_hello(name: String) {\n" -" println!(\"Hello {name}\")\n" -"}" +#: src/structs/tuple-structs.md:1 +msgid "# Tuple Structs" msgstr "" -#: src/ownership/moves-function-calls.md:11 +#: src/structs/tuple-structs.md:3 +msgid "If the field names are unimportant, you can use a tuple struct:" +msgstr "" + +#: src/structs/tuple-structs.md:5 msgid "" +"```rust,editable\n" +"struct Point(i32, i32);\n" +"\n" "fn main() {\n" -" let name = String::from(\"Alice\");\n" -" say_hello(name);\n" -" // say_hello(name);\n" +" let p = Point(17, 23);\n" +" println!(\"({}, {})\", p.0, p.1);\n" "}\n" "```" msgstr "" -#: src/ownership/moves-function-calls.md:20 -msgid "" -"* With the first call to `say_hello`, `main` gives up ownership of `name`. " -"Afterwards, `name` cannot be used anymore within `main`.\n" -"* `main` can retain ownership if it passes `name` as a reference (`&name`) " -"and if `say_hello` accepts a reference as a parameter.\n" -"* Alternatively, `main` can pass a clone of `name` in the first call (`name." -"clone()`).\n" -"* Rust makes it harder than C++ to inadvertently create copies by making " -"move semantics the default, and by forcing programmers to make clones " -"explicit." -msgstr "" - -#: src/ownership/copy-clone.md:1 -msgid "# Copying and Cloning" -msgstr "" - -#: src/ownership/copy-clone.md:3 -msgid "" -"While move semantics are the default, certain types are copied by default:" +#: src/structs/tuple-structs.md:14 +msgid "This is often used for single-field wrappers (called newtypes):" msgstr "" -#: src/ownership/copy-clone.md:5 +#: src/structs/tuple-structs.md:16 msgid "" -"```rust,editable\n" +"```rust,editable,compile_fail\n" +"struct PoundsOfForce(f64);\n" +"struct Newtons(f64);\n" +"\n" +"fn compute_thruster_force() -> PoundsOfForce {\n" +" todo!(\"Ask a rocket scientist at NASA\")\n" +"}\n" +"\n" +"fn set_thruster_force(force: Newtons) {\n" +" // ...\n" +"}\n" +"\n" "fn main() {\n" -" let x = 42;\n" -" let y = x;\n" -" println!(\"x: {x}\");\n" -" println!(\"y: {y}\");\n" +" let force = compute_thruster_force();\n" +" set_thruster_force(force);\n" "}\n" +"\n" "```" msgstr "" -#: src/ownership/copy-clone.md:14 -msgid "These types implement the `Copy` trait." +#: src/structs/tuple-structs.md:37 +msgid "" +"* Newtypes are a great way to encode additional information about the value " +"in a primitive type, for example:\n" +" * The number is measured in some units: `Newtons` in the example above.\n" +" * The value passed some validation when it was created, so you no longer " +"have to validate it again at every use: 'PhoneNumber(String)` or " +"`OddNumber(u32)`.\n" +"* Demonstrate how to add a `f64` value to a `Newtons` type by accessing the " +"single field in the newtype.\n" +" * Rust generally doesn’t like inexplicit things, like automatic " +"unwrapping or for instance using booleans as integers.\n" +" * Operator overloading is discussed on Day 3 (generics). " msgstr "" -#: src/ownership/copy-clone.md:16 -msgid "You can opt-in your own types to use copy semantics:" +#: src/structs/field-shorthand.md:1 +msgid "# Field Shorthand Syntax" msgstr "" -#: src/ownership/copy-clone.md:18 +#: src/structs/field-shorthand.md:3 msgid "" -"```rust,editable\n" -"#[derive(Copy, Clone, Debug)]\n" -"struct Point(i32, i32);" +"If you already have variables with the right names, then you can create the\n" +"struct using a shorthand:" msgstr "" -#: src/ownership/copy-clone.md:22 +#: src/structs/field-shorthand.md:6 msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn new(name: String, age: u8) -> Person {\n" +" Person { name, age }\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = p1;\n" -" println!(\"p1: {p1:?}\");\n" -" println!(\"p2: {p2:?}\");\n" +" let peter = Person::new(String::from(\"Peter\"), 27);\n" +" println!(\"{peter:?}\");\n" "}\n" "```" msgstr "" -#: src/ownership/copy-clone.md:30 -msgid "" -"* After the assignment, both `p1` and `p2` own their own data.\n" -"* We can also use `p1.clone()` to explicitly copy the data." +#: src/structs/field-shorthand.md:27 +msgid "" +"* The `new` function could be written using `Self` as a type, as it is " +"interchangeable with the struct type name\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Person {\n" +" fn new(name: String, age: u8) -> Self {\n" +" Self { name, age }\n" +" }\n" +" }\n" +" ``` \n" +"* Implement the `Default` trait for the struct. Define some fields and use " +"the default values for the other fields.\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Default for Person {\n" +" fn default() -> Person {\n" +" Person {\n" +" name: \"Bot\".to_string(),\n" +" age: 0,\n" +" }\n" +" }\n" +" }\n" +" fn create_default() {\n" +" let tmp = Person {\n" +" ..Default::default()\n" +" };\n" +" let tmp = Person {\n" +" name: \"Sam\".to_string(),\n" +" ..Default::default()\n" +" };\n" +" }\n" +" ```\n" +"\n" +"* Methods are defined in the `impl` block.\n" +"* Use struct update syntax to define a new structure using `peter`. Note " +"that the variable `peter` will no longer be accessible afterwards.\n" +"* Use `{:#?}` when printing structs to request the `Debug` representation." msgstr "" -#: src/ownership/copy-clone.md:35 -msgid "Copying and cloning are not the same thing:" +#: src/enums.md:1 +msgid "# Enums" msgstr "" -#: src/ownership/copy-clone.md:37 +#: src/enums.md:3 msgid "" -"* Copying refers to bitwise copies of memory regions and does not work on " -"arbitrary objects.\n" -"* Copying does not allow for custom logic (unlike copy constructors in C+" -"+).\n" -"* Cloning is a more general operation and also allows for custom behavior by " -"implementing the `Clone` trait.\n" -"* Copying does not work on types that implement the `Drop` trait." -msgstr "" - -#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 -msgid "In the above example, try the following:" +"The `enum` keyword allows the creation of a type which has a few\n" +"different variants:" msgstr "" -#: src/ownership/copy-clone.md:44 +#: src/enums.md:6 msgid "" -"* Add a `String` field to `struct Point`. It will not compile because " -"`String` is not a `Copy` type.\n" -"* Remove `Copy` from the `derive` attribute. The compiler error is now in " -"the `println!` for `p1`.\n" -"* Show that it works if you clone `p1` instead." +"```rust,editable\n" +"fn generate_random_number() -> i32 {\n" +" 4 // Chosen by fair dice roll. Guaranteed to be random.\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"enum CoinFlip {\n" +" Heads,\n" +" Tails,\n" +"}\n" +"\n" +"fn flip_coin() -> CoinFlip {\n" +" let random_number = generate_random_number();\n" +" if random_number % 2 == 0 {\n" +" return CoinFlip::Heads;\n" +" } else {\n" +" return CoinFlip::Tails;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"You got: {:?}\", flip_coin());\n" +"}\n" +"```" msgstr "" -#: src/ownership/borrowing.md:1 -msgid "# Borrowing" +#: 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 +msgid "Key Points:" msgstr "" -#: src/ownership/borrowing.md:3 +#: src/enums.md:35 msgid "" -"Instead of transferring ownership when calling a function, you can let a\n" -"function _borrow_ the value:" +"* Enumerations allow you to collect a set of values under one type\n" +"* This page offers an enum type `CoinFlip` with two variants `Heads` and " +"`Tail`. You might note the namespace when using variants.\n" +"* This might be a good time to compare Structs and Enums:\n" +" * In both, you can have a simple version without fields (unit struct) or " +"one with different types of fields (variant payloads). \n" +" * In both, associated functions are defined within an `impl` block.\n" +" * You could even implement the different variants of an enum with separate " +"structs but then they wouldn’t be the same type as they would if they were " +"all defined in an enum. " msgstr "" -#: src/ownership/borrowing.md:6 src/ownership/lifetimes-function-calls.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);" +#: src/enums/variant-payloads.md:1 +msgid "# Variant Payloads" msgstr "" -#: src/ownership/borrowing.md:10 +#: src/enums/variant-payloads.md:3 msgid "" -"fn add(p1: &Point, p2: &Point) -> Point {\n" -" Point(p1.0 + p2.0, p1.1 + p2.1)\n" -"}" +"You can define richer enums where the variants carry data. You can then use " +"the\n" +"`match` statement to extract the data from each variant:" msgstr "" -#: src/ownership/borrowing.md:14 +#: src/enums/variant-payloads.md:6 msgid "" +"```rust,editable\n" +"enum WebEvent {\n" +" PageLoad, // Variant without payload\n" +" KeyPress(char), // Tuple struct variant\n" +" Click { x: i64, y: i64 }, // Full struct variant\n" +"}\n" +"\n" +"#[rustfmt::skip]\n" +"fn inspect(event: WebEvent) {\n" +" match event {\n" +" WebEvent::PageLoad => println!(\"page loaded\"),\n" +" WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" +" WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" -" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +" let load = WebEvent::PageLoad;\n" +" let press = WebEvent::KeyPress('x');\n" +" let click = WebEvent::Click { x: 20, y: 80 };\n" +"\n" +" inspect(load);\n" +" inspect(press);\n" +" inspect(click);\n" "}\n" "```" msgstr "" -#: src/ownership/borrowing.md:22 +#: src/enums/variant-payloads.md:35 msgid "" -"* The `add` function _borrows_ two points and returns a new point.\n" -"* The caller retains ownership of the inputs." +"* The values in the enum variants can only be accessed after being pattern " +"matched. The pattern binds references to the fields in the \"match arm\" " +"after the `=>`.\n" +" * The expression is matched against the patterns from top to bottom. There " +"is no fall-through like in C or C++.\n" +" * The match expression has a value. The value is the last expression in " +"the match arm which was executed.\n" +" * Starting from the top we look for what pattern matches the value then " +"run the code following the arrow. Once we find a match, we stop. \n" +"* Demonstrate what happens when the search is inexhaustive. Note the " +"advantage the Rust compiler provides by confirming when all cases are " +"handled. \n" +"* `match` inspects a hidden discriminant field in the `enum`.\n" +"* It is possible to retrieve the discriminant by calling `std::mem::" +"discriminant()`\n" +" * This is useful, for example, if implementing `PartialEq` for structs " +"where comparing field values doesn't affect equality.\n" +"* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::" +"Click(Click)` with a top level `struct Click { ... }`. The inlined version " +"cannot implement traits, for example. \n" +" " msgstr "" -#: src/ownership/borrowing.md:27 -msgid "" -"Notes on stack returns:\n" -"* Demonstrate that the return from `add` is cheap because the compiler can " -"eliminate the copy operation. Change the above code to print stack addresses " -"and run it on the [Playground]. In the \"DEBUG\" optimization level, the " -"addresses should change, while the stay the same when changing to the " -"\"RELEASE\" setting:" +#: src/enums/sizes.md:1 +msgid "# Enum Sizes" msgstr "" -#: src/ownership/borrowing.md:30 +#: src/enums/sizes.md:3 msgid "" -" ```rust,editable\n" -" #[derive(Debug)]\n" -" struct Point(i32, i32);" +"Rust enums are packed tightly, taking constraints due to alignment into " +"account:" msgstr "" -#: src/ownership/borrowing.md:34 +#: src/enums/sizes.md:5 msgid "" -" fn add(p1: &Point, p2: &Point) -> Point {\n" -" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" -" println!(\"&p.0: {:p}\", &p.0);\n" -" p\n" -" }" +"```rust,editable\n" +"use std::mem::{align_of, size_of};\n" +"\n" +"macro_rules! dbg_size {\n" +" ($t:ty) => {\n" +" println!(\"{}: size {} bytes, align: {} bytes\",\n" +" stringify!($t), size_of::<$t>(), align_of::<$t>());\n" +" };\n" +"}\n" +"\n" +"enum Foo {\n" +" A,\n" +" B,\n" +"}\n" +"\n" +"fn main() {\n" +" dbg_size!(Foo);\n" +"}\n" +"```" msgstr "" -#: src/ownership/borrowing.md:40 +#: src/enums/sizes.md:25 msgid "" -" fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" -" println!(\"&p3.0: {:p}\", &p3.0);\n" -" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" -" }\n" -" ```\n" -"* The Rust compiler can do return value optimization (RVO).\n" -"* In C++, copy elision has to be defined in the language specification " -"because constructors can have side effects. In Rust, this is not an issue at " -"all." +"* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout." +"html)." msgstr "" -#: src/ownership/borrowing.md:53 -msgid "[Playground]: https://play.rust-lang.org/" +#: src/enums/sizes.md:31 +msgid "" +" * Internally Rust is using a field (discriminant) to keep track of the enum " +"variant.\n" +"\n" +" * You can control the discriminant if needed (e.g., for compatibility with " +"C):\n" +" \n" +" ```rust,editable\n" +" #[repr(u32)]\n" +" enum Bar {\n" +" A, // 0\n" +" B = 10000,\n" +" C, // 10001\n" +" }\n" +" \n" +" fn main() {\n" +" println!(\"A: {}\", Bar::A as u32);\n" +" println!(\"B: {}\", Bar::B as u32);\n" +" println!(\"C: {}\", Bar::C as u32);\n" +" }\n" +" ```\n" +"\n" +" Without `repr`, the discriminant type takes 2 bytes, because 10001 fits " +"2\n" +" bytes.\n" +"\n" +"\n" +" * Try out other types such as\n" +" \n" +" * `dbg_size!(bool)`: size 1 bytes, align: 1 bytes,\n" +" * `dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche " +"optimization, see below),\n" +" * `dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit " +"machine),\n" +" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer " +"optimization, see below).\n" +"\n" +" * Niche optimization: Rust will merge use unused bit patterns for the enum\n" +" discriminant.\n" +"\n" +" * Null pointer optimization: For [some\n" +" types](https://doc.rust-lang.org/std/option/#representation), Rust " +"guarantees\n" +" that `size_of::()` equals `size_of::>()`.\n" +"\n" +" Example code if you want to show how the bitwise representation *may* " +"look like in practice.\n" +" It's important to note that the compiler provides no guarantees " +"regarding this representation, therefore this is totally unsafe.\n" +"\n" +" ```rust,editable\n" +" use std::mem::transmute;\n" +"\n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, " +"$bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" println!(\"Bitwise representation of bool\");\n" +" dbg_bits!(false, u8);\n" +" dbg_bits!(true, u8);\n" +"\n" +" println!(\"Bitwise representation of Option\");\n" +" dbg_bits!(None::, u8);\n" +" dbg_bits!(Some(false), u8);\n" +" dbg_bits!(Some(true), u8);\n" +"\n" +" println!(\"Bitwise representation of Option>\");\n" +" dbg_bits!(Some(Some(false)), u8);\n" +" dbg_bits!(Some(Some(true)), u8);\n" +" dbg_bits!(Some(None::), u8);\n" +" dbg_bits!(None::>, u8);\n" +"\n" +" println!(\"Bitwise representation of Option<&i32>\");\n" +" dbg_bits!(None::<&i32>, usize);\n" +" dbg_bits!(Some(&0i32), usize);\n" +" }\n" +" }\n" +" ```\n" +"\n" +" More complex example if you want to discuss what happens when we chain " +"more than 256 `Option`s together.\n" +"\n" +" ```rust,editable\n" +" #![recursion_limit = \"1000\"]\n" +"\n" +" use std::mem::transmute;\n" +" \n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, " +"$bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" // Macro to wrap a value in 2^n Some() where n is the number of \"@\" " +"signs.\n" +" // Increasing the recursion limit is required to evaluate this macro.\n" +" macro_rules! many_options {\n" +" ($value:expr) => { Some($value) };\n" +" ($value:expr, @) => {\n" +" Some(Some($value))\n" +" };\n" +" ($value:expr, @ $($more:tt)+) => {\n" +" many_options!(many_options!($value, $($more)+), $($more)+)\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" assert_eq!(many_options!(false), Some(false));\n" +" assert_eq!(many_options!(false, @), Some(Some(false)));\n" +" assert_eq!(many_options!(false, @@), " +"Some(Some(Some(Some(false)))));\n" +"\n" +" println!(\"Bitwise representation of a chain of 128 Option's." +"\");\n" +" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" +" dbg_bits!(many_options!(true, @@@@@@@), u8);\n" +"\n" +" println!(\"Bitwise representation of a chain of 256 Option's." +"\");\n" +" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(true, @@@@@@@@), u16);\n" +"\n" +" println!(\"Bitwise representation of a chain of 257 Option's." +"\");\n" +" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" +" }\n" +" }\n" +" ```" msgstr "" -#: src/ownership/shared-unique-borrows.md:1 -msgid "# Shared and Unique Borrows" +#: src/methods.md:3 +msgid "" +"Rust allows you to associate functions with your new types. You do this with " +"an\n" +"`impl` block:" msgstr "" -#: src/ownership/shared-unique-borrows.md:3 -msgid "Rust puts constraints on the ways you can borrow values:" +#: src/methods.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn say_hello(&self) {\n" +" println!(\"Hello, my name is {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" peter.say_hello();\n" +"}\n" +"```" msgstr "" -#: src/ownership/shared-unique-borrows.md:5 +#: src/methods.md:31 msgid "" -"* You can have one or more `&T` values at any given time, _or_\n" -"* You can have exactly one `&mut T` value." +"* It can be helpful to introduce methods by comparing them to functions.\n" +" * Methods are called on an instance of a type (such as a struct or enum), " +"the first parameter represents the instance as `self`.\n" +" * Developers may choose to use methods to take advantage of method " +"receiver syntax and to help keep them more organized. By using methods we " +"can keep all the implementation code in one predictable place.\n" +"* Point out the use of the keyword `self`, a method receiver. \n" +" * Show that it is an abbreviated term for `self:&Self` and perhaps show " +"how the struct name could also be used. \n" +" * Explain that `Self` is a type alias for the type the `impl` block is in " +"and can be used elsewhere in the block.\n" +" * Note how `self` is used like other structs and dot notation can be used " +"to refer to individual fields.\n" +" * This might be a good time to demonstrate how the `&self` differs from " +"`self` by modifying the code and trying to run say_hello twice. \n" +"* We describe the distinction between method receivers next.\n" +" " msgstr "" -#: src/ownership/shared-unique-borrows.md:8 +#: src/methods/receiver.md:1 +msgid "# Method Receiver" +msgstr "" + +#: src/methods/receiver.md:3 msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let mut a: i32 = 10;\n" -" let b: &i32 = &a;" +"The `&self` above indicates that the method borrows the object immutably. " +"There\n" +"are other possible receivers for a method:" msgstr "" -#: src/ownership/shared-unique-borrows.md:13 +#: src/methods/receiver.md:6 msgid "" -" {\n" -" let c: &mut i32 = &mut a;\n" -" *c = 20;\n" -" }" +"* `&self`: borrows the object from the caller using a shared and immutable\n" +" reference. The object can be used again afterwards.\n" +"* `&mut self`: borrows the object from the caller using a unique and " +"mutable\n" +" reference. The object can be used again afterwards.\n" +"* `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" +"* No receiver: this becomes a static method on the struct. Typically used " +"to\n" +" create constructors which are called `new` by convention." msgstr "" -#: src/ownership/shared-unique-borrows.md:18 src/std/rc.md:13 +#: src/methods/receiver.md:19 msgid "" -" println!(\"a: {a}\");\n" -" println!(\"b: {b}\");\n" -"}\n" -"```" +"Beyond variants on `self`, there are also\n" +"[special wrapper types](https://doc.rust-lang.org/reference/special-types-" +"and-traits.html)\n" +"allowed to be receiver types, such as `Box`." msgstr "" -#: src/ownership/shared-unique-borrows.md:25 +#: src/methods/receiver.md:25 msgid "" -"* The above code does not compile because `a` is borrowed as mutable " -"(through `c`) and as immutable (through `b`) at the same time.\n" -"* Move the `println!` statement for `b` before the scope that introduces `c` " -"to make the code compile.\n" -"* After that change, the compiler realizes that `b` is only ever used before " -"the new mutable borrow of `a` through `c`. This is a feature of the borrow " -"checker called \"non-lexical lifetimes\"." +"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". " +"These constraints always come\n" +"together in Rust due to borrow checker rules, and `self` is no exception. It " +"isn't possible to\n" +"reference a struct from multiple locations and call a mutating (`&mut self`) " +"method on it." msgstr "" -#: src/ownership/lifetimes.md:1 -msgid "# Lifetimes" +#: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 +msgid "# Example" msgstr "" -#: src/ownership/lifetimes.md:3 -msgid "A borrowed value has a _lifetime_:" +#: src/methods/example.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Race {\n" +" name: String,\n" +" laps: Vec,\n" +"}\n" +"\n" +"impl Race {\n" +" fn new(name: &str) -> Race { // No receiver, a static method\n" +" Race { name: String::from(name), laps: Vec::new() }\n" +" }\n" +"\n" +" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write " +"access to self\n" +" self.laps.push(lap);\n" +" }\n" +"\n" +" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" +" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" +" for (idx, lap) in self.laps.iter().enumerate() {\n" +" println!(\"Lap {idx}: {lap} sec\");\n" +" }\n" +" }\n" +"\n" +" fn finish(self) { // Exclusive ownership of self\n" +" let total = self.laps.iter().sum::();\n" +" println!(\"Race {} is finished, total lap time: {}\", self.name, " +"total);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut race = Race::new(\"Monaco Grand Prix\");\n" +" race.add_lap(70);\n" +" race.add_lap(68);\n" +" race.print_laps();\n" +" race.add_lap(71);\n" +" race.print_laps();\n" +" race.finish();\n" +" // race.add_lap(42);\n" +"}\n" +"```" msgstr "" -#: src/ownership/lifetimes.md:5 +#: src/methods/example.md:47 msgid "" -"* The lifetime can be elided: `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." +"* All four methods here use a different method receiver.\n" +" * You can point out how that changes what the function can do with the " +"variable values and if/how it can be used again in `main`.\n" +" * You can showcase the error that appears when trying to call `finish` " +"twice.\n" +"* Note that although the method receivers are different, the non-static " +"functions are called the same way in the main body. Rust enables automatic " +"referencing and dereferencing when calling methods. Rust automatically adds " +"in the `&`, `*`, `muts` so that that object matches the method signature.\n" +"* You might point out that `print_laps` is using a vector that is iterated " +"over. We describe vectors in more detail in the afternoon. " msgstr "" -#: src/ownership/lifetimes-function-calls.md:1 -msgid "# Lifetimes in Function Calls" +#: src/pattern-matching.md:1 +msgid "# Pattern Matching" msgstr "" -#: src/ownership/lifetimes-function-calls.md:3 +#: src/pattern-matching.md:3 msgid "" -"In addition to borrowing its arguments, a function can return a borrowed " -"value:" +"The `match` keyword let you match a value against one or more _patterns_. " +"The\n" +"comparisons are done from top to bottom and the first match wins." msgstr "" -#: src/ownership/lifetimes-function-calls.md:9 -msgid "" -"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" -" if p1.0 < p2.0 { p1 } else { p2 }\n" -"}" +#: src/pattern-matching.md:6 +msgid "The patterns can be simple values, similarly to `switch` in C and C++:" msgstr "" -#: src/ownership/lifetimes-function-calls.md:13 +#: src/pattern-matching.md:8 msgid "" +"```rust,editable\n" "fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p2: Point = Point(20, 20);\n" -" let p3: &Point = left_most(&p1, &p2);\n" -" println!(\"left-most point: {:?}\", p3);\n" +" let input = 'x';\n" +"\n" +" match input {\n" +" 'q' => println!(\"Quitting\"),\n" +" 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" +" '0'..='9' => println!(\"Number input\"),\n" +" _ => println!(\"Something else\"),\n" +" }\n" "}\n" "```" msgstr "" -#: src/ownership/lifetimes-function-calls.md:21 -msgid "" -"* `'a` is a generic parameter, it is inferred by the compiler.\n" -"* Lifetimes start with `'` and `'a` is a typical default name.\n" -"* Read `&'a Point` as \"a borrowed `Point` which is valid for at least the\n" -" lifetime `a`\".\n" -" * The _at least_ part is important when parameters are in different scopes." +#: src/pattern-matching.md:21 +msgid "The `_` pattern is a wildcard pattern which matches any value." msgstr "" -#: src/ownership/lifetimes-function-calls.md:31 +#: src/pattern-matching.md:26 msgid "" -"* Move the declaration of `p2` and `p3` into a a new scope (`{ ... }`), " -"resulting in the following code:\n" -" ```rust,ignore\n" -" #[derive(Debug)]\n" -" struct Point(i32, i32);" +"* You might point out how some specific characters are being used when in a " +"pattern\n" +" * `|` as an `or`\n" +" * `..` can expand as much as it needs to be\n" +" * `1..=5` represents an inclusive range\n" +" * `_` is a wild card\n" +"* It can be useful to show how binding works, by for instance replacing a " +"wildcard character with a variable, or removing the quotes around `q`.\n" +"* You can demonstrate matching on a reference.\n" +"* This might be a good time to bring up the concept of irrefutable patterns, " +"as the term can show up in error messages.\n" +" " msgstr "" -#: src/ownership/lifetimes-function-calls.md:36 -msgid "" -" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" -" if p1.0 < p2.0 { p1 } else { p2 }\n" -" }" +#: src/pattern-matching/destructuring-enums.md:1 +msgid "# Destructuring Enums" msgstr "" -#: src/ownership/lifetimes-function-calls.md:40 +#: src/pattern-matching/destructuring-enums.md:3 msgid "" -" fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p3: &Point;\n" -" {\n" -" let p2: Point = Point(20, 20);\n" -" p3 = left_most(&p1, &p2);\n" -" }\n" -" println!(\"left-most point: {:?}\", p3);\n" -" }\n" -" ```\n" -" Note how this does not compile since `p3` outlives `p2`." +"Patterns can also be used to bind variables to parts of your values. This is " +"how\n" +"you inspect the structure of your types. Let us start with a simple `enum` " +"type:" msgstr "" -#: src/ownership/lifetimes-function-calls.md:52 +#: src/pattern-matching/destructuring-enums.md:6 msgid "" -"* Reset the workspace and change the function signature to `fn left_most<'a, " -"'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " -"because the relationship between the lifetimes `'a` and `'b` is unclear." +"```rust,editable\n" +"enum Result {\n" +" Ok(i32),\n" +" Err(String),\n" +"}\n" +"\n" +"fn divide_in_two(n: i32) -> Result {\n" +" if n % 2 == 0 {\n" +" Result::Ok(n / 2)\n" +" } else {\n" +" Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let n = 100;\n" +" match divide_in_two(n) {\n" +" Result::Ok(half) => println!(\"{n} divided in two is {half}\"),\n" +" Result::Err(msg) => println!(\"sorry, an error happened: {msg}\"),\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/ownership/lifetimes-data-structures.md:1 -msgid "# Lifetimes in Data Structures" +#: src/pattern-matching/destructuring-enums.md:29 +msgid "" +"Here we have used the arms to _destructure_ the `Result` value. In the " +"first\n" +"arm, `half` is bound to the value inside the `Ok` variant. In the second " +"arm,\n" +"`msg` is bound to the error message." msgstr "" -#: src/ownership/lifetimes-data-structures.md:3 +#: src/pattern-matching/destructuring-enums.md:36 msgid "" -"If a data type stores borrowed data, it must be annotated with a lifetime:" +"* The `if`/`else` expression is returning an enum that is later unpacked " +"with a `match`.\n" +"* You can try adding a third variant to the enum definition and displaying " +"the errors when running the code. Point out the places where your code is " +"now inexhaustive and how the compiler tries to give you hints." msgstr "" -#: src/ownership/lifetimes-data-structures.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Highlight<'doc>(&'doc str);" +#: src/pattern-matching/destructuring-structs.md:1 +msgid "# Destructuring Structs" msgstr "" -#: src/ownership/lifetimes-data-structures.md:9 -msgid "" -"fn erase(text: String) {\n" -" println!(\"Bye {text}!\");\n" -"}" +#: src/pattern-matching/destructuring-structs.md:3 +msgid "You can also destructure `structs`:" msgstr "" -#: src/ownership/lifetimes-data-structures.md:13 +#: src/pattern-matching/destructuring-structs.md:5 msgid "" +"```rust,editable\n" +"struct Foo {\n" +" x: (u32, u32),\n" +" y: u32,\n" +"}\n" +"\n" +"#[rustfmt::skip]\n" "fn main() {\n" -" let text = String::from(\"The quick brown fox jumps over the lazy dog." -"\");\n" -" let fox = Highlight(&text[4..19]);\n" -" let dog = Highlight(&text[35..43]);\n" -" // erase(text);\n" -" println!(\"{fox:?}\");\n" -" println!(\"{dog:?}\");\n" +" let foo = Foo { x: (1, 2), y: 3 };\n" +" match foo {\n" +" Foo { x: (1, b), y } => println!(\"x.0 = 1, b = {b}, y = {y}\"),\n" +" Foo { y: 2, x: i } => println!(\"y = 2, x = {i:?}\"),\n" +" Foo { y, .. } => println!(\"y = {y}, other fields were " +"ignored\"),\n" +" }\n" "}\n" "```" msgstr "" -#: src/ownership/lifetimes-data-structures.md:25 +#: src/pattern-matching/destructuring-structs.md:23 msgid "" -"* In the above example, the annotation on `Highlight` enforces that the data " -"underlying the contained `&str` lives at least as long as any instance of " -"`Highlight` that uses that data.\n" -"* If `text` is consumed before the end of the lifetime of `fox` (or `dog`), " -"the borrow checker throws an error.\n" -"* Types with borrowed data force users to hold on to the original data. This " -"can be useful for creating lightweight views, but it generally makes them " -"somewhat harder to use.\n" -"* When possible, make data structures own their data directly." -msgstr "" - -#: src/exercises/day-1/afternoon.md:1 -msgid "# Day 1: Afternoon Exercises" +"* 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.\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/exercises/day-1/afternoon.md:3 -msgid "We will look at two things:" +#: src/pattern-matching/destructuring-arrays.md:1 +msgid "# Destructuring Arrays" msgstr "" -#: src/exercises/day-1/afternoon.md:5 -msgid "* A small book library," +#: src/pattern-matching/destructuring-arrays.md:3 +msgid "" +"You can destructure arrays, tuples, and slices by matching on their elements:" msgstr "" -#: src/exercises/day-1/afternoon.md:7 -msgid "* Iterators and ownership (hard)." +#: src/pattern-matching/destructuring-arrays.md:5 +msgid "" +"```rust,editable\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let triple = [0, -2, 3];\n" +" println!(\"Tell me about {triple:?}\");\n" +" match triple {\n" +" [0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" [1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-1/afternoon.md:13 src/exercises/day-2/afternoon.md:9 -#: src/exercises/day-3/afternoon.md:9 -msgid "[solutions]: solutions-afternoon.md" +#: src/pattern-matching/destructuring-arrays.md:21 +msgid "" +"* Destructuring of slices of unknown length also works with patterns of " +"fixed length.\n" +"\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" inspect(&[0, -2, 3]);\n" +" inspect(&[0, -2, 3, 4]);\n" +" }\n" +"\n" +" #[rustfmt::skip]\n" +" fn inspect(slice: &[i32]) {\n" +" println!(\"Tell me about {slice:?}\");\n" +" match slice {\n" +" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" &[1, ..] => println!(\"First is 1 and the rest were " +"ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +" }\n" +" ```\n" +" \n" +"* Create a new pattern using `_` to represent an element. \n" +"* Add more values to the array.\n" +"* Point out that how `..` will expand to account for different number of " +"elements.\n" +"* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`" msgstr "" -#: src/exercises/day-1/book-library.md:1 -msgid "# Designing a Library" +#: src/pattern-matching/match-guards.md:1 +msgid "# Match Guards" msgstr "" -#: src/exercises/day-1/book-library.md:3 +#: src/pattern-matching/match-guards.md:3 msgid "" -"We will learn much more about structs and the `Vec` type tomorrow. For " -"now,\n" -"you just need to know part of its API:" +"When matching, you can add a _guard_ to a pattern. This is an arbitrary " +"Boolean\n" +"expression which will be executed if the pattern matches:" msgstr "" -#: src/exercises/day-1/book-library.md:6 +#: src/pattern-matching/match-guards.md:6 msgid "" "```rust,editable\n" +"#[rustfmt::skip]\n" "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" -" println!(\"item: {item}\");\n" +" let pair = (2, -2);\n" +" println!(\"Tell me about {pair:?}\");\n" +" match pair {\n" +" (x, y) if x == y => println!(\"These are twins\"),\n" +" (x, y) if x + y == 0 => println!(\"Antimatter, kaboom!\"),\n" +" (x, _) if x % 2 == 1 => println!(\"The first one is odd\"),\n" +" _ => println!(\"No correlation...\"),\n" " }\n" "}\n" "```" msgstr "" -#: src/exercises/day-1/book-library.md:17 +#: src/pattern-matching/match-guards.md:23 msgid "" -"Use this to create a library application. Copy the code below to\n" -" and update the types to make it compile:" +"* Match guards as a separate syntax feature are important and necessary when " +"we wish to concisely express more complex ideas than patterns alone would " +"allow.\n" +"* They are not the same as separate `if` expression inside of the match arm. " +"An `if` expression inside of the branch block (after `=>`) happens after the " +"match arm is selected. Failing the `if` condition inside of that block won't " +"result in other arms\n" +"of the original `match` expression being considered. \n" +"* You can use the variables defined in the pattern in your if expression.\n" +"* The condition defined in the guard applies to every expression in a " +"pattern with an `|`." msgstr "" -#: src/exercises/day-1/book-library.md:24 -msgid "" -"struct Library {\n" -" books: Vec,\n" -"}" +#: src/exercises/day-2/morning.md:1 +msgid "# Day 2: Morning Exercises" msgstr "" -#: src/exercises/day-1/book-library.md:28 -#: src/exercises/day-1/solutions-afternoon.md:27 -msgid "" -"struct Book {\n" -" title: String,\n" -" year: u16,\n" -"}" +#: src/exercises/day-2/morning.md:3 +msgid "We will look at implementing methods in two contexts:" msgstr "" -#: src/exercises/day-1/book-library.md:33 -#: src/exercises/day-1/solutions-afternoon.md:32 +#: src/exercises/day-2/morning.md:5 msgid "" -"impl Book {\n" -" // This is a constructor, used below.\n" -" fn new(title: &str, year: u16) -> Book {\n" -" Book {\n" -" title: String::from(title),\n" -" year,\n" -" }\n" -" }\n" -"}" +"* Simple struct which tracks health statistics.\n" +"\n" +"* Multiple structs and enums for a drawing library." +msgstr "" + +#: src/exercises/day-2/health-statistics.md:1 +msgid "# Health Statistics" msgstr "" -#: src/exercises/day-1/book-library.md:43 +#: src/exercises/day-2/health-statistics.md:3 msgid "" -"// 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" -"}" +"You're working on implementing a health-monitoring system. As part of that, " +"you\n" +"need to keep track of users' health statistics." msgstr "" -#: src/exercises/day-1/book-library.md:50 +#: src/exercises/day-2/health-statistics.md:6 msgid "" -"impl Library {\n" -" fn new() -> Library {\n" -" unimplemented!()\n" -" }" +"You'll start with some stubbed functions in an `impl` block as well as a " +"`User`\n" +"struct definition. Your goal is to implement the stubbed out methods on the\n" +"`User` `struct` defined in the `impl` block." msgstr "" -#: src/exercises/day-1/book-library.md:55 +#: src/exercises/day-2/health-statistics.md:10 msgid "" -" //fn len(self) -> usize {\n" -" // unimplemented!()\n" -" //}" +"Copy the code below to and fill in the " +"missing\n" +"methods:" msgstr "" -#: src/exercises/day-1/book-library.md:59 +#: src/exercises/day-2/health-statistics.md:13 msgid "" -" //fn is_empty(self) -> bool {\n" -" // unimplemented!()\n" -" //}" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"struct User {\n" +" name: String,\n" +" age: u32,\n" +" weight: f32,\n" +"}\n" +"\n" +"impl User {\n" +" pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn name(&self) -> &str {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn age(&self) -> u32 {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn weight(&self) -> f32 {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn set_age(&mut self, new_age: u32) {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn set_weight(&mut self, new_weight: f32) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_weight() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.weight(), 155.2);\n" +"}\n" +"\n" +"#[test]\n" +"fn test_set_age() {\n" +" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.age(), 32);\n" +" bob.set_age(33);\n" +" assert_eq!(bob.age(), 33);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:1 +msgid "# Polygon Struct" msgstr "" -#: src/exercises/day-1/book-library.md:63 +#: src/exercises/day-2/points-polygons.md:3 msgid "" -" //fn add_book(self, book: Book) {\n" -" // unimplemented!()\n" -" //}" +"We will create a `Polygon` struct which contain some points. Copy the code " +"below\n" +"to and fill in the missing methods to make " +"the\n" +"tests pass:" msgstr "" -#: src/exercises/day-1/book-library.md:67 +#: src/exercises/day-2/points-polygons.md:7 msgid "" -" //fn print_books(self) {\n" -" // unimplemented!()\n" -" //}" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub struct Point {\n" +" // add fields\n" +"}\n" +"\n" +"impl Point {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Polygon {\n" +" // add fields\n" +"}\n" +"\n" +"impl Polygon {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Circle {\n" +" // add fields\n" +"}\n" +"\n" +"impl Circle {\n" +" // add methods\n" +"}\n" +"\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" msgstr "" -#: src/exercises/day-1/book-library.md:71 +#: src/exercises/day-2/points-polygons.md:117 msgid "" -" //fn oldest_book(self) -> Option<&Book> {\n" -" // unimplemented!()\n" -" //}\n" -"}" +"Since the method signatures are missing from the problem statements, the key " +"part\n" +"of the exercise is to specify those correctly. You don't have to modify the " +"tests." msgstr "" -#: src/exercises/day-1/book-library.md:76 -msgid "" -"// This shows the desired behavior. Uncomment the code below and\n" -"// implement the missing methods. You will need to update the\n" -"// method signatures, including the \"self\" parameter! You may\n" -"// also need to update the variable bindings within main.\n" -"fn main() {\n" -" let library = Library::new();" +#: src/exercises/day-2/points-polygons.md:120 +msgid "Other interesting parts of the exercise:" msgstr "" -#: src/exercises/day-1/book-library.md:83 +#: src/exercises/day-2/points-polygons.md:122 msgid "" -" //println!(\"Our 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" -" //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" -" //}\n" -" //\n" -" //println!(\"Our library has {} books\", library.len());\n" -"}\n" -"```" +"* Derive a `Copy` trait for some structs, as in tests the methods sometimes " +"don't borrow their arguments.\n" +"* Discover that `Add` trait must be implemented for two objects to be " +"addable via \"+\". Note that we do not discuss generics until Day 3." msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:1 -msgid "# Iterators and Ownership" +#: src/control-flow.md:1 +msgid "# Control Flow" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:3 +#: src/control-flow.md:3 msgid "" -"The ownership model of Rust affects many APIs. An example of this is the\n" -"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and\n" -"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator." -"html)\n" -"traits." +"As we have seen, `if` is an expression in Rust. It is used to conditionally\n" +"evaluate one of two blocks, but the blocks can have a value which then " +"becomes\n" +"the value of the `if` expression. Other control flow expressions work " +"similarly\n" +"in Rust." msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:8 -msgid "## `Iterator`" +#: src/control-flow/blocks.md:1 +msgid "# Blocks" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:10 +#: src/control-flow/blocks.md:3 msgid "" -"Traits are like interfaces: they describe behavior (methods) for a type. " -"The\n" -"`Iterator` trait simply says that you can call `next` until you get `None` " -"back:" +"A block in Rust has a value and a type: the value is the last expression of " +"the\n" +"block:" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:13 +#: src/control-flow/blocks.md:6 msgid "" -"```rust\n" -"pub trait Iterator {\n" -" type Item;\n" -" fn next(&mut self) -> Option;\n" +"```rust,editable\n" +"fn main() {\n" +" let x = {\n" +" let y = 10;\n" +" println!(\"y: {y}\");\n" +" let z = {\n" +" let w = {\n" +" 3 + 4\n" +" };\n" +" println!(\"w: {w}\");\n" +" y * w\n" +" };\n" +" println!(\"z: {z}\");\n" +" z - y\n" +" };\n" +" println!(\"x: {x}\");\n" "}\n" "```" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:20 -msgid "You use this trait like this:" +#: src/control-flow/blocks.md:25 +msgid "" +"The same rule is used for functions: the value of the function body is the\n" +"return value:" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:22 +#: src/control-flow/blocks.md:28 msgid "" "```rust,editable\n" +"fn double(x: i32) -> i32 {\n" +" x + x\n" +"}\n" +"\n" "fn main() {\n" -" let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:27 -msgid "" -" println!(\"v[0]: {:?}\", iter.next());\n" -" println!(\"v[1]: {:?}\", iter.next());\n" -" println!(\"v[2]: {:?}\", iter.next());\n" -" println!(\"No more items: {:?}\", iter.next());\n" +" println!(\"doubled: {}\", double(7));\n" "}\n" "```" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:34 -msgid "What is the type returned by the iterator? Test your answer here:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:36 +#: src/control-flow/blocks.md:38 msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();" +"However if the last expression ends with `;`, then the resulting value and " +"type is `()`." msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:41 -#: src/exercises/day-1/iterators-and-ownership.md:78 +#: src/control-flow/blocks.md:43 msgid "" -" let v0: Option<..> = iter.next();\n" -" println!(\"v0: {v0:?}\");\n" -"}\n" -"```" +"* The point of this slide is to show that blocks have a type and value in " +"Rust. \n" +"* You can show how the value of the block changes by changing the last line " +"in the block. For instance, adding/removing a semicolon or using a " +"`return`.\n" +" " msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:46 -msgid "Why is this type used?" +#: src/control-flow/if-expressions.md:1 +msgid "# `if` expressions" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:48 -msgid "## `IntoIterator`" +#: src/control-flow/if-expressions.md:3 +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/exercises/day-1/iterators-and-ownership.md:50 +#: src/control-flow/if-expressions.md:7 msgid "" -"The `Iterator` trait tells you how to _iterate_ once you have created an\n" -"iterator. The related trait `IntoIterator` tells you how to create the " -"iterator:" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" if x % 2 == 0 {\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:53 +#: src/control-flow/if-expressions.md:18 msgid "" -"```rust\n" -"pub trait IntoIterator {\n" -" type Item;\n" -" type IntoIter: Iterator;" +"In addition, you can use `if` as an expression. The last expression of each\n" +"block becomes the value of the `if` expression:" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:58 +#: src/control-flow/if-expressions.md:22 msgid "" -" fn into_iter(self) -> Self::IntoIter;\n" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" "}\n" "```" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:62 +#: src/control-flow/if-expressions.md:35 msgid "" -"The syntax here means that every implementation of `IntoIterator` must\n" -"declare two types:" +"Because `if` is an expression and must have a particular type, both of its " +"branch blocks must have the same type. Consider showing what happens if you " +"add `;` after `x / 2` in the second example." msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:65 -msgid "" -"* `Item`: the type we iterate over, such as `i8`,\n" -"* `IntoIter`: the `Iterator` type returned by the `into_iter` method." +#: src/control-flow/if-let-expressions.md:1 +msgid "# `if let` expressions" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:68 +#: src/control-flow/if-let-expressions.md:3 msgid "" -"Note that `IntoIter` and `Item` are linked: the iterator must have the same\n" -"`Item` type, which means that it returns `Option`" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:71 -msgid "Like before, what is the type returned by the iterator?" +"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/exercises/day-1/iterators-and-ownership.md:73 +#: src/control-flow/if-let-expressions.md:7 msgid "" -"```rust,editable,compile_fail\n" +"```rust,editable\n" "fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::" -"from(\"bar\")];\n" -" let mut iter = v.into_iter();" +" let arg = std::env::args().next();\n" +" if let Some(value) = arg {\n" +" println!(\"Program name: {value}\");\n" +" } else {\n" +" println!(\"Missing name?\");\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:83 -msgid "## `for` Loops" +#: src/control-flow/if-let-expressions.md:18 +#: src/control-flow/while-let-expressions.md:21 +#: src/control-flow/match-expressions.md:23 +msgid "" +"See [pattern matching](../pattern-matching.md) for more details on patterns " +"in\n" +"Rust." msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:85 +#: src/control-flow/if-let-expressions.md:23 msgid "" -"Now that we know both `Iterator` and `IntoIterator`, we can build `for` " -"loops.\n" -"They call `into_iter()` on an expression and iterates over the resulting\n" -"iterator:" +"* `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" +"* A common usage is handling `Some` values when working with `Option`.\n" +"* Unlike `match`, `if let` does not support guard clauses for pattern " +"matching.\n" +"* Since 1.65, a similar [let-else](https://doc.rust-lang.org/rust-by-example/" +"flow_control/let_else.html) construct allows to do a destructuring " +"assignment, or if it fails, have a non-returning block branch (panic/return/" +"break/continue):\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" println!(\"{:?}\", second_word_to_upper(\"foo bar\"));\n" +" }\n" +" \n" +" fn second_word_to_upper(s: &str) -> Option {\n" +" let mut it = s.split(' ');\n" +" let (Some(_), Some(item)) = (it.next(), it.next()) else {\n" +" return None;\n" +" };\n" +" Some(item.to_uppercase())\n" +" }" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:89 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];" +#: src/control-flow/while-expressions.md:1 +msgid "# `while` loops" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:93 +#: src/control-flow/while-expressions.md:3 msgid "" -" for word in &v {\n" -" println!(\"word: {word}\");\n" -" }" +"The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-" +"expr.html#predicate-loops)\n" +"works very similar to other languages:" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:97 +#: src/control-flow/while-expressions.md:6 msgid "" -" for word in v {\n" -" println!(\"word: {word}\");\n" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" while x != 1 {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" " }\n" +" println!(\"Final x: {x}\");\n" "}\n" "```" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:103 -msgid "What is the type of `word` in each loop?" +#: src/control-flow/while-let-expressions.md:1 +msgid "# `while let` loops" msgstr "" -#: src/exercises/day-1/iterators-and-ownership.md:105 +#: src/control-flow/while-let-expressions.md:3 msgid "" -"Experiment with the code above and then consult the documentation for " -"[`impl\n" -"IntoIterator for\n" -"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-" -"IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E)\n" -"and [`impl IntoIterator for\n" -"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-" -"for-%26%27a%20Vec%3CT%2C%20A%3E)\n" -"to check your answers." +"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 "" -#: src/welcome-day-2.md:1 -msgid "# Welcome to Day 2" +#: src/control-flow/while-let-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +"\n" +" while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/welcome-day-2.md:3 -msgid "Now that we have seen a fair amount of Rust, we will continue with:" +#: src/control-flow/while-let-expressions.md:17 +msgid "" +"Here the iterator returned by `v.iter()` will return a `Option` on " +"every\n" +"call to `next()`. It returns `Some(x)` until it is done, after which it " +"will\n" +"return `None`. The `while let` lets us keep iterating through all items." msgstr "" -#: src/welcome-day-2.md:5 -msgid "* Structs, enums, methods." +#: src/control-flow/while-let-expressions.md:26 +msgid "" +"* Point out that the `while let` loop will keep going as long as the value " +"matches the pattern.\n" +"* You could rewrite the `while let` loop as an infinite loop with an if " +"statement that breaks when there is no value to unwrap for `iter.next()`. " +"The `while let` provides syntactic sugar for the above scenario.\n" +" " msgstr "" -#: src/welcome-day-2.md:7 -msgid "* Pattern matching: destructuring enums, structs, and arrays." +#: src/control-flow/for-expressions.md:1 +msgid "# `for` loops" msgstr "" -#: src/welcome-day-2.md:9 +#: src/control-flow/for-expressions.md:3 msgid "" -"* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, " -"and\n" -" `continue`." +"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 "" -#: src/welcome-day-2.md:12 +#: src/control-flow/for-expressions.md:7 msgid "" -"* The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, " -"`Rc`\n" -" and `Arc`." +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +"\n" +" for x in v {\n" +" println!(\"x: {x}\");\n" +" }\n" +" \n" +" for i in (0..10).step_by(2) {\n" +" println!(\"i: {i}\");\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/welcome-day-2.md:15 -msgid "* Modules: visibility, paths, and filesystem hierarchy." +#: src/control-flow/for-expressions.md:21 +msgid "You can use `break` and `continue` here as usual." msgstr "" -#: src/structs.md:1 -msgid "# Structs" +#: src/control-flow/for-expressions.md:25 +msgid "" +"* Index iteration is not a special syntax in Rust for just that case.\n" +"* `(0..10)` is a range that implements an `Iterator` trait. \n" +"* `step_by` is a method that returns another `Iterator` that skips every " +"other element. \n" +"* Modify the elements in the vector and explain the compiler errors. Change " +"vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." msgstr "" -#: src/structs.md:3 -msgid "Like C and C++, Rust has support for custom structs:" +#: src/control-flow/loop-expressions.md:1 +msgid "# `loop` expressions" msgstr "" -#: src/structs.md:5 +#: src/control-flow/loop-expressions.md:3 msgid "" -"```rust,editable\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}" +"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/structs.md:11 -msgid "" -"fn main() {\n" -" let peter = Person {\n" -" name: String::from(\"Peter\"),\n" -" age: 27,\n" -" };" +#: src/control-flow/loop-expressions.md:6 +msgid "Here you must either `break` or `return` to stop the loop:" msgstr "" -#: src/structs.md:17 +#: src/control-flow/loop-expressions.md:8 msgid "" -" println!(\"{} is {} years old\", peter.name, peter.age);\n" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" loop {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" if x == 1 {\n" +" break;\n" +" }\n" +" }\n" +" println!(\"Final x: {x}\");\n" "}\n" "```" msgstr "" -#: src/structs/tuple-structs.md:1 -msgid "# Tuple Structs" +#: 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/structs/tuple-structs.md:3 -msgid "If the field names are unimportant, you can use a tuple struct:" +#: src/control-flow/match-expressions.md:1 +msgid "# `match` expressions" msgstr "" -#: src/structs/tuple-structs.md:5 +#: src/control-flow/match-expressions.md:3 msgid "" -"```rust,editable\n" -"struct Point(i32, i32);" +"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 "" -#: src/structs/tuple-structs.md:8 +#: src/control-flow/match-expressions.md:7 msgid "" +"```rust,editable\n" "fn main() {\n" -" let p = Point(17, 23);\n" -" println!(\"({}, {})\", p.0, p.1);\n" +" match std::env::args().next().as_deref() {\n" +" Some(\"cat\") => println!(\"Will do cat things\"),\n" +" Some(\"ls\") => println!(\"Will ls some files\"),\n" +" Some(\"mv\") => println!(\"Let's move some files\"),\n" +" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" +" None => println!(\"Hmm, no program name?\"),\n" +" _ => println!(\"Unknown program name!\"),\n" +" }\n" "}\n" "```" msgstr "" -#: src/structs/tuple-structs.md:14 -msgid "This is often used for single-field wrappers (called newtypes):" +#: src/control-flow/match-expressions.md:20 +msgid "" +"Like `if let`, each match arm must have the same type. The type is the last\n" +"expression of the block, if any. In the example above, the type is `()`." msgstr "" -#: src/structs/tuple-structs.md:16 +#: src/control-flow/match-expressions.md:28 msgid "" -"```rust,editable,compile_fail\n" -"struct PoundOfForce(f64);\n" -"struct Newtons(f64);" +"* Save the match expression to a variable and print it out.\n" +"* Remove `.as_deref()` and explain the error.\n" +" * `std::env::args().next()` returns an `Option`, but we cannot " +"match against `String`.\n" +" * `as_deref()` transforms an `Option` to `Option<&T::Target>`. In our " +"case, this turns `Option` into `Option<&str>`.\n" +" * We can now use pattern matching to match against the `&str` inside " +"`Option`." +msgstr "" + +#: src/control-flow/break-continue.md:1 +msgid "# `break` and `continue`" msgstr "" -#: src/structs/tuple-structs.md:20 +#: src/control-flow/break-continue.md:3 msgid "" -"fn compute_thruster_force() -> PoundOfForce {\n" -" todo!(\"Ask a rocket scientist at NASA\")\n" -"}" +"- 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/structs/tuple-structs.md:24 +#: src/control-flow/break-continue.md:7 msgid "" -"fn set_thruster_force(force: Newtons) {\n" -" // ...\n" -"}" +"Both `continue` and `break` can optionally take a label argument which is " +"used\n" +"to break out of nested loops:" msgstr "" -#: src/structs/tuple-structs.md:28 +#: src/control-flow/break-continue.md:10 msgid "" +"```rust,editable\n" "fn main() {\n" -" let force = compute_thruster_force();\n" -" set_thruster_force(force);\n" -"}" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +" 'outer: while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" let mut i = 0;\n" +" while i < x {\n" +" println!(\"x: {x}, i: {i}\");\n" +" i += 1;\n" +" if i == 3 {\n" +" break 'outer;\n" +" }\n" +" }\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/structs/tuple-structs.md:33 src/generics/trait-objects.md:86 -msgid "```" +#: src/control-flow/break-continue.md:28 +msgid "" +"In this case we break the outer loop after 3 iterations of the inner loop." msgstr "" -#: src/structs/field-shorthand.md:1 -msgid "# Field Shorthand Syntax" +#: src/std.md:1 +msgid "# Standard Library" msgstr "" -#: src/structs/field-shorthand.md:3 +#: src/std.md:3 msgid "" -"If you already have variables with the right names, then you can create the\n" -"struct using a shorthand:" +"Rust comes with a standard library which helps establish a set of common " +"types\n" +"used by Rust library and programs. This way, two libraries can work " +"together\n" +"smoothly because they both use the same `String` type." msgstr "" -#: src/structs/field-shorthand.md:6 src/methods.md:6 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}" +#: src/std.md:7 +msgid "The common vocabulary types include:" msgstr "" -#: src/structs/field-shorthand.md:13 +#: src/std.md:9 msgid "" -"impl Person {\n" -" fn new(name: String, age: u8) -> Person {\n" -" Person { name, age }\n" -" }\n" -"}" +"* [`Option` and `Result`](std/option-result.md) types: used for optional " +"values\n" +" and [error handling](error-handling.md).\n" +"\n" +"* [`String`](std/string.md): the default string type used for owned data.\n" +"\n" +"* [`Vec`](std/vec.md): a standard extensible vector.\n" +"\n" +"* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" +" algorithm.\n" +"\n" +"* [`Box`](std/box.md): an owned pointer for heap-allocated data.\n" +"\n" +"* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated " +"data." msgstr "" -#: src/structs/field-shorthand.md:19 +#: src/std.md:25 msgid "" -"fn main() {\n" -" let peter = Person::new(String::from(\"Peter\"), 27);\n" -" println!(\"{peter:?}\");\n" -"}\n" -"```" +" * In fact, Rust contains several layers of the Standard Library: `core`, " +"`alloc` and `std`. \n" +" * `core` includes the most basic types and functions that don't depend on " +"`libc`, allocator or\n" +" even the presence of an operating system. \n" +" * `alloc` includes types which require a global heap allocator, such as " +"`Vec`, `Box` and `Arc`.\n" +" * Embedded Rust applications often only use `core`, and sometimes `alloc`." msgstr "" -#: src/enums.md:1 -msgid "# Enums" +#: src/std/option-result.md:1 +msgid "# `Option` and `Result`" msgstr "" -#: src/enums.md:3 -msgid "" -"The `enum` keyword allows the creation of a type which has a few\n" -"different variants:" +#: src/std/option-result.md:3 +msgid "The types represent optional data:" msgstr "" -#: src/enums.md:6 +#: src/std/option-result.md:5 msgid "" "```rust,editable\n" -"fn generate_random_number() -> i32 {\n" -" 4 // Chosen by fair dice roll. Guaranteed to be random.\n" -"}" +"fn main() {\n" +" let numbers = vec![10, 20, 30];\n" +" let first: Option<&i8> = numbers.first();\n" +" println!(\"first: {first:?}\");\n" +"\n" +" let idx: Result = numbers.binary_search(&10);\n" +" println!(\"idx: {idx:?}\");\n" +"}\n" +"```" msgstr "" -#: src/enums.md:11 +#: src/std/option-result.md:18 msgid "" -"#[derive(Debug)]\n" -"enum CoinFlip {\n" -" Heads,\n" -" Tails,\n" -"}" +"* `Option` and `Result` are widely used not just in the standard library.\n" +"* `Option<&T>` has zero space overhead compared to `&T`.\n" +"* `Result` is the standard type to implement error handling as we will see " +"on Day 3.\n" +"* `binary_search` returns `Result`.\n" +" * If found, `Result::Ok` holds the index where the element is found.\n" +" * Otherwise, `Result::Err` contains the index where such an element should " +"be inserted." +msgstr "" + +#: src/std/string.md:1 +msgid "# String" msgstr "" -#: src/enums.md:17 +#: src/std/string.md:3 msgid "" -"fn flip_coin() -> CoinFlip {\n" -" let random_number = generate_random_number();\n" -" if random_number % 2 == 0 {\n" -" return CoinFlip::Heads;\n" -" } else {\n" -" return CoinFlip::Tails;\n" -" }\n" -"}" +"[`String`][1] is the standard heap-allocated growable UTF-8 string buffer:" msgstr "" -#: src/enums.md:26 +#: src/std/string.md:5 msgid "" +"```rust,editable\n" "fn main() {\n" -" println!(\"You got: {:?}\", flip_coin());\n" +" let mut s1 = String::new();\n" +" s1.push_str(\"Hello\");\n" +" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());\n" +"\n" +" let mut s2 = String::with_capacity(s1.len() + 1);\n" +" s2.push_str(&s1);\n" +" s2.push('!');\n" +" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());\n" +"\n" +" let s3 = String::from(\"🇨🇭\");\n" +" println!(\"s3: len = {}, number of chars = {}\", s3.len(),\n" +" s3.chars().count());\n" "}\n" "```" msgstr "" -#: src/enums/variant-payloads.md:1 -msgid "# Variant Payloads" -msgstr "" - -#: src/enums/variant-payloads.md:3 +#: src/std/string.md:22 msgid "" -"You can define richer enums where the variants carry data. You can then use " -"the\n" -"`match` statement to extract the data from each variant:" +"`String` implements [`Deref`][2], which means that you can " +"call all\n" +"`str` methods on a `String`." msgstr "" -#: src/enums/variant-payloads.md:6 +#: src/std/string.md:30 msgid "" -"```rust,editable\n" -"enum WebEvent {\n" -" PageLoad, // Variant without payload\n" -" KeyPress(char), // Tuple struct variant\n" -" Click { x: i64, y: i64 }, // Full struct variant\n" -"}" +"* `String::new` returns a new empty string, use `String::with_capacity` when " +"you know how much data you want to push to the string.\n" +"* `String::len` returns the size of the `String` in bytes (which can be " +"different from its length in characters).\n" +"* `String::chars` returns an iterator over the actual characters. Note that " +"a `char` can be different from what a human will consider a \"character\" " +"due to [grapheme clusters](https://docs.rs/unicode-segmentation/latest/" +"unicode_segmentation/struct.Graphemes.html).\n" +"* When people refer to strings they could either be talking about `&str` or " +"`String`. \n" +"* When a type implements `Deref`, the compiler will let you " +"transparently call methods from `T`.\n" +" * `String` implements `Deref` which transparently gives it " +"access to `str`'s methods.\n" +" * 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`:\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/enums/variant-payloads.md:13 -msgid "" -"#[rustfmt::skip]\n" -"fn inspect(event: WebEvent) {\n" -" match event {\n" -" WebEvent::PageLoad => println!(\"page loaded\"),\n" -" WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" -" WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" -" }\n" -"}" +#: src/std/vec.md:1 +msgid "# `Vec`" msgstr "" -#: src/enums/variant-payloads.md:22 -msgid "" -"fn main() {\n" -" let load = WebEvent::PageLoad;\n" -" let press = WebEvent::KeyPress('x');\n" -" let click = WebEvent::Click { x: 20, y: 80 };" +#: src/std/vec.md:3 +msgid "[`Vec`][1] is the standard resizable heap-allocated buffer:" msgstr "" -#: src/enums/variant-payloads.md:27 +#: src/std/vec.md:5 msgid "" -" inspect(load);\n" -" inspect(press);\n" -" inspect(click);\n" +"```rust,editable\n" +"fn main() {\n" +" let mut v1 = Vec::new();\n" +" v1.push(42);\n" +" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());\n" +"\n" +" let mut v2 = Vec::with_capacity(v1.len() + 1);\n" +" v2.extend(v1.iter());\n" +" v2.push(9999);\n" +" println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());\n" +"\n" +" // Canonical macro to initialize a vector with elements.\n" +" let mut v3 = vec![0, 0, 1, 2, 3, 4];\n" +"\n" +" // Retain only the even elements.\n" +" v3.retain(|x| x % 2 == 0);\n" +" println!(\"{v3:?}\");\n" +"\n" +" // Remove consecutive duplicates.\n" +" v3.dedup();\n" +" println!(\"{v3:?}\");\n" "}\n" "```" msgstr "" -#: src/enums/variant-payloads.md:35 +#: src/std/vec.md:29 msgid "" -"* In the above example, accessing the `char` in `KeyPress`, or `x` and `y` " -"in `Click` only works within a `match` statement.\n" -"* `match` inspects a hidden discriminant field in the `enum`.\n" -"* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::" -"Click(Click)` with a top level `struct Click { ... }`. The inlined version " -"cannot implement traits, for example." +"`Vec` implements [`Deref`][2], which means that you can call " +"slice\n" +"methods on a `Vec`." msgstr "" -#: src/enums/sizes.md:1 -msgid "# Enum Sizes" +#: src/std/vec.md:37 +msgid "" +"* `Vec` is a type of collection, along with `String` and `HashMap`. The data " +"it contains is stored\n" +" on the heap. This means the amount of data doesn't need to be known at " +"compile time. It can grow\n" +" or shrink at runtime.\n" +"* Notice how `Vec` is a generic type too, but you don't have to specify " +"`T` explicitly. As always\n" +" with Rust type inference, the `T` was established during the first `push` " +"call.\n" +"* `vec![...]` is a canonical macro to use instead of `Vec::new()` and it " +"supports adding initial\n" +" elements to the vector.\n" +"* To index the vector you use `[` `]`, but they will panic if out of bounds. " +"Alternatively, using\n" +" `get` will return an `Option`. The `pop` function will remove the last " +"element.\n" +"* Show iterating over a vector and mutating the value:\n" +" `for e in &mut v { *e += 50; }`" msgstr "" -#: src/enums/sizes.md:3 -msgid "" -"Rust enums are packed tightly, taking constraints due to alignment into " -"account:" +#: src/std/hashmap.md:1 +msgid "# `HashMap`" msgstr "" -#: src/enums/sizes.md:5 +#: src/std/hashmap.md:3 +msgid "Standard hash map with protection against HashDoS attacks:" +msgstr "" + +#: src/std/hashmap.md:5 msgid "" "```rust,editable\n" -"use std::mem::{align_of, size_of};" +"use std::collections::HashMap;\n" +"\n" +"fn main() {\n" +" let mut page_counts = HashMap::new();\n" +" page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), " +"207);\n" +" page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" +" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);\n" +"\n" +" if !page_counts.contains_key(\"Les Misérables\") {\n" +" println!(\"We know about {} books, but not Les Misérables.\",\n" +" page_counts.len());\n" +" }\n" +"\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in " +"Wonderland\"] {\n" +" match page_counts.get(book) {\n" +" Some(count) => println!(\"{book}: {count} pages\"),\n" +" None => println!(\"{book} is unknown.\")\n" +" }\n" +" }\n" +"\n" +" // Use the .entry() method to insert a value if nothing is found.\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in " +"Wonderland\"] {\n" +" let page_count: &mut i32 = page_counts.entry(book.to_string())." +"or_insert(0);\n" +" *page_count += 1;\n" +" }\n" +"\n" +" println!(\"{page_counts:#?}\");\n" +"}\n" +"```" msgstr "" -#: src/enums/sizes.md:8 -msgid "" -"macro_rules! dbg_size {\n" -" ($t:ty) => {\n" -" println!(\"{}: size {} bytes, align: {} bytes\",\n" -" stringify!($t), size_of::<$t>(), align_of::<$t>());\n" -" };\n" -"}" +#: src/std/hashmap.md:38 +msgid "" +"* `HashMap` is not defined in the prelude and needs to be brought into " +"scope.\n" +"* Try the following lines of code. The first line will see if a book is in " +"the hashmap and if not return an alternative value. The second line will " +"insert the alternative value in the hashmap if the book is not found.\n" +"\n" +" ```rust,ignore\n" +" let pc1 = page_counts\n" +" .get(\"Harry Potter and the Sorcerer's Stone \")\n" +" .unwrap_or(&336);\n" +" let pc2 = page_counts\n" +" .entry(\"The Hunger Games\".to_string())\n" +" .or_insert(374);\n" +" ```\n" +"* Unlike `vec!`, there is unfortunately no standard `hashmap!` macro.\n" +" * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], " +"which allows us to easily initialize a hash map from a literal array:\n" +"\n" +" ```rust,ignore\n" +" let page_counts = HashMap::from([\n" +" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" +" (\"The Hunger Games\".to_string(), 374),\n" +" ]);\n" +" ```\n" +"\n" +" * Alternatively HashMap can be built from any `Iterator` which yields key-" +"value tuples.\n" +"* We are showing `HashMap`, and avoid using `&str` as key to " +"make examples easier. Using references in collections can, of course, be " +"done,\n" +" but it can lead into complications with the borrow checker.\n" +" * Try removing `to_string()` from the example above and see if it still " +"compiles. Where do you think we might run into issues?" msgstr "" -#: src/enums/sizes.md:15 -msgid "" -"enum Foo {\n" -" A,\n" -" B,\n" -"}" +#: src/std/box.md:1 +msgid "# `Box`" +msgstr "" + +#: src/std/box.md:3 +msgid "[`Box`][1] is an owned pointer to data on the heap:" msgstr "" -#: src/enums/sizes.md:20 +#: src/std/box.md:5 msgid "" +"```rust,editable\n" "fn main() {\n" -" dbg_size!(Foo);\n" -" dbg_size!(bool);\n" -" dbg_size!(Option);\n" -" dbg_size!(&i32);\n" -" dbg_size!(Option<&i32>);\n" +" let five = Box::new(5);\n" +" println!(\"five: {}\", *five);\n" "}\n" "```" msgstr "" -#: src/enums/sizes.md:29 +#: src/std/box.md:13 msgid "" -"* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout." -"html)." +"```bob\n" +" Stack Heap\n" +".- - - - - - -. .- - - - - - -.\n" +": : : :\n" +": five : : :\n" +": +-----+ : : +-----+ :\n" +": | o---|---+-----+-->| 5 | :\n" +": +-----+ : : +-----+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - -' `- - - - - - -'\n" +"```" msgstr "" -#: src/enums/sizes.md:33 +#: src/std/box.md:26 msgid "" -"* `Option` is another example of tight packing.\n" -"* For [some types](https://doc.rust-lang.org/std/option/#representation), " -"Rust guarantees that `size_of::()` equals `size_of::>()`.\n" -"* Zero-sized types allow for efficient implementation of `HashSet` using " -"`HashMap` with `()` as the value." +"`Box` implements `Deref`, which means that you can [call " +"methods\n" +"from `T` directly on a `Box`][2]." msgstr "" -#: src/methods.md:3 +#: src/std/box.md:34 msgid "" -"Rust allows you to associate functions with your new types. You do this with " -"an\n" -"`impl` block:" +"* `Box` is like `std::unique_ptr` in C++, except that it's guaranteed to be " +"not null. \n" +"* In the above example, you can even leave out the `*` in the `println!` " +"statement thanks to `Deref`. \n" +"* A `Box` can be useful when you:\n" +" * have a type whose size that can't be known at compile time, but the " +"Rust compiler wants to know an exact size.\n" +" * want to transfer ownership of a large amount of data. To avoid copying " +"large amounts of data on the stack, instead store the data on the heap in a " +"`Box` so only the pointer is moved." +msgstr "" + +#: src/std/box-recursive.md:1 +msgid "# Box with Recursive Data Structures" msgstr "" -#: src/methods.md:13 +#: src/std/box-recursive.md:3 msgid "" -"impl Person {\n" -" fn say_hello(&self) {\n" -" println!(\"Hello, my name is {}\", self.name);\n" -" }\n" -"}" +"Recursive data types or data types with dynamic sizes need to use a `Box`:" msgstr "" -#: src/methods.md:19 +#: src/std/box-recursive.md:5 src/std/box-niche.md:3 msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"enum List {\n" +" Cons(T, Box>),\n" +" Nil,\n" +"}\n" +"\n" "fn main() {\n" -" let peter = Person {\n" -" name: String::from(\"Peter\"),\n" -" age: 27,\n" -" };\n" -" peter.say_hello();\n" +" let list: List = List::Cons(1, Box::new(List::Cons(2, Box::" +"new(List::Nil))));\n" +" println!(\"{list:?}\");\n" "}\n" "```" msgstr "" -#: src/methods/receiver.md:1 -msgid "# Method Receiver" -msgstr "" - -#: src/methods/receiver.md:3 -msgid "" -"The `&self` above indicates that the method borrows the object immutably. " -"There\n" -"are other possible receivers for a method:" -msgstr "" - -#: src/methods/receiver.md:6 +#: src/std/box-recursive.md:18 +#, fuzzy msgid "" -"* `&self`: borrows the object from the caller using a shared and immutable\n" -" reference. The object can be used again afterwards.\n" -"* `&mut self`: borrows the object from the caller using a unique and " -"mutable\n" -" reference. The object can be used again afterwards.\n" -"* `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" -"* No receiver: this becomes a static method on the struct. Typically used " -"to\n" -" create constructors which are called `new` by convention." +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - " +"- -.\n" +": : : :\n" +": " +"list : : :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----" +"+ :\n" +": | Cons | 1 | o--+----+-----+--->| Cons | 2 | o--+--->| Nil | // | // " +"| :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----" +"+ :\n" +": : : :\n" +": : : :\n" +"'- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - " +"- -'\n" +"```" msgstr "" +"```bob\n" +" Stak Bunke\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | a | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" -#: src/methods/receiver.md:17 +#: src/std/box-recursive.md:33 msgid "" -"Beyond variants on `self`, there are also\n" -"[special wrapper types](https://doc.rust-lang.org/reference/special-types-" -"and-traits.html)\n" -"allowed to be receiver types, such as `Box`." -msgstr "" - -#: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 -msgid "# Example" +"* If the `Box` was not used here and we attempted to embed a `List` directly " +"into the `List`,\n" +"the compiler would not compute a fixed size of the struct in memory, it " +"would look infinite.\n" +"\n" +"* `Box` solves this problem as it has the same size as a regular pointer and " +"just points at the next\n" +"element of the `List` in the heap.\n" +"\n" +"* Remove the `Box` in the List definition and show the compiler error. " +"\"Recursive with indirection\" is a hint you might want to use a Box or " +"reference of some kind, instead of storing a value directly. \n" +" " msgstr "" -#: src/methods/example.md:3 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Race {\n" -" name: String,\n" -" laps: Vec,\n" -"}" +#: src/std/box-niche.md:1 +msgid "# Niche Optimization" msgstr "" -#: src/methods/example.md:10 +#: src/std/box-niche.md:16 msgid "" -"impl Race {\n" -" fn new(name: &str) -> Race { // No receiver, a static method\n" -" Race { name: String::from(name), laps: Vec::new() }\n" -" }" +"A `Box` cannot be empty, so the pointer is always valid and non-`null`. " +"This\n" +"allows the compiler to optimize the memory layout:" msgstr "" -#: src/methods/example.md:15 +#: src/std/box-niche.md:19 +#, fuzzy msgid "" -" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write " -"access to self\n" -" self.laps.push(lap);\n" -" }" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - " +"-.\n" +": : : :\n" +": " +"list : : :\n" +": +----+----+ : : +----+----+ +----+------" +"+ :\n" +": | 1 | o--+-----------+-----+--->| 2 | o--+--->| // | null " +"| :\n" +": +----+----+ : : +----+----+ +----+------" +"+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - " +"-'\n" +"```" msgstr "" +"```bob\n" +" Stak Bunke\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | a | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" -#: src/methods/example.md:19 -msgid "" -" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" -" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" -" for (idx, lap) in self.laps.iter().enumerate() {\n" -" println!(\"Lap {idx}: {lap} sec\");\n" -" }\n" -" }" +#: src/std/rc.md:1 +msgid "# `Rc`" msgstr "" -#: src/methods/example.md:26 +#: src/std/rc.md:3 msgid "" -" fn finish(self) { // Exclusive ownership of self\n" -" let total = self.laps.iter().sum::();\n" -" println!(\"Race {} is finished, total lap time: {}\", self.name, " -"total);\n" -" }\n" -"}" +"[`Rc`][1] is a reference-counted shared pointer. Use this when you need to " +"refer\n" +"to the same data from multiple places:" msgstr "" -#: src/methods/example.md:32 +#: src/std/rc.md:6 msgid "" +"```rust,editable\n" +"use std::rc::Rc;\n" +"\n" "fn main() {\n" -" let mut race = Race::new(\"Monaco Grand Prix\");\n" -" race.add_lap(70);\n" -" race.add_lap(68);\n" -" race.print_laps();\n" -" race.add_lap(71);\n" -" race.print_laps();\n" -" race.finish();\n" +" let mut a = Rc::new(10);\n" +" let mut b = Rc::clone(&a);\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" "}\n" "```" msgstr "" -#: src/pattern-matching.md:1 -msgid "# Pattern Matching" -msgstr "" - -#: src/pattern-matching.md:3 +#: src/std/rc.md:18 msgid "" -"The `match` keyword let you match a value against one or more _patterns_. " -"The\n" -"comparisons are done from top to bottom and the first match wins." +"* If you need to mutate the data inside an `Rc`, you will need to wrap the " +"data in\n" +" a type such as [`Cell` or `RefCell`][2].\n" +"* See [`Arc`][3] if you are in a multi-threaded context.\n" +"* You can *downgrade* a shared pointer into a [`Weak`][4] pointer to create " +"cycles\n" +" that will get dropped." msgstr "" -#: src/pattern-matching.md:6 -msgid "The patterns can be simple values, similarly to `switch` in C and C++:" +#: src/std/rc.md:31 +msgid "" +"* `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" +"* `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" +"* `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 "" -#: src/pattern-matching.md:8 +#: src/std/rc.md:41 msgid "" "```rust,editable\n" +"use std::rc::{Rc, Weak};\n" +"use std::cell::RefCell;\n" +"\n" +"#[derive(Debug)]\n" +"struct Node {\n" +" value: i64,\n" +" parent: Option>>,\n" +" children: Vec>>,\n" +"}\n" +"\n" "fn main() {\n" -" let input = 'x';" -msgstr "" - -#: src/pattern-matching.md:12 -msgid "" -" match input {\n" -" 'q' => println!(\"Quitting\"),\n" -" 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" -" '0'..='9' => println!(\"Number input\"),\n" -" _ => println!(\"Something else\"),\n" -" }\n" +" let mut root = Rc::new(RefCell::new(Node {\n" +" value: 42,\n" +" parent: None,\n" +" children: vec![],\n" +" }));\n" +" let child = Rc::new(RefCell::new(Node {\n" +" value: 43,\n" +" children: vec![],\n" +" parent: Some(Rc::downgrade(&root))\n" +" }));\n" +" root.borrow_mut().children.push(child);\n" +"\n" +" println!(\"graph: {root:#?}\");\n" "}\n" "```" msgstr "" -#: src/pattern-matching.md:21 -msgid "The `_` pattern is a wildcard pattern which matches any value." +#: src/modules.md:1 +msgid "# Modules" msgstr "" -#: src/pattern-matching/destructuring-enums.md:1 -msgid "# Destructuring Enums" +#: src/modules.md:3 +msgid "We have seen how `impl` blocks let us namespace functions to a type." msgstr "" -#: src/pattern-matching/destructuring-enums.md:3 -msgid "" -"Patterns can also be used to bind variables to parts of your values. This is " -"how\n" -"you inspect the structure of your types. Let us start with a simple `enum` " -"type:" +#: src/modules.md:5 +msgid "Similarly, `mod` lets us namespace types and functions:" msgstr "" -#: src/pattern-matching/destructuring-enums.md:6 +#: src/modules.md:7 msgid "" "```rust,editable\n" -"enum Result {\n" -" Ok(i32),\n" -" Err(String),\n" -"}" -msgstr "" - -#: src/pattern-matching/destructuring-enums.md:12 -msgid "" -"fn divide_in_two(n: i32) -> Result {\n" -" if n % 2 == 0 {\n" -" Result::Ok(n / 2)\n" -" } else {\n" -" Result::Err(format!(\"cannot divide {} into two equal parts\", n))\n" +"mod foo {\n" +" pub fn do_something() {\n" +" println!(\"In the foo module\");\n" " }\n" -"}" -msgstr "" - -#: src/pattern-matching/destructuring-enums.md:20 -msgid "" -"fn main() {\n" -" let n = 100;\n" -" match divide_in_two(n) {\n" -" Result::Ok(half) => println!(\"{n} divided in two is {half}\"),\n" -" Result::Err(msg) => println!(\"sorry, an error happened: {msg}\"),\n" +"}\n" +"\n" +"mod bar {\n" +" pub fn do_something() {\n" +" println!(\"In the bar module\");\n" " }\n" "}\n" +"\n" +"fn main() {\n" +" foo::do_something();\n" +" bar::do_something();\n" +"}\n" "```" msgstr "" -#: src/pattern-matching/destructuring-enums.md:29 +#: src/modules.md:28 msgid "" -"Here we have used the arms to _destructure_ the `Result` value. In the " -"first\n" -"arm, `half` is bound to the value inside the `Ok` variant. In the second " -"arm,\n" -"`msg` is bound to the error message." +"* Packages provide functionality and include a `Cargo.toml` file that " +"describes how to build a bundle of 1+ crates.\n" +"* Crates are a tree of modules, where a binary crate creates an executable " +"and a library crate compiles to a library.\n" +"* Modules define organization, scope, and are the focus of this section." msgstr "" -#: src/pattern-matching/destructuring-structs.md:1 -msgid "# Destructuring Structs" +#: src/modules/visibility.md:1 +msgid "# Visibility" msgstr "" -#: src/pattern-matching/destructuring-structs.md:3 -msgid "You can also destructure `structs`:" +#: src/modules/visibility.md:3 +msgid "Modules are a privacy boundary:" msgstr "" -#: src/pattern-matching/destructuring-structs.md:5 +#: src/modules/visibility.md:5 msgid "" -"```rust,editable\n" -"struct Foo {\n" -" x: (u32, u32),\n" -" y: u32,\n" -"}" +"* Module items are private by default (hides implementation details).\n" +"* Parent and sibling items are always visible.\n" +"* In other words, if an item is visible in module `foo`, it's visible in all " +"the\n" +" descendants of `foo`." msgstr "" -#: src/pattern-matching/destructuring-structs.md:11 +#: src/modules/visibility.md:10 msgid "" -"#[rustfmt::skip]\n" -"fn main() {\n" -" let foo = Foo { x: (1, 2), y: 3 };\n" -" match foo {\n" -" Foo { x: (1, b), y } => println!(\"x.0 = 1, b = {b}, y = {y}\"),\n" -" Foo { y: 2, x: i } => println!(\"y = 2, i = {i:?}\"),\n" -" Foo { y, .. } => println!(\"y = {y}, other fields were " -"ignored\"),\n" +"```rust,editable\n" +"mod outer {\n" +" fn private() {\n" +" println!(\"outer::private\");\n" +" }\n" +"\n" +" pub fn public() {\n" +" println!(\"outer::public\");\n" +" }\n" +"\n" +" mod inner {\n" +" fn private() {\n" +" println!(\"outer::inner::private\");\n" +" }\n" +"\n" +" pub fn public() {\n" +" println!(\"outer::inner::public\");\n" +" super::private();\n" +" }\n" " }\n" "}\n" +"\n" +"fn main() {\n" +" outer::public();\n" +"}\n" "```" msgstr "" -#: src/pattern-matching/destructuring-arrays.md:1 -msgid "# Destructuring Arrays" +#: src/modules/visibility.md:39 +msgid "* Use the `pub` keyword to make modules public." msgstr "" -#: src/pattern-matching/destructuring-arrays.md:3 +#: src/modules/visibility.md:41 msgid "" -"You can destructure arrays, tuples, and slices by matching on their elements:" +"Additionally, there are advanced `pub(...)` specifiers to restrict the scope " +"of public visibility." msgstr "" -#: src/pattern-matching/destructuring-arrays.md:5 +#: src/modules/visibility.md:43 msgid "" -"```rust,editable\n" -"#[rustfmt::skip]\n" -"fn main() {\n" -" let triple = [0, -2, 3];\n" -" println!(\"Tell me about {triple:?}\");\n" -" match triple {\n" -" [0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" -" [1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" -" _ => println!(\"All elements were ignored\"),\n" -" }\n" -"}\n" -"```" +"* See the [Rust Reference](https://doc.rust-lang.org/reference/visibility-" +"and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself).\n" +"* Configuring `pub(crate)` visibility is a common pattern.\n" +"* Less commonly, you can give visibility to a specific path.\n" +"* In any case, visibility must be granted to an ancestor module (and all of " +"its descendants)." msgstr "" -#: src/pattern-matching/match-guards.md:1 -msgid "# Match Guards" +#: src/modules/paths.md:1 +msgid "# Paths" msgstr "" -#: src/pattern-matching/match-guards.md:3 -msgid "" -"When matching, you can add a _guard_ to a pattern. This is an arbitrary " -"Boolean\n" -"expression which will be executed if the pattern matches:" +#: src/modules/paths.md:3 +msgid "Paths are resolved as follows:" msgstr "" -#: src/pattern-matching/match-guards.md:6 +#: src/modules/paths.md:5 msgid "" -"```rust,editable\n" -"#[rustfmt::skip]\n" -"fn main() {\n" -" let pair = (2, -2);\n" -" println!(\"Tell me about {pair:?}\");\n" -" match pair {\n" -" (x, y) if x == y => println!(\"These are twins\"),\n" -" (x, y) if x + y == 0 => println!(\"Antimatter, kaboom!\"),\n" -" (x, _) if x % 2 == 1 => println!(\"The first one is odd\"),\n" -" _ => println!(\"No correlation...\"),\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-2/morning.md:1 -msgid "# Day 2: Morning Exercises" +"1. As a relative path:\n" +" * `foo` or `self::foo` refers to `foo` in the current module,\n" +" * `super::foo` refers to `foo` in the parent module.\n" +"\n" +"2. As an absolute path:\n" +" * `crate::foo` refers to `foo` in the root of the current crate,\n" +" * `bar::foo` refers to `foo` in the `bar` crate." msgstr "" -#: src/exercises/day-2/morning.md:3 -msgid "We will look at implementing methods in two contexts:" +#: 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/exercises/day-2/morning.md:5 -msgid "* Simple struct which tracks health statistics." +#: src/modules/paths.md:16 +msgid "" +"```rust,editable\n" +"use std::collections::HashSet;\n" +"use std::mem::transmute;\n" +"```" msgstr "" -#: src/exercises/day-2/morning.md:7 -msgid "* Multiple structs and enums for a drawing library." +#: src/modules/filesystem.md:1 +msgid "# Filesystem Hierarchy" msgstr "" -#: src/exercises/day-2/health-statistics.md:1 -msgid "# Health Statistics" +#: src/modules/filesystem.md:3 +msgid "The module content can be omitted:" msgstr "" -#: src/exercises/day-2/health-statistics.md:3 +#: src/modules/filesystem.md:5 msgid "" -"You're working on implementing a health-monitoring system. As part of that, " -"you\n" -"need to keep track of users' health statistics." +"```rust,editable,compile_fail\n" +"mod garden;\n" +"```" +msgstr "" + +#: src/modules/filesystem.md:9 +msgid "The `garden` module content is found at:" msgstr "" -#: src/exercises/day-2/health-statistics.md:6 +#: src/modules/filesystem.md:11 msgid "" -"You'll start with some stubbed functions in an `impl` block as well as a " -"`User`\n" -"struct definition. Your goal is to implement the stubbed out methods on the\n" -"`User` `struct` defined in the `impl` block." +"* `src/garden.rs` (modern Rust 2018 style)\n" +"* `src/garden/mod.rs` (older Rust 2015 style)" msgstr "" -#: src/exercises/day-2/health-statistics.md:10 -msgid "" -"Copy the code below to and fill in the " -"missing\n" -"methods:" +#: src/modules/filesystem.md:14 +msgid "Similarly, a `garden::vegetables` module can be found at:" msgstr "" -#: src/exercises/day-2/health-statistics.md:17 +#: src/modules/filesystem.md:16 msgid "" -"struct User {\n" -" name: String,\n" -" age: u32,\n" -" weight: f32,\n" -"}" +"* `src/garden/vegetables.rs` (modern Rust 2018 style)\n" +"* `src/garden/vegetables/mod.rs` (older Rust 2015 style)" msgstr "" -#: src/exercises/day-2/health-statistics.md:23 -msgid "" -"impl User {\n" -" pub fn new(name: String, age: u32, weight: f32) -> Self {\n" -" unimplemented!()\n" -" }" +#: src/modules/filesystem.md:19 +msgid "The `crate` root is in:" msgstr "" -#: src/exercises/day-2/health-statistics.md:28 +#: src/modules/filesystem.md:21 msgid "" -" pub fn name(&self) -> &str {\n" -" unimplemented!()\n" -" }" +"* `src/lib.rs` (for a library crate)\n" +"* `src/main.rs` (for a binary crate)" msgstr "" -#: src/exercises/day-2/health-statistics.md:32 +#: src/modules/filesystem.md:24 msgid "" -" pub fn age(&self) -> u32 {\n" -" unimplemented!()\n" -" }" +"Modules defined in files can be documented, too, using \"inner doc " +"comments\".\n" +"These document the item that contains them -- in this case, a module." msgstr "" -#: src/exercises/day-2/health-statistics.md:36 +#: src/modules/filesystem.md:27 msgid "" -" pub fn weight(&self) -> f32 {\n" -" unimplemented!()\n" -" }" +"```rust,editable,compile_fail\n" +"//! This module implements the garden, including a highly performant " +"germination\n" +"//! implementation.\n" +"\n" +"// Re-export types from this module.\n" +"pub use seeds::SeedPacket;\n" +"pub use garden::Garden;\n" +"\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/exercises/day-2/health-statistics.md:40 -msgid "" -" pub fn set_age(&mut self, new_age: u32) {\n" -" unimplemented!()\n" -" }" +#: 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" +" (It was mandatory in Rust 2015.)\n" +"\n" +" The following is valid:\n" +"\n" +" ```ignore\n" +" src/\n" +" ├── main.rs\n" +" ├── top_module.rs\n" +" └── top_module/\n" +" └── sub_module.rs\n" +" ```\n" +"\n" +"* The main reason for the change is to prevent many files named `mod.rs`, " +"which can be hard\n" +" to distinguish in IDEs.\n" +"\n" +"* Rust will look for modules in `modulename/mod.rs` and `modulename.rs`, but " +"this can be changed\n" +" with a compiler directive:\n" +"\n" +" ```rust,ignore\n" +" #[path = \"some/path.rs\"]\n" +" mod some_module { }\n" +" ```\n" +"\n" +" This is useful, for example, if you would like to place tests for a module " +"in a file named\n" +" `some_module_test.rs`, similar to the convention in Go." msgstr "" -#: src/exercises/day-2/health-statistics.md:44 -msgid "" -" pub fn set_weight(&mut self, new_weight: f32) {\n" -" unimplemented!()\n" -" }\n" -"}" +#: src/exercises/day-2/afternoon.md:1 +msgid "# Day 2: Afternoon Exercises" msgstr "" -#: src/exercises/day-2/health-statistics.md:49 -msgid "" -"fn main() {\n" -" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" -"}" +#: src/exercises/day-2/afternoon.md:3 +msgid "The exercises for this afternoon will focus on strings and iterators." msgstr "" -#: src/exercises/day-2/health-statistics.md:54 -msgid "" -"#[test]\n" -"fn test_weight() {\n" -" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" assert_eq!(bob.weight(), 155.2);\n" -"}" +#: src/exercises/day-2/luhn.md:1 +msgid "# Luhn Algorithm" msgstr "" -#: src/exercises/day-2/health-statistics.md:60 +#: src/exercises/day-2/luhn.md:3 msgid "" -"#[test]\n" -"fn test_set_age() {\n" -" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" assert_eq!(bob.age(), 32);\n" -" bob.set_age(33);\n" -" assert_eq!(bob.age(), 33);\n" -"}\n" -"```" +"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used " +"to\n" +"validate credit card numbers. The algorithm takes a string as input and does " +"the\n" +"following to validate the credit card number:" msgstr "" -#: src/exercises/day-2/points-polygons.md:1 -msgid "# Polygon Struct" +#: src/exercises/day-2/luhn.md:7 +msgid "" +"* Ignore all spaces. Reject number with less than two digits.\n" +"\n" +"* Moving from right to left, double every second digit: for the number " +"`1234`,\n" +" we double `3` and `1`.\n" +"\n" +"* After doubling a digit, sum the digits. So doubling `7` becomes `14` " +"which\n" +" becomes `5`.\n" +"\n" +"* Sum all the undoubled and doubled digits.\n" +"\n" +"* The credit card number is valid if the sum ends with `0`." msgstr "" -#: src/exercises/day-2/points-polygons.md:3 +#: src/exercises/day-2/luhn.md:19 msgid "" -"We will create a `Polygon` struct which contain some points. Copy the code " -"below\n" -"to and fill in the missing methods to make " -"the\n" -"tests pass:" +"Copy the following code to and implement the\n" +"function:" msgstr "" -#: src/exercises/day-2/points-polygons.md:7 src/exercises/day-2/luhn.md:23 -#: src/exercises/day-2/strings-iterators.md:12 +#: src/exercises/day-2/luhn.md:23 msgid "" "```rust\n" "// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" msgstr "" -#: src/exercises/day-2/points-polygons.md:11 -msgid "" -"pub struct Point {\n" -" // add fields\n" -"}" +#: src/exercises/day-2/strings-iterators.md:1 +msgid "# Strings and Iterators" msgstr "" -#: src/exercises/day-2/points-polygons.md:15 +#: src/exercises/day-2/strings-iterators.md:3 msgid "" -"impl Point {\n" -" // add methods\n" -"}" +"In this exercise, you are implementing a routing component of a web server. " +"The\n" +"server is configured with a number of _path prefixes_ which are matched " +"against\n" +"_request paths_. The path prefixes can contain a wildcard character which\n" +"matches a full segment. See the unit tests below." msgstr "" -#: src/exercises/day-2/points-polygons.md:19 +#: src/exercises/day-2/strings-iterators.md:8 msgid "" -"pub struct Polygon {\n" -" // add fields\n" -"}" +"Copy the following code to and make the tests\n" +"pass. Try avoiding allocating a `Vec` for your intermediate results:" msgstr "" -#: src/exercises/day-2/points-polygons.md:23 +#: src/exercises/day-2/strings-iterators.md:12 msgid "" -"impl Polygon {\n" -" // add methods\n" -"}" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/" +"abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/" +"books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/" +"publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/" +"publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-2/points-polygons.md:27 -msgid "" -"pub struct Circle {\n" -" // add fields\n" -"}" +#: src/welcome-day-3.md:1 +msgid "# Welcome to Day 3" msgstr "" -#: src/exercises/day-2/points-polygons.md:31 -msgid "" -"impl Circle {\n" -" // add methods\n" -"}" +#: src/welcome-day-3.md:3 +msgid "Today, we will cover some more advanced topics of Rust:" msgstr "" -#: src/exercises/day-2/points-polygons.md:35 +#: src/welcome-day-3.md:5 msgid "" -"pub enum Shape {\n" -" Polygon(Polygon),\n" -" Circle(Circle),\n" -"}" +"* Traits: deriving traits, default methods, and important standard library\n" +" traits.\n" +"\n" +"* Generics: generic data types, generic methods, monomorphization, and " +"trait\n" +" objects.\n" +"\n" +"* Error handling: panics, `Result`, and the try operator `?`.\n" +"\n" +"* Testing: unit tests, documentation tests, and integration tests.\n" +"\n" +"* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" +" functions." msgstr "" -#: src/exercises/day-2/points-polygons.md:40 src/testing/test-modules.md:15 -msgid "" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;" +#: src/generics.md:1 +msgid "# Generics" msgstr "" -#: src/exercises/day-2/points-polygons.md:44 -#: src/exercises/day-2/solutions-morning.md:165 +#: src/generics.md:3 msgid "" -" fn round_two_digits(x: f64) -> f64 {\n" -" (x * 100.0).round() / 100.0\n" -" }" +"Rust support generics, which lets you abstract an algorithm (such as " +"sorting)\n" +"over the types used in the algorithm." msgstr "" -#: src/exercises/day-2/points-polygons.md:48 -#: src/exercises/day-2/solutions-morning.md:169 -msgid "" -" #[test]\n" -" fn test_point_magnitude() {\n" -" let p1 = Point::new(12, 13);\n" -" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" -" }" +#: src/generics/data-types.md:1 +msgid "# Generic Data Types" msgstr "" -#: src/exercises/day-2/points-polygons.md:54 -#: src/exercises/day-2/solutions-morning.md:175 -msgid "" -" #[test]\n" -" fn test_point_dist() {\n" -" let p1 = Point::new(10, 10);\n" -" let p2 = Point::new(14, 13);\n" -" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" -" }" +#: src/generics/data-types.md:3 +msgid "You can use generics to abstract over the concrete field type:" msgstr "" -#: src/exercises/day-2/points-polygons.md:61 -#: src/exercises/day-2/solutions-morning.md:182 +#: src/generics/data-types.md:5 msgid "" -" #[test]\n" -" fn test_point_add() {\n" -" let p1 = Point::new(16, 16);\n" -" let p2 = p1 + Point::new(-4, 3);\n" -" assert_eq!(p2, Point::new(12, 19));\n" -" }" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point {\n" +" x: T,\n" +" y: T,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Point { x: 5, y: 10 };\n" +" let float = Point { x: 1.0, y: 4.0 };\n" +" println!(\"{integer:?} and {float:?}\");\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-2/points-polygons.md:68 -#: src/exercises/day-2/solutions-morning.md:189 +#: src/generics/data-types.md:21 msgid "" -" #[test]\n" -" fn test_polygon_left_most_point() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);" +"* Try declaring a new variable `let p = Point { x: 5, y: 10.0 };`.\n" +"\n" +"* Fix the code to allow points that have elements of different types." msgstr "" -#: src/exercises/day-2/points-polygons.md:73 -#: src/exercises/day-2/solutions-morning.md:194 -msgid "" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -" assert_eq!(poly.left_most_point(), Some(p1));\n" -" }" +#: src/generics/methods.md:1 +msgid "# Generic Methods" msgstr "" -#: src/exercises/day-2/points-polygons.md:79 -#: src/exercises/day-2/solutions-morning.md:200 -msgid "" -" #[test]\n" -" fn test_polygon_iter() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);" +#: src/generics/methods.md:3 +msgid "You can declare a generic type on your `impl` block:" msgstr "" -#: src/exercises/day-2/points-polygons.md:84 -#: src/exercises/day-2/solutions-morning.md:205 +#: src/generics/methods.md:5 msgid "" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(T, T);\n" +"\n" +"impl Point {\n" +" fn x(&self) -> &T {\n" +" &self.0 // + 10\n" +" }\n" +"\n" +" // fn set_x(&mut self, x: T)\n" +"}\n" +"\n" +"fn main() {\n" +" let p = Point(5, 10);\n" +" println!(\"p.x = {}\", p.x());\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-2/points-polygons.md:88 -#: src/exercises/day-2/solutions-morning.md:209 +#: src/generics/methods.md:25 msgid "" -" let points = poly.iter().cloned().collect::>();\n" -" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" -" }" +"* *Q:* Why `T` is specified twice in `impl Point {}`? Isn't that " +"redundant?\n" +" * This is because it is a generic implementation section for generic " +"type. They are independently generic.\n" +" * It means these methods are defined for any `T`.\n" +" * It is possible to write `impl Point { .. }`. \n" +" * `Point` is still generic and you can use `Point`, but methods " +"in this block will only be available for `Point`." msgstr "" -#: src/exercises/day-2/points-polygons.md:92 -msgid "" -" #[test]\n" -" fn test_shape_circumferences() {\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(Point::new(12, 13));\n" -" poly.add_point(Point::new(17, 11));\n" -" poly.add_point(Point::new(16, 16));\n" -" let shapes = vec![\n" -" Shape::from(poly),\n" -" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" -" ];\n" -" let circumferences = shapes\n" -" .iter()\n" -" .map(Shape::circumference)\n" -" .map(round_two_digits)\n" -" .collect::>();\n" -" assert_eq!(circumferences, vec![15.48, 31.42]);\n" -" }\n" -"}" +#: src/generics/monomorphization.md:1 +msgid "# Monomorphization" +msgstr "" + +#: src/generics/monomorphization.md:3 +msgid "Generic code is turned into non-generic code based on the call sites:" msgstr "" -#: src/exercises/day-2/points-polygons.md:111 src/exercises/day-2/luhn.md:68 -#: src/exercises/day-2/solutions-morning.md:233 +#: src/generics/monomorphization.md:5 msgid "" -"#[allow(dead_code)]\n" -"fn main() {}\n" +"```rust,editable\n" +"fn main() {\n" +" let integer = Some(5);\n" +" let float = Some(5.0);\n" +"}\n" "```" msgstr "" -#: src/control-flow.md:1 -msgid "# Control Flow" +#: src/generics/monomorphization.md:12 +msgid "behaves as if you wrote" msgstr "" -#: src/control-flow.md:3 +#: src/generics/monomorphization.md:14 msgid "" -"As we have seen, `if` is an expression in Rust. It is used to conditionally\n" -"evaluate one of two blocks, but the blocks can have a value which then " -"becomes\n" -"the value of the `if` expression. Other control flow expressions work " -"similarly\n" -"in Rust." +"```rust,editable\n" +"enum Option_i32 {\n" +" Some(i32),\n" +" None,\n" +"}\n" +"\n" +"enum Option_f64 {\n" +" Some(f64),\n" +" None,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Option_i32::Some(5);\n" +" let float = Option_f64::Some(5.0);\n" +"}\n" +"```" msgstr "" -#: src/control-flow/blocks.md:1 -msgid "# Blocks" +#: src/generics/monomorphization.md:31 +msgid "" +"This is a zero-cost abstraction: you get exactly the same result as if you " +"had\n" +"hand-coded the data structures without the abstraction." msgstr "" -#: src/control-flow/blocks.md:3 +#: src/traits.md:1 +msgid "# Traits" +msgstr "" + +#: src/traits.md:3 msgid "" -"A block in Rust has a value and a type: the value is the last expression of " -"the\n" -"block:" +"Rust lets you abstract over types with traits. They're similar to interfaces:" msgstr "" -#: src/control-flow/blocks.md:6 +#: src/traits.md:5 msgid "" "```rust,editable\n" +"trait Pet {\n" +" fn name(&self) -> String;\n" +"}\n" +"\n" +"struct Dog {\n" +" name: String,\n" +"}\n" +"\n" +"struct Cat;\n" +"\n" +"impl Pet for Dog {\n" +" fn name(&self) -> String {\n" +" self.name.clone()\n" +" }\n" +"}\n" +"\n" +"impl Pet for Cat {\n" +" fn name(&self) -> String {\n" +" String::from(\"The cat\") // No name, cats won't respond to it " +"anyway.\n" +" }\n" +"}\n" +"\n" +"fn greet(pet: &P) {\n" +" println!(\"Who's a cutie? {} is!\", pet.name());\n" +"}\n" +"\n" "fn main() {\n" -" let x = {\n" -" let y = 10;\n" -" println!(\"y: {y}\");\n" -" let z = {\n" -" let w = {\n" -" 3 + 4\n" -" };\n" -" println!(\"w: {w}\");\n" -" y * w\n" -" };\n" -" println!(\"z: {z}\");\n" -" z - y\n" -" };\n" -" println!(\"x: {x}\");\n" +" let fido = Dog { name: \"Fido\".into() };\n" +" greet(&fido);\n" +"\n" +" let captain_floof = Cat;\n" +" greet(&captain_floof);\n" "}\n" "```" msgstr "" -#: src/control-flow/blocks.md:25 -msgid "" -"The same rule is used for functions: the value of the function body is the\n" -"return value:" +#: src/traits/trait-objects.md:1 +msgid "# Trait Objects" msgstr "" -#: src/control-flow/blocks.md:28 +#: src/traits/trait-objects.md:3 msgid "" -"```rust,editable\n" -"fn double(x: i32) -> i32 {\n" -" x + x\n" -"}" +"Trait objects allow for values of different types, for instance in a " +"collection:" msgstr "" -#: src/control-flow/blocks.md:33 +#: src/traits/trait-objects.md:5 msgid "" +"```rust,editable\n" +"trait Pet {\n" +" fn name(&self) -> String;\n" +"}\n" +"\n" +"struct Dog {\n" +" name: String,\n" +"}\n" +"\n" +"struct Cat;\n" +"\n" +"impl Pet for Dog {\n" +" fn name(&self) -> String {\n" +" self.name.clone()\n" +" }\n" +"}\n" +"\n" +"impl Pet for Cat {\n" +" fn name(&self) -> String {\n" +" String::from(\"The cat\") // No name, cats won't respond to it " +"anyway.\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" println!(\"doubled: {}\", double(7));\n" +" let pets: Vec> = vec![\n" +" Box::new(Cat),\n" +" Box::new(Dog { name: String::from(\"Fido\") }),\n" +" ];\n" +" for pet in pets {\n" +" println!(\"Hello {}!\", pet.name());\n" +" }\n" "}\n" "```" msgstr "" -#: src/control-flow/if-expressions.md:1 -msgid "# `if` expressions" +#: src/traits/trait-objects.md:40 +msgid "Memory layout after allocating `pets`:" msgstr "" -#: src/control-flow/if-expressions.md:3 -msgid "You use `if` very similarly to how you would in other languages:" +#: src/traits/trait-objects.md:42 +#, fuzzy +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - " +"- -.\n" +": : : :\n" +": " +"pets : : :\n" +": +-----------+-------+ : : +-----+-----" +"+ :\n" +": | ptr | o---+---+-----+-->| o o | o o " +"| :\n" +": | len | 2 | : : +-|-|-+-|-|-" +"+ :\n" +": | capacity | 2 | : : | | | | +---------------" +"+ :\n" +": +-----------+-------+ : : | | | '-->| name: \"Fido\" " +"| :\n" +": : : | | | +---------------" +"+ :\n" +"`- - - - - - - - - - - - - -' : | | " +"| :\n" +" : | | | +----------------------" +"+ : \n" +" : | | '---->| \"::name\" " +"| :\n" +" : | | +----------------------" +"+ : \n" +" : | " +"| : \n" +" : | | +-" +"+ : \n" +" : | '-->|" +"\\| : \n" +" : | +-" +"+ : \n" +" : " +"| : \n" +" : | +----------------------" +"+ : \n" +" : '---->| \"::name\" " +"| : \n" +" : +----------------------" +"+ :\n" +" : :\n" +" '- - - - - - - - - - - - - - - - - - - - - " +"- -'\n" +"\n" +"```" +msgstr "" +"```bob\n" +" Stak Bunke\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | a | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" + +#: src/traits/trait-objects.md:72 +msgid "" +"* Types that implement a given trait may be of different sizes. This makes " +"it impossible to have things like `Vec` in the example above.\n" +"* `dyn Pet` is a way to tell the compiler about a dynamically sized type " +"that implements `Pet`.\n" +"* In the example, `pets` holds *fat pointers* to objects that implement " +"`Pet`. The fat pointer consists of two components, a pointer to the actual " +"object and a pointer to the virtual method table for the `Pet` " +"implementation of that particular object.\n" +"* Compare these outputs in the above example:\n" +" ```rust,ignore\n" +" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::" +"());\n" +" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::" +"<&Cat>());\n" +" println!(\"{}\", std::mem::size_of::<&dyn Pet>());\n" +" println!(\"{}\", std::mem::size_of::>());\n" +" ```" msgstr "" -#: src/control-flow/if-expressions.md:5 +#: src/traits/deriving-traits.md:1 +msgid "# Deriving Traits" +msgstr "" + +#: src/traits/deriving-traits.md:3 +msgid "You can let the compiler derive a number of traits:" +msgstr "" + +#: src/traits/deriving-traits.md:5 msgid "" "```rust,editable\n" +"#[derive(Debug, Clone, PartialEq, Eq, Default)]\n" +"struct Player {\n" +" name: String,\n" +" strength: u8,\n" +" hit_points: u8,\n" +"}\n" +"\n" "fn main() {\n" -" let mut x = 10;\n" -" if x % 2 == 0 {\n" -" x = x / 2;\n" -" } else {\n" -" x = 3 * x + 1;\n" -" }\n" +" let p1 = Player::default();\n" +" let p2 = p1.clone();\n" +" println!(\"Is {:?}\\nequal to {:?}?\\nThe answer is {}!\", &p1, &p2,\n" +" if p1 == p2 { \"yes\" } else { \"no\" });\n" "}\n" "```" msgstr "" -#: src/control-flow/if-expressions.md:16 -msgid "" -"In addition, you can use it as an expression. This does the same as above:" +#: src/traits/default-methods.md:1 +msgid "# Default Methods" msgstr "" -#: src/control-flow/if-expressions.md:18 +#: src/traits/default-methods.md:3 +msgid "Traits can implement behavior in terms of other trait methods:" +msgstr "" + +#: src/traits/default-methods.md:5 msgid "" "```rust,editable\n" +"trait Equals {\n" +" fn equal(&self, other: &Self) -> bool;\n" +" fn not_equal(&self, other: &Self) -> bool {\n" +" !self.equal(other)\n" +" }\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"struct Centimeter(i16);\n" +"\n" +"impl Equals for Centimeter {\n" +" fn equal(&self, other: &Centimeter) -> bool {\n" +" self.0 == other.0\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let mut x = 10;\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" +" let a = Centimeter(10);\n" +" let b = Centimeter(20);\n" +" println!(\"{a:?} equals {b:?}: {}\", a.equal(&b));\n" +" println!(\"{a:?} not_equals {b:?}: {}\", a.not_equal(&b));\n" "}\n" "```" msgstr "" -#: src/control-flow/if-let-expressions.md:1 -msgid "# `if let` expressions" +#: src/traits/default-methods.md:32 +msgid "" +"* Traits may specify pre-implemented (default) methods and methods that " +"users are required to\n" +" implement themselves. Methods with default implementations can rely on " +"required methods.\n" +"\n" +"* Move method `not_equal` to a new trait `NotEqual`.\n" +"\n" +"* Make `NotEqual` a super trait for `Equal`.\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`." +msgstr "" + +#: src/traits/trait-bounds.md:1 +msgid "# Trait Bounds" +msgstr "" + +#: src/traits/trait-bounds.md:3 +msgid "" +"When working with generics, you often want to require the types to " +"implement\n" +"some trait, so that you can call this trait's methods." msgstr "" -#: src/control-flow/if-let-expressions.md:3 -msgid "If you want to match a value against a pattern, you can use `if let`:" +#: src/traits/trait-bounds.md:6 +msgid "You can do this with `T: Trait` or `impl Trait`:" msgstr "" -#: src/control-flow/if-let-expressions.md:5 +#: src/traits/trait-bounds.md:8 msgid "" "```rust,editable\n" +"fn duplicate(a: T) -> (T, T) {\n" +" (a.clone(), a.clone())\n" +"}\n" +"\n" +"// Syntactic sugar for:\n" +"// fn add_42_millions>(x: T) -> i32 {\n" +"fn add_42_millions(x: impl Into) -> i32 {\n" +" x.into() + 42_000_000\n" +"}\n" +"\n" +"// struct NotClonable;\n" +"\n" "fn main() {\n" -" let arg = std::env::args().next();\n" -" if let Some(value) = arg {\n" -" println!(\"Program name: {value}\");\n" -" } else {\n" -" println!(\"Missing name?\");\n" -" }\n" +" let foo = String::from(\"foo\");\n" +" let pair = duplicate(foo);\n" +" println!(\"{pair:?}\");\n" +"\n" +" let many = add_42_millions(42_i8);\n" +" println!(\"{many}\");\n" +" let many_more = add_42_millions(10_000_000);\n" +" println!(\"{many_more}\");\n" "}\n" "```" 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/traits/trait-bounds.md:35 +msgid "Show a `where` clause, students will encounter it when reading code." +msgstr "" + +#: src/traits/trait-bounds.md:37 msgid "" -"See [pattern matching](../pattern-matching.md) for more details on patterns " -"in\n" -"Rust." +"```rust,ignore\n" +"fn duplicate(a: T) -> (T, T)\n" +"where\n" +" T: Clone,\n" +"{\n" +" (a.clone(), a.clone())\n" +"}\n" +"```" msgstr "" -#: src/control-flow/if-let-expressions.md:21 +#: src/traits/trait-bounds.md:46 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" -"* A common usage is handling `Some` values when working with `Option`.\n" -"* Unlike `match`, `if let` does not support guard clauses for pattern " -"matching." +"* It declutters the function signature if you have many parameters.\n" +"* It has additional features making it more powerful.\n" +" * If someone asks, the extra feature is that the type on the left of \":" +"\" can be arbitrary, like `Option`.\n" +" " msgstr "" -#: src/control-flow/while-expressions.md:1 -msgid "# `while` expressions" +#: src/traits/impl-trait.md:1 +msgid "# `impl Trait`" msgstr "" -#: src/control-flow/while-expressions.md:3 -msgid "The `while` keyword works very similar to other languages:" +#: src/traits/impl-trait.md:3 +msgid "" +"Similar to trait bounds, an `impl Trait` syntax can be used in function\n" +"arguments and return values:" msgstr "" -#: src/control-flow/while-expressions.md:5 +#: src/traits/impl-trait.md:6 msgid "" "```rust,editable\n" +"use std::fmt::Display;\n" +"\n" +"fn get_x(name: impl Display) -> impl Display {\n" +" format!(\"Hello {name}\")\n" +"}\n" +"\n" "fn main() {\n" -" let mut x = 10;\n" -" while x != 1 {\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -" }\n" -" println!(\"Final x: {x}\");\n" +" let x = get_x(\"foo\");\n" +" println!(\"{x}\");\n" "}\n" "```" msgstr "" -#: src/control-flow/while-let-expressions.md:1 -msgid "# `while let` expressions" +#: src/traits/impl-trait.md:19 +msgid "* `impl Trait` allows you to work with types which you cannot name." msgstr "" -#: src/control-flow/while-let-expressions.md:3 +#: src/traits/impl-trait.md:23 msgid "" -"Like with `if`, there is a `while let` variant which repeatedly tests a " -"value\n" -"against a pattern:" +"The meaning of `impl Trait` is a bit different in the different positions." msgstr "" -#: src/control-flow/while-let-expressions.md:6 +#: src/traits/impl-trait.md:25 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();" +"* For a parameter, `impl Trait` is like an anonymous generic parameter with " +"a trait bound.\n" +"\n" +"* For a return type, it means that the return type is some concrete type " +"that implements the trait,\n" +" without naming the type. This can be useful when you don't want to expose " +"the concrete type in a\n" +" public API.\n" +"\n" +" Inference is hard in return position. A function returning `impl Foo` " +"picks\n" +" the concrete type it returns, without writing it out in the source. A " +"function\n" +" returning a generic type like `collect() -> B` can return any type\n" +" satisfying `B`, and the caller may need to choose one, such as with `let " +"x:\n" +" Vec<_> = foo.collect()` or with the turbofish, `foo.collect::>()`." +msgstr "" + +#: src/traits/impl-trait.md:37 +msgid "" +"This example is great, because it uses `impl Display` twice. It helps to " +"explain that\n" +"nothing here enforces that it is _the same_ `impl Display` type. If we used " +"a single \n" +"`T: Display`, it would enforce the constraint that input `T` and return `T` " +"type are the same type.\n" +"It would not work for this particular function, as the type we expect as " +"input is likely not\n" +"what `format!` returns. If we wanted to do the same via `: Display` syntax, " +"we'd need two\n" +"independent generic parameters." msgstr "" -#: src/control-flow/while-let-expressions.md:11 +#: src/traits/important-traits.md:1 +msgid "# Important Traits" +msgstr "" + +#: src/traits/important-traits.md:3 msgid "" -" while let Some(x) = iter.next() {\n" -" println!(\"x: {x}\");\n" -" }\n" -"}\n" -"```" +"We will now look at some of the most common traits of the Rust standard " +"library:" msgstr "" -#: src/control-flow/while-let-expressions.md:17 +#: src/traits/important-traits.md:5 msgid "" -"Here the iterator returned by `v.iter()` will return a `Option` on " -"every\n" -"call to `next()`. It returns `Some(x)` until it is done, after which it " -"will\n" -"return `None`. The `while let` lets us keep iterating through all items." +"* [`Iterator`][1] and [`IntoIterator`][2] used in `for` loops,\n" +"* [`From`][3] and [`Into`][4] used to convert values,\n" +"* [`Read`][5] and [`Write`][6] used for IO,\n" +"* [`Add`][7], [`Mul`][8], ... used for operator overloading, and\n" +"* [`Drop`][9] used for defining destructors.\n" +"* [`Default`][10] used to construct a default instance of a type." msgstr "" -#: src/control-flow/for-expressions.md:1 -msgid "# `for` expressions" +#: src/traits/iterator.md:1 +msgid "# Iterators" msgstr "" -#: src/control-flow/for-expressions.md:3 -msgid "" -"The `for` expression is closely related to the `while let` expression. It " -"will\n" -"automatically call `into_iter()` on the expression and then iterate over it:" +#: src/traits/iterator.md:3 +msgid "You can implement the [`Iterator`][1] trait on your own types:" msgstr "" -#: src/control-flow/for-expressions.md:6 +#: src/traits/iterator.md:5 msgid "" "```rust,editable\n" +"struct Fibonacci {\n" +" curr: u32,\n" +" next: u32,\n" +"}\n" +"\n" +"impl Iterator for Fibonacci {\n" +" type Item = u32;\n" +"\n" +" fn next(&mut self) -> Option {\n" +" let new_next = self.curr + self.next;\n" +" self.curr = self.next;\n" +" self.next = new_next;\n" +" Some(self.curr)\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let v = vec![10, 20, 30];" -msgstr "" - -#: src/control-flow/for-expressions.md:10 -msgid "" -" for x in v {\n" -" println!(\"x: {x}\");\n" +" let fib = Fibonacci { curr: 0, next: 1 };\n" +" for (i, n) in fib.enumerate().take(5) {\n" +" println!(\"fib({i}): {n}\");\n" " }\n" "}\n" "```" msgstr "" -#: src/control-flow/for-expressions.md:16 -msgid "You can use `break` and `continue` here as usual." +#: src/traits/iterator.md:32 +msgid "" +"* The `Iterator` trait implements many common functional programming " +"operations over collections \n" +" (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can " +"find all the documentation\n" +" about them. In Rust these functions should produce the code as efficient " +"as equivalent imperative\n" +" implementations.\n" +" \n" +"* `IntoIterator` is the trait that makes for loops work. It is implemented " +"by collection types such as\n" +" `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also " +"implement it. This is why\n" +" you can iterate over a vector with `for i in some_vec { .. }` but\n" +" `some_vec.next()` doesn't exist." msgstr "" -#: src/control-flow/loop-expressions.md:1 -msgid "# `loop` expressions" +#: src/traits/from-iterator.md:1 +msgid "# FromIterator" msgstr "" -#: src/control-flow/loop-expressions.md:3 +#: src/traits/from-iterator.md:3 msgid "" -"Finally, there is a `loop` keyword which creates an endless loop. Here you " -"must\n" -"either `break` or `return` to stop the loop:" +"[`FromIterator`][1] lets you build a collection from an [`Iterator`][2]." msgstr "" -#: src/control-flow/loop-expressions.md:6 +#: src/traits/from-iterator.md:5 msgid "" "```rust,editable\n" "fn main() {\n" -" let mut x = 10;\n" -" loop {\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -" if x == 1 {\n" -" break;\n" -" }\n" -" }\n" -" println!(\"Final x: {x}\");\n" +" let primes = vec![2, 3, 5, 7];\n" +" let prime_squares = primes\n" +" .into_iter()\n" +" .map(|prime| prime * prime)\n" +" .collect::>();\n" "}\n" "```" msgstr "" -#: src/control-flow/match-expressions.md:1 -msgid "# `match` expressions" +#: src/traits/from-iterator.md:17 +msgid "" +"`Iterator` implements\n" +"`fn collect(self) -> B\n" +"where\n" +" B: FromIterator,\n" +" Self: Sized`" msgstr "" -#: src/control-flow/match-expressions.md:3 +#: src/traits/from-iterator.md:23 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:" +"There are also implementations which let you do cool things like convert an\n" +"`Iterator>` into a `Result, E>`." msgstr "" -#: src/control-flow/match-expressions.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" match std::env::args().next().as_deref() {\n" -" Some(\"cat\") => println!(\"Will do cat things\"),\n" -" Some(\"ls\") => println!(\"Will ls some files\"),\n" -" Some(\"mv\") => println!(\"Let's move some files\"),\n" -" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" -" None => println!(\"Hmm, no program name?\"),\n" -" _ => println!(\"Unknown program name!\"),\n" -" }\n" -"}\n" -"```" +#: src/traits/from-into.md:1 +msgid "# `From` and `Into`" msgstr "" -#: src/control-flow/match-expressions.md:19 +#: src/traits/from-into.md:3 msgid "" -"Like `if let`, each match arm must have the same type. The type is the last\n" -"expression of the block, if any. In the example above, the type is `()`." +"Types implement [`From`][1] and [`Into`][2] to facilitate type conversions:" msgstr "" -#: src/control-flow/break-continue.md:1 -msgid "# `break` and `continue`" +#: src/traits/from-into.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s = String::from(\"hello\");\n" +" let addr = std::net::Ipv4Addr::from([127, 0, 0, 1]);\n" +" let one = i16::from(true);\n" +" let bigger = i32::from(123i16);\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" +"}\n" +"```" msgstr "" -#: src/control-flow/break-continue.md:3 +#: src/traits/from-into.md:15 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:" +"[`Into`][2] is automatically implemented when [`From`][1] is implemented:" msgstr "" -#: src/control-flow/break-continue.md:7 +#: src/traits/from-into.md:17 msgid "" "```rust,editable\n" "fn main() {\n" -" let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();\n" -" 'outer: while let Some(x) = iter.next() {\n" -" println!(\"x: {x}\");\n" -" let mut i = 0;\n" -" while i < x {\n" -" println!(\"x: {x}, i: {i}\");\n" -" i += 1;\n" -" if i == 3 {\n" -" break 'outer;\n" -" }\n" -" }\n" -" }\n" +" let s: String = \"hello\".into();\n" +" let addr: std::net::Ipv4Addr = [127, 0, 0, 1].into();\n" +" let one: i16 = true.into();\n" +" let bigger: i32 = 123i16.into();\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" "}\n" "```" msgstr "" -#: src/control-flow/break-continue.md:25 +#: src/traits/from-into.md:29 msgid "" -"In this case we break the outer loop after 3 iterations of the inner loop." +"* That's why it is common to only implement `From`, as your type will get " +"`Into` implementation too.\n" +"* When declaring a function argument input type like \"anything that can be " +"converted into a `String`\", the rule is opposite, you should use `Into`.\n" +" Your function will accept types that implement `From` and those that " +"_only_ implement `Into`.\n" +" " msgstr "" -#: src/std.md:1 -msgid "# Standard Library" +#: src/traits/read-write.md:1 +msgid "# `Read` and `Write`" msgstr "" -#: src/std.md:3 +#: src/traits/read-write.md:3 msgid "" -"Rust comes with a standard library which helps establish a set of common " -"types\n" -"used by Rust library and programs. This way, two libraries can work " -"together\n" -"smoothly because they both use the same `String` type." +"Using [`Read`][1] and [`BufRead`][2], you can abstract over `u8` sources:" msgstr "" -#: src/std.md:7 -msgid "The common vocabulary types include:" +#: src/traits/read-write.md:5 +msgid "" +"```rust,editable\n" +"use std::io::{BufRead, BufReader, Read, Result};\n" +"\n" +"fn count_lines(reader: R) -> usize {\n" +" let buf_reader = BufReader::new(reader);\n" +" buf_reader.lines().count()\n" +"}\n" +"\n" +"fn main() -> Result<()> {\n" +" let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" +" println!(\"lines in slice: {}\", count_lines(slice));\n" +"\n" +" let file = std::fs::File::open(std::env::current_exe()?)?;\n" +" println!(\"lines in file: {}\", count_lines(file));\n" +" Ok(())\n" +"}\n" +"```" msgstr "" -#: src/std.md:9 -msgid "" -"* [`Option` and `Result`](std/option-result.md) types: used for optional " -"values\n" -" and [error handling](error-handling.md)." +#: src/traits/read-write.md:23 +msgid "Similarly, [`Write`][3] lets you abstract over `u8` sinks:" msgstr "" -#: src/std.md:12 +#: src/traits/read-write.md:25 msgid "" -"* [`String`](std/string.md): the default string type used for owned data." +"```rust,editable\n" +"use std::io::{Result, Write};\n" +"\n" +"fn log(writer: &mut W, msg: &str) -> Result<()> {\n" +" writer.write_all(msg.as_bytes())?;\n" +" writer.write_all(\"\\n\".as_bytes())\n" +"}\n" +"\n" +"fn main() -> Result<()> {\n" +" let mut buffer = Vec::new();\n" +" log(&mut buffer, \"Hello\")?;\n" +" log(&mut buffer, \"World\")?;\n" +" println!(\"Logged: {:?}\", buffer);\n" +" Ok(())\n" +"}\n" +"```" msgstr "" -#: src/std.md:14 -msgid "* [`Vec`](std/vec.md): a standard extensible vector." +#: src/traits/drop.md:1 +msgid "# The `Drop` Trait" msgstr "" -#: src/std.md:16 +#: src/traits/drop.md:3 msgid "" -"* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" -" algorithm." +"Values which implement [`Drop`][1] can specify code to run when they go out " +"of scope:" +msgstr "" + +#: src/traits/drop.md:5 +msgid "" +"```rust,editable\n" +"struct Droppable {\n" +" name: &'static str,\n" +"}\n" +"\n" +"impl Drop for Droppable {\n" +" fn drop(&mut self) {\n" +" println!(\"Dropping {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let a = Droppable { name: \"a\" };\n" +" {\n" +" let b = Droppable { name: \"b\" };\n" +" {\n" +" let c = Droppable { name: \"c\" };\n" +" let d = Droppable { name: \"d\" };\n" +" println!(\"Exiting block B\");\n" +" }\n" +" println!(\"Exiting block A\");\n" +" }\n" +" drop(a);\n" +" println!(\"Exiting main\");\n" +"}\n" +"```" msgstr "" -#: src/std.md:19 -msgid "* [`Box`](std/box.md): an owned pointer for heap-allocated data." +#: src/traits/drop.md:34 src/traits/operators.md:26 +msgid "Discussion points:" msgstr "" -#: src/std.md:21 +#: src/traits/drop.md:36 msgid "" -"* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated " -"data." +"* Why doesn't `Drop::drop` take `self`?\n" +" * Short-answer: If it did, `std::mem::drop` would be called at the end " +"of\n" +" the block, resulting in another call to `Drop::drop`, and a stack\n" +" overflow!\n" +"* Try replacing `drop(a)` with `a.drop()`." msgstr "" -#: src/std/string.md:1 -msgid "# String" +#: src/traits/default.md:1 +msgid "# The `Default` Trait" msgstr "" -#: src/std/string.md:3 -msgid "" -"[`String`][1] is the standard heap-allocated growable UTF-8 string buffer:" +#: src/traits/default.md:3 +msgid "[`Default`][1] trait provides a default implementation of a trait." msgstr "" -#: src/std/string.md:5 +#: src/traits/default.md:5 msgid "" "```rust,editable\n" +"#[derive(Debug, Default)]\n" +"struct Derived {\n" +" x: u32,\n" +" y: String,\n" +" z: Implemented,\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"struct Implemented(String);\n" +"\n" +"impl Default for Implemented {\n" +" fn default() -> Self {\n" +" Self(\"John Smith\".into())\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let mut s1 = String::new();\n" -" s1.push_str(\"Hello\");\n" -" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());" +" let default_struct: Derived = Default::default();\n" +" println!(\"{default_struct:#?}\");\n" +"\n" +" let almost_default_struct = Derived {\n" +" y: \"Y is set!\".into(),\n" +" ..Default::default()\n" +" };\n" +" println!(\"{almost_default_struct:#?}\");\n" +"\n" +" let nothing: Option = None;\n" +" println!(\"{:#?}\", nothing.unwrap_or_default());\n" +"}\n" +"\n" +"```" msgstr "" -#: src/std/string.md:11 +#: src/traits/default.md:40 msgid "" -" let mut s2 = String::with_capacity(s1.len() + 1);\n" -" s2.push_str(&s1);\n" -" s2.push('!');\n" -" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());" +" * It can be implemented directly or it can be derived via " +"`#[derive(Default)]`.\n" +" * Derived implementation will produce an instance where all fields are set " +"to their default values.\n" +" * This means all types in the struct must implement `Default` too.\n" +" * Standard Rust types often implement `Default` with reasonable values (e." +"g. `0`, `\"\"`, etc).\n" +" * The partial struct copy works nicely with default.\n" +" * Rust standard library is aware that types can implement `Default` and " +"provides convenience methods that use it." msgstr "" -#: src/std/string.md:16 -msgid "" -" let s3 = String::from(\"🇨🇭\");\n" -" println!(\"s3: len = {}, number of chars = {}\", s3.len(),\n" -" s3.chars().count());\n" -"}\n" -"```" +#: src/traits/operators.md:1 +msgid "# `Add`, `Mul`, ..." msgstr "" -#: src/std/string.md:22 -msgid "" -"`String` implements [`Deref`][2], which means that you can " -"call all\n" -"`str` methods on a `String`." +#: src/traits/operators.md:3 +msgid "Operator overloading is implemented via traits in [`std::ops`][1]:" msgstr "" -#: src/std/string.md:25 +#: src/traits/operators.md:5 msgid "" -"[1]: https://doc.rust-lang.org/std/string/struct.String.html\n" -"[2]: https://doc.rust-lang.org/std/string/struct.String.html#deref-methods-" -"str" +"```rust,editable\n" +"#[derive(Debug, Copy, Clone)]\n" +"struct Point { x: i32, y: i32 }\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self {\n" +" Self {x: self.x + other.x, y: self.y + other.y}\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point { x: 10, y: 20 };\n" +" let p2 = Point { x: 100, y: 200 };\n" +" println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" +"}\n" +"```" msgstr "" -#: src/std/string.md:30 +#: src/traits/operators.md:28 msgid "" -"* `len` returns the size of the `String` in bytes, not its length in " -"characters.\n" -"* `chars` returns an iterator over the actual characters.\n" -"* `String` implements `Deref` which transparently gives it " -"access to `str`'s methods." +"* You could implement `Add` for `&Point`. In which situations is that " +"useful? \n" +" * Answer: `Add:add` consumes `self`. If type `T` for which you are\n" +" 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" +" associated types (like `Output`) are controlled by the implementor " +"of a\n" +" trait." msgstr "" -#: src/std/option-result.md:1 -msgid "# `Option` and `Result`" +#: src/traits/closures.md:1 +msgid "# Closures" msgstr "" -#: src/std/option-result.md:3 -msgid "The types represent optional data:" +#: src/traits/closures.md:3 +msgid "" +"Closures or lambda expressions have types which cannot be named. However, " +"they\n" +"implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:" msgstr "" -#: src/std/option-result.md:5 +#: src/traits/closures.md:8 msgid "" "```rust,editable\n" +"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" +" println!(\"Calling function on {input}\");\n" +" func(input)\n" +"}\n" +"\n" "fn main() {\n" -" let numbers = vec![10, 20, 30];\n" -" let first: Option<&i8> = numbers.first();\n" -" println!(\"first: {first:?}\");" -msgstr "" - -#: src/std/option-result.md:11 -msgid "" -" let idx: Result = numbers.binary_search(&10);\n" -" println!(\"idx: {idx:?}\");\n" +" let add_3 = |x| x + 3;\n" +" let mul_5 = |x| x * 5;\n" +"\n" +" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" +" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" "}\n" "```" msgstr "" -#: src/std/option-result.md:18 +#: src/traits/closures.md:25 msgid "" -"* `Option` and `Result` are widely used not just in the standard library.\n" -"* `Option<&T>` has zero space overhead compared to `&T`.\n" -"* `Result` is the standard type to implement error handling as we will see " -"on Day 3.\n" -"* `binary_search` returns `Result`.\n" -" * If found, `Result::Ok` holds the index where the element is found.\n" -" * Otherwise, `Result::Err` contains the index where such an element should " -"be inserted." +"If you have an `FnOnce`, you may only call it once. It might consume " +"captured values." msgstr "" -#: src/std/vec.md:1 -msgid "# `Vec`" +#: src/traits/closures.md:27 +msgid "" +"An `FnMut` might mutate captured values, so you can call it multiple times " +"but not concurrently." msgstr "" -#: src/std/vec.md:3 -msgid "[`Vec`][1] is the standard resizable heap-allocated buffer:" +#: src/traits/closures.md:29 +msgid "" +"An `Fn` neither consumes nor mutates captured values, or perhaps captures " +"nothing at all, so it can\n" +"be called multiple times concurrently." msgstr "" -#: src/std/vec.md:5 +#: src/traits/closures.md:32 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut numbers = Vec::new();\n" -" numbers.push(42);" +"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. " +"I.e. you can use an\n" +"`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever " +"an `FnMut` or `FnOnce`\n" +"is called for." msgstr "" -#: src/std/vec.md:10 -msgid "" -" let mut v1 = Vec::new();\n" -" v1.push(42);\n" -" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());" +#: src/traits/closures.md:36 +msgid "`move` closures only implement `FnOnce`." msgstr "" -#: src/std/vec.md:14 -msgid "" -" let mut v2 = Vec::with_capacity(v1.len() + 1);\n" -" v2.extend(v1.iter());\n" -" v2.push(9999);\n" -" println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());\n" -"}\n" -"```" +#: src/exercises/day-3/morning.md:1 +msgid "# Day 3: Morning Exercises" msgstr "" -#: src/std/vec.md:21 -msgid "" -"`Vec` implements [`Deref`][2], which means that you can call " -"slice\n" -"methods on a `Vec`." +#: src/exercises/day-3/morning.md:3 +msgid "We will design a classical GUI library traits and trait objects." msgstr "" -#: src/std/vec.md:24 -msgid "" -"[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" -"[2]: https://doc.rust-lang.org/std/vec/struct.Vec.html#deref-methods-[T]" +#: src/exercises/day-3/simple-gui.md:1 +msgid "# A Simple GUI Library" msgstr "" -#: src/std/hashmap.md:1 -msgid "# `HashMap`" +#: src/exercises/day-3/simple-gui.md:3 +msgid "" +"Let us design a classical GUI library using our new knowledge of traits and\n" +"trait objects." msgstr "" -#: src/std/hashmap.md:3 -msgid "Standard hash map with protection against HashDoS attacks:" +#: src/exercises/day-3/simple-gui.md:6 +msgid "We will have a number of widgets in our library:" msgstr "" -#: src/std/hashmap.md:5 +#: src/exercises/day-3/simple-gui.md:8 msgid "" -"```rust,editable\n" -"use std::collections::HashMap;" +"* `Window`: has a `title` and contains other widgets.\n" +"* `Button`: has a `label` and a callback function which is invoked when the\n" +" button is pressed.\n" +"* `Label`: has a `label`." msgstr "" -#: src/std/hashmap.md:8 -msgid "" -"fn main() {\n" -" let mut page_counts = HashMap::new();\n" -" page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), " -"207);\n" -" page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" -" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);" +#: src/exercises/day-3/simple-gui.md:13 +msgid "The widgets will implement a `Widget` trait, see below." msgstr "" -#: src/std/hashmap.md:14 +#: src/exercises/day-3/simple-gui.md:15 msgid "" -" if !page_counts.contains_key(\"Les Misérables\") {\n" -" println!(\"We've know about {} books, but not Les Misérables.\",\n" -" page_counts.len());\n" -" }" +"Copy the code below to , fill in the missing\n" +"`draw_into` methods so that you implement the `Widget` trait:" msgstr "" -#: src/std/hashmap.md:19 +#: src/exercises/day-3/simple-gui.md:18 msgid "" -" for book in [\"Pride and Prejudice\", \"Alice's Adventure in " -"Wonderland\"] {\n" -" match page_counts.get(book) {\n" -" Some(count) => println!(\"{book}: {count} pages\"),\n" -" None => println!(\"{book} is unknown.\")\n" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" " }\n" " }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"\n" +" fn inner_width(&self) -> usize {\n" +" std::cmp::max(\n" +" self.title.chars().count(),\n" +" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +" )\n" +" }\n" +"}\n" +"\n" +"\n" +"impl Widget for Label {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Widget for Button {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo." +"\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" "}\n" "```" msgstr "" -#: src/std/box.md:1 -msgid "# `Box`" +#: src/exercises/day-3/simple-gui.md:130 +msgid "The output of the above program can be something simple like this:" msgstr "" -#: src/std/box.md:3 -msgid "[`Box`][1] is an owned pointer to data on the heap:" +#: src/exercises/day-3/simple-gui.md:132 +msgid "" +"```text\n" +"========\n" +"Rust GUI Demo 1.23\n" +"========\n" +"\n" +"This is a small text GUI demo.\n" +"\n" +"| Click me! |\n" +"```" msgstr "" -#: src/std/box.md:5 +#: src/exercises/day-3/simple-gui.md:142 +msgid "" +"If you want to draw aligned text, you can use the\n" +"[fill/alignment](https://doc.rust-lang.org/std/fmt/index." +"html#fillalignment)\n" +"formatting operators. In particular, notice how you can pad with different\n" +"characters (here a `'/'`) and how you can control alignment:" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:147 msgid "" "```rust,editable\n" "fn main() {\n" -" let five = Box::new(5);\n" -" println!(\"five: {}\", *five);\n" +" let width = 10;\n" +" println!(\"left aligned: |{:/width$}|\", \"foo\");\n" "}\n" "```" msgstr "" -#: src/std/box.md:13 +#: src/exercises/day-3/simple-gui.md:156 msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - -. .- - - - - - -.\n" -": : : :\n" -": five : : :\n" -": +-----+ : : +-----+ :\n" -": | o---|---+-----+-->| 5 | :\n" -": +-----+ : : +-----+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - -' `- - - - - - -'\n" -"```" +"Using such alignment tricks, you can for example produce output like this:" msgstr "" -#: src/std/box.md:26 +#: src/exercises/day-3/simple-gui.md:158 msgid "" -"`Box` implements `Deref`, which means that you can [call " -"methods\n" -"from `T` directly on a `Box`][2]." +"```text\n" +"+--------------------------------+\n" +"| Rust GUI Demo 1.23 |\n" +"+================================+\n" +"| This is a small text GUI demo. |\n" +"| +-----------+ |\n" +"| | Click me! | |\n" +"| +-----------+ |\n" +"+--------------------------------+\n" +"```" msgstr "" -#: src/std/box.md:29 -msgid "" -"[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" -"[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-" -"coercion" +#: src/error-handling.md:1 +msgid "# Error Handling" msgstr "" -#: src/std/box.md:34 -msgid "" -"* `Box` is like `std::unique_ptr` in C++.\n" -"* In the above example, you can even leave out the `*` in the `println!` " -"statement thanks to `Deref`." +#: src/error-handling.md:3 +msgid "Error handling in Rust is done using explicit control flow:" msgstr "" -#: src/std/box-recursive.md:1 -msgid "# Box with Recursive Data Structures" +#: src/error-handling.md:5 +msgid "" +"* Functions that can have errors list this in their return type,\n" +"* There are no exceptions." msgstr "" -#: src/std/box-recursive.md:3 -msgid "" -"Recursive data types or data types with dynamic sizes need to use a `Box`:" +#: src/error-handling/panics.md:1 +msgid "# Panics" msgstr "" -#: src/std/box-recursive.md:5 src/std/box-niche.md:3 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"enum List {\n" -" Cons(T, Box>),\n" -" Nil,\n" -"}" +#: src/error-handling/panics.md:3 +msgid "Rust will trigger a panic if a fatal error happens at runtime:" msgstr "" -#: src/std/box-recursive.md:12 src/std/box-niche.md:10 +#: src/error-handling/panics.md:5 msgid "" +"```rust,editable,should_panic\n" "fn main() {\n" -" let list: List = List::Cons(1, Box::new(List::Cons(2, Box::" -"new(List::Nil))));\n" -" println!(\"{list:?}\");\n" +" let v = vec![10, 20, 30];\n" +" println!(\"v[100]: {}\", v[100]);\n" "}\n" "```" msgstr "" -#: src/std/box-recursive.md:18 +#: src/error-handling/panics.md:12 msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - " -"- -.\n" -": : : :\n" -": " -"list : : :\n" -": +--------+-------+ : : +--------+--------+ +--------+------" -"+ :\n" -": | Tag | Cons | : : .->| Tag | Cons | .->| Tag | Nil " -"| :\n" -": | 0 | 1 | : : | | 0 | 2 | | | ////// | //// " -"| :\n" -": | 1 | o-----+----+-----+-' | 1 | o------+-' | ////// | //// " -"| :\n" -": +--------+-------+ : : +--------+--------+ +--------+------" -"+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - " -"- -'\n" -"```" +"* Panics are for unrecoverable and unexpected errors.\n" +" * Panics are symptoms of bugs in the program.\n" +"* Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." msgstr "" -#: src/std/box-niche.md:1 -msgid "# Niche Optimization" +#: src/error-handling/panic-unwind.md:1 +msgid "# Catching the Stack Unwinding" msgstr "" -#: src/std/box-niche.md:16 +#: src/error-handling/panic-unwind.md:3 msgid "" -"A `Box` cannot be empty, so the pointer is always valid and non-`null`. " -"This\n" -"allows the compiler to optimize the memory layout:" +"By default, a panic will cause the stack to unwind. The unwinding can be " +"caught:" msgstr "" -#: src/std/box-niche.md:19 -#, fuzzy +#: src/error-handling/panic-unwind.md:5 msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - " -"- -.\n" -": : : :\n" -": " -"list : : :\n" -": +--------+-------+ : : +--------+--------+ +--------+------" -"+ :\n" -": | 0 | 1 | : : .->| 0 | 2 | .->| ////// | //// " -"| :\n" -": | \"1/Tag\"| o-----+----+-----+-' | \"1/Tag\"| o-----+-' | \"1/Tag\"| " -"null | :\n" -": +--------+-------+ : : +--------+--------+ +--------+------" -"+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - " -"- -'\n" +"```rust,editable\n" +"use std::panic;\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" println!(\"hello!\");\n" +"});\n" +"assert!(result.is_ok());\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" panic!(\"oh no!\");\n" +"});\n" +"assert!(result.is_err());\n" "```" msgstr "" -"```bob\n" -" Stak Bunke\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| H | a | l | l | o | :\n" -": | len | 5 | : : +----+----+----+----+----+ :\n" -": | capacity | 5 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -#: src/std/rc.md:1 -msgid "# `Rc`" +#: src/error-handling/panic-unwind.md:19 +msgid "" +"* This can be useful in servers which should keep running even if a single\n" +" request crashes.\n" +"* This does not work if `panic = 'abort'` is set in your `Cargo.toml`." msgstr "" -#: src/std/rc.md:3 -msgid "" -"[`Rc`][1] is a reference-counted shared pointer. Use this when you need to " -"refer\n" -"to the same data from multiple places:" +#: src/error-handling/result.md:1 +msgid "# Structured Error Handling with `Result`" msgstr "" -#: src/std/rc.md:6 +#: src/error-handling/result.md:3 msgid "" -"```rust,editable\n" -"use std::rc::Rc;" +"We have already seen the `Result` enum. This is used pervasively when errors " +"are\n" +"expected as part of normal operation:" msgstr "" -#: src/std/rc.md:9 +#: src/error-handling/result.md:6 msgid "" +"```rust,editable\n" +"use std::fs::File;\n" +"use std::io::Read;\n" +"\n" "fn main() {\n" -" let mut a = Rc::new(10);\n" -" let mut b = a.clone();" +" let file = File::open(\"diary.txt\");\n" +" match file {\n" +" Ok(mut file) => {\n" +" let mut contents = String::new();\n" +" file.read_to_string(&mut contents);\n" +" println!(\"Dear diary: {contents}\");\n" +" },\n" +" Err(err) => {\n" +" println!(\"The diary could not be opened: {err}\");\n" +" }\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/std/rc.md:18 +#: src/error-handling/result.md:27 msgid "" -"If you need to mutate the data inside an `Rc`, you will need to wrap the " -"data in\n" -"a type such as [`Cell` or `RefCell`][2]. See [`Arc`][3] if you are in a " -"multi-threaded\n" -"context." +" * As with `Option`, the successful value sits inside of `Result`, forcing " +"the developer to\n" +" explicitly extract it. This encourages error checking. In the case where " +"an error should never happen,\n" +" `unwrap()` or `expect()` can be called, and this is a signal of the " +"developer intent too. \n" +" * `Result` documentation is a recommended read. Not during the course, but " +"it is worth mentioning. \n" +" It contains a lot of convenience methods and functions that help " +"functional-style programming. \n" +" " +msgstr "" + +#: src/error-handling/try-operator.md:1 +msgid "# Propagating Errors with `?`" msgstr "" -#: src/std/rc.md:22 +#: src/error-handling/try-operator.md:3 msgid "" -"[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" -"[2]: https://doc.rust-lang.org/std/cell/index.html\n" -"[3]: ../concurrency/shared_state/arc.md" +"The try-operator `?` is used to return errors to the caller. It lets you " +"turn\n" +"the common" msgstr "" -#: src/std/rc.md:28 +#: src/error-handling/try-operator.md:6 msgid "" -"* Like C++'s `std::shared_ptr`.\n" -"* `clone` is cheap: creates a pointer to the same allocation and increases " -"the reference count.\n" -"* `make_mut` actually clones the inner value if necessary (\"clone-on-" -"write\") and returns a mutable reference." +"```rust,ignore\n" +"match some_expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(err),\n" +"}\n" +"```" msgstr "" -#: src/modules.md:1 -msgid "# Modules" +#: src/error-handling/try-operator.md:13 +msgid "into the much simpler" msgstr "" -#: src/modules.md:3 -msgid "We have seen how `impl` blocks let us namespace functions to a type." +#: src/error-handling/try-operator.md:15 +msgid "" +"```rust,ignore\n" +"some_expression?\n" +"```" msgstr "" -#: src/modules.md:5 -msgid "Similarly, `mod` lets us namespace types and functions:" +#: src/error-handling/try-operator.md:19 +msgid "We can use this to simplify our error handing code:" msgstr "" -#: src/modules.md:7 +#: src/error-handling/try-operator.md:21 msgid "" "```rust,editable\n" -"mod foo {\n" -" pub fn do_something() {\n" -" println!(\"In the foo module\");\n" +"use std::fs;\n" +"use std::io::{self, Read};\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let username_file_result = fs::File::open(path);\n" +" let mut username_file = match username_file_result {\n" +" Ok(file) => file,\n" +" Err(err) => return Err(err),\n" +" };\n" +"\n" +" let mut username = String::new();\n" +" match username_file.read_to_string(&mut username) {\n" +" Ok(_) => Ok(username),\n" +" Err(err) => Err(err),\n" " }\n" -"}" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"alice\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:50 +#: src/error-handling/converting-error-types-example.md:52 +msgid "" +"* The `username` variable can be either `Ok(string)` or `Err(error)`.\n" +"* Use the `fs::write` call to test out the different scenarios: no file, " +"empty file, file with username." +msgstr "" + +#: src/error-handling/converting-error-types.md:1 +#: src/error-handling/converting-error-types-example.md:1 +msgid "# Converting Error Types" msgstr "" -#: src/modules.md:14 +#: src/error-handling/converting-error-types.md:3 msgid "" -"mod bar {\n" -" pub fn do_something() {\n" -" println!(\"In the bar module\");\n" -" }\n" -"}" +"The effective expansion of `?` is a little more complicated than previously " +"indicated:" msgstr "" -#: src/modules.md:20 +#: src/error-handling/converting-error-types.md:5 msgid "" -"fn main() {\n" -" foo::do_something();\n" -" bar::do_something();\n" -"}\n" +"```rust,ignore\n" +"expression?\n" "```" msgstr "" -#: src/modules/visibility.md:1 -msgid "# Visibility" +#: src/error-handling/converting-error-types.md:9 +msgid "works the same as" msgstr "" -#: src/modules/visibility.md:3 -msgid "Modules are a privacy boundary:" +#: src/error-handling/converting-error-types.md:11 +msgid "" +"```rust,ignore\n" +"match expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(From::from(err)),\n" +"}\n" +"```" msgstr "" -#: src/modules/visibility.md:5 +#: src/error-handling/converting-error-types.md:18 msgid "" -"* Module items are private by default (hides implementation details).\n" -"* Parent and sibling items are always visible." +"The `From::from` call here means we attempt to convert the error type to " +"the\n" +"type returned by the function:" msgstr "" -#: src/modules/visibility.md:8 +#: src/error-handling/converting-error-types-example.md:3 msgid "" "```rust,editable\n" -"mod outer {\n" -" fn private() {\n" -" println!(\"outer::private\");\n" -" }" +"use std::error::Error;\n" +"use std::fmt::{self, Display, Formatter};\n" +"use std::fs::{self, File};\n" +"use std::io::{self, Read};\n" +"\n" +"#[derive(Debug)]\n" +"enum ReadUsernameError {\n" +" IoError(io::Error),\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"impl Error for ReadUsernameError {}\n" +"\n" +"impl Display for ReadUsernameError {\n" +" fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" +" match self {\n" +" Self::IoError(e) => write!(f, \"IO error: {e}\"),\n" +" Self::EmptyUsername(filename) => write!(f, \"Found no username " +"in {filename}\"),\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl From for ReadUsernameError {\n" +" fn from(err: io::Error) -> ReadUsernameError {\n" +" ReadUsernameError::IoError(err)\n" +" }\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" msgstr "" -#: src/modules/visibility.md:14 +#: src/error-handling/converting-error-types-example.md:55 msgid "" -" pub fn public() {\n" -" println!(\"outer::public\");\n" -" }" +"It is good practice for all error types to implement `std::error::Error`, " +"which requires `Debug` and\n" +"`Display`. It's generally helpful for them to implement `Clone` and `Eq` too " +"where possible, to make\n" +"life easier for tests and consumers of your library. In this case we can't " +"easily do so, because\n" +"`io::Error` doesn't implement them." msgstr "" -#: src/modules/visibility.md:18 -msgid "" -" mod inner {\n" -" fn private() {\n" -" println!(\"outer::inner::private\");\n" -" }" +#: src/error-handling/deriving-error-enums.md:1 +msgid "# Deriving Error Enums" msgstr "" -#: src/modules/visibility.md:23 +#: src/error-handling/deriving-error-enums.md:3 msgid "" -" pub fn public() {\n" -" println!(\"outer::inner::public\");\n" -" super::private();\n" -" }\n" -" }\n" -"}" +"The [thiserror](https://docs.rs/thiserror/) crate is a popular way to create " +"an\n" +"error enum like we did on the previous page:" msgstr "" -#: src/modules/visibility.md:30 +#: src/error-handling/deriving-error-enums.md:6 msgid "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"\n" +"#[derive(Debug, Error)]\n" +"enum ReadUsernameError {\n" +" #[error(\"Could not read: {0}\")]\n" +" IoError(#[from] io::Error),\n" +" #[error(\"Found no username in {0}\")]\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" "fn main() {\n" -" outer::public();\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" "}\n" "```" msgstr "" -#: src/modules/paths.md:1 -msgid "# Paths" +#: src/error-handling/deriving-error-enums.md:39 +msgid "" +"`thiserror`'s derive macro automatically implements `std::error::Error`, and " +"optionally `Display`\n" +"(if the `#[error(...)]` attributes are provided) and `From` (if the " +"`#[from]` attribute is added).\n" +"It also works for structs." msgstr "" -#: src/modules/paths.md:3 -msgid "Paths are resolved as follows:" +#: src/error-handling/deriving-error-enums.md:43 +msgid "It doesn't affect your public API, which makes it good for libraries." msgstr "" -#: src/modules/paths.md:5 +#: src/error-handling/dynamic-errors.md:1 +msgid "# Dynamic Error Types" +msgstr "" + +#: src/error-handling/dynamic-errors.md:3 msgid "" -"1. As a relative path:\n" -" * `foo` or `self::foo` refers to `foo` in the current module,\n" -" * `super::foo` refers to `foo` in the parent module." +"Sometimes we want to allow any type of error to be returned without writing " +"our own enum covering\n" +"all the different possibilities. `std::error::Error` makes this easy." msgstr "" -#: src/modules/paths.md:9 +#: src/error-handling/dynamic-errors.md:6 msgid "" -"2. As an absolute path:\n" -" * `crate::foo` refers to `foo` in the root of the current crate,\n" -" * `bar::foo` refers to `foo` in the `bar` crate." +"```rust,editable,compile_fail\n" +"use std::fs::{self, File};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"use std::error::Error;\n" +"\n" +"#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" +"#[error(\"Found no username in {0}\")]\n" +"struct EmptyUsernameError(String);\n" +"\n" +"fn read_username(path: &str) -> Result> {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(EmptyUsernameError(String::from(path)).into());\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/modules/filesystem.md:1 -msgid "# Filesystem Hierarchy" +#: src/error-handling/dynamic-errors.md:36 +msgid "" +"This saves on code, but gives up the ability to cleanly handle different " +"error cases differently in\n" +"the program. As such it's generally not a good idea to use `Box` " +"in the public API of a\n" +"library, but it can be a good option in a program where you just want to " +"display the error message\n" +"somewhere." msgstr "" -#: src/modules/filesystem.md:3 -msgid "The module content can be omitted:" +#: src/error-handling/error-contexts.md:1 +msgid "# Adding Context to Errors" msgstr "" -#: src/modules/filesystem.md:5 +#: src/error-handling/error-contexts.md:3 +msgid "" +"The widely used [anyhow](https://docs.rs/anyhow/) crate can help you add\n" +"contextual information to your errors and allows you to have fewer\n" +"custom error types:" +msgstr "" + +#: src/error-handling/error-contexts.md:7 msgid "" "```rust,editable,compile_fail\n" -"mod garden;\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use anyhow::{Context, Result, bail};\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)\n" +" .with_context(|| format!(\"Failed to open {path}\"))?\n" +" .read_to_string(&mut username)\n" +" .context(\"Failed to read\")?;\n" +" if username.is_empty() {\n" +" bail!(\"Found no username in {path}\");\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err:?}\"),\n" +" }\n" +"}\n" "```" msgstr "" -#: src/modules/filesystem.md:9 -msgid "The `garden` module content is found at:" +#: src/error-handling/error-contexts.md:35 +msgid "" +"* `anyhow::Result` is a type alias for `Result`.\n" +"* `anyhow::Error` is essentially a wrapper around `Box`. As such " +"it's again generally not\n" +" a good choice for the public API of a library, but is widely used in " +"applications.\n" +"* Actual error type inside of it can be extracted for examination if " +"necessary.\n" +"* Functionality provided by `anyhow::Result` may be familiar to Go " +"developers, as it provides\n" +" similar usage patterns and ergonomics to `(T, error)` from Go." msgstr "" -#: src/modules/filesystem.md:11 -msgid "" -"* `src/garden.rs` (modern Rust 2018 style)\n" -"* `src/garden/mod.rs` (older Rust 2015 style)" +#: src/testing.md:1 +msgid "# Testing" msgstr "" -#: src/modules/filesystem.md:14 -msgid "Similarly, a `garden::vegetables` module can be found at:" +#: src/testing.md:3 +msgid "Rust and Cargo come with a simple unit test framework:" msgstr "" -#: src/modules/filesystem.md:16 +#: src/testing.md:5 msgid "" -"* `src/garden/vegetables.rs` (modern Rust 2018 style)\n" -"* `src/garden/vegetables/mod.rs` (older Rust 2015 style)" +"* Unit tests are supported throughout your code.\n" +"\n" +"* Integration tests are supported via the `tests/` directory." msgstr "" -#: src/modules/filesystem.md:19 -msgid "The `crate` root is in:" +#: src/testing/unit-tests.md:1 +msgid "# Unit Tests" msgstr "" -#: src/modules/filesystem.md:21 -msgid "" -"* `src/lib.rs` (for a library crate)\n" -"* `src/main.rs` (for a binary crate)" +#: src/testing/unit-tests.md:3 +msgid "Mark unit tests with `#[test]`:" msgstr "" -#: src/exercises/day-2/afternoon.md:1 -msgid "# Day 2: Afternoon Exercises" +#: src/testing/unit-tests.md:5 +msgid "" +"```rust,editable,ignore\n" +"fn first_word(text: &str) -> &str {\n" +" match text.find(' ') {\n" +" Some(idx) => &text[..idx],\n" +" None => &text,\n" +" }\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty() {\n" +" assert_eq!(first_word(\"\"), \"\");\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_word() {\n" +" assert_eq!(first_word(\"Hello\"), \"Hello\");\n" +"}\n" +"\n" +"#[test]\n" +"fn test_multiple_words() {\n" +" assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-2/afternoon.md:3 -msgid "The exercises for this afternoon will focus on strings and iterators." +#: src/testing/unit-tests.md:29 +msgid "Use `cargo test` to find and run the unit tests." msgstr "" -#: src/exercises/day-2/luhn.md:1 -msgid "# Luhn Algorithm" +#: src/testing/test-modules.md:1 +msgid "# Test Modules" msgstr "" -#: src/exercises/day-2/luhn.md:3 +#: src/testing/test-modules.md:3 msgid "" -"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used " -"to\n" -"validate credit card numbers. The algorithm takes a string as input and does " -"the\n" -"following to validate the credit card number:" -msgstr "" - -#: src/exercises/day-2/luhn.md:7 -msgid "* Ignore all spaces. Reject number with less than two digits." +"Unit tests are often put in a nested module (run tests on the\n" +"[Playground](https://play.rust-lang.org/)):" msgstr "" -#: src/exercises/day-2/luhn.md:9 +#: src/testing/test-modules.md:6 msgid "" -"* Moving from right to left, double every second digit: for the number " -"`1234`,\n" -" we double `3` and `1`." +"```rust,editable\n" +"fn helper(a: &str, b: &str) -> String {\n" +" format!(\"{a} {b}\")\n" +"}\n" +"\n" +"pub fn main() {\n" +" println!(\"{}\", helper(\"Hello\", \"World\"));\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" #[test]\n" +" fn test_helper() {\n" +" assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-2/luhn.md:12 +#: src/testing/test-modules.md:26 msgid "" -"* After doubling a digit, sum the digits. So doubling `7` becomes `14` " -"which\n" -" becomes `5`." +"* This lets you unit test private helpers.\n" +"* The `#[cfg(test)]` attribute is only active when you run `cargo test`." msgstr "" -#: src/exercises/day-2/luhn.md:15 -msgid "* Sum all the undoubled and doubled digits." +#: src/testing/doc-tests.md:1 +msgid "# Documentation Tests" msgstr "" -#: src/exercises/day-2/luhn.md:17 -msgid "* The credit card number is valid if the sum ends with `0`." +#: src/testing/doc-tests.md:3 +msgid "Rust has built-in support for documentation tests:" msgstr "" -#: src/exercises/day-2/luhn.md:19 +#: src/testing/doc-tests.md:5 msgid "" -"Copy the following code to and implement the\n" -"function:" +"```rust\n" +"/// Shortens a string to the given length.\n" +"///\n" +"/// ```\n" +"/// use playground::shorten_string;\n" +"/// assert_eq!(shorten_string(\"Hello World\", 5), \"Hello\");\n" +"/// assert_eq!(shorten_string(\"Hello World\", 20), \"Hello World\");\n" +"/// ```\n" +"pub fn shorten_string(s: &str, length: usize) -> &str {\n" +" &s[..std::cmp::min(length, s.len())]\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-2/luhn.md:27 +#: src/testing/doc-tests.md:18 msgid "" -"pub fn luhn(cc_number: &str) -> bool {\n" -" unimplemented!()\n" -"}" +"* Code blocks in `///` comments are automatically seen as Rust code.\n" +"* The code will be compiled and executed as part of `cargo test`.\n" +"* Test the above code on the [Rust Playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." msgstr "" -#: src/exercises/day-2/luhn.md:31 -msgid "" -"#[test]\n" -"fn test_non_digit_cc_number() {\n" -" assert!(!luhn(\"foo\"));\n" -"}" +#: src/testing/integration-tests.md:1 +msgid "# Integration Tests" msgstr "" -#: src/exercises/day-2/luhn.md:36 src/exercises/day-2/solutions-afternoon.md:64 -msgid "" -"#[test]\n" -"fn test_empty_cc_number() {\n" -" assert!(!luhn(\"\"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -"}" +#: src/testing/integration-tests.md:3 +msgid "If you want to test your library as a client, use an integration test." msgstr "" -#: src/exercises/day-2/luhn.md:44 src/exercises/day-2/solutions-afternoon.md:72 -msgid "" -"#[test]\n" -"fn test_single_digit_cc_number() {\n" -" assert!(!luhn(\"0\"));\n" -"}" +#: src/testing/integration-tests.md:5 +msgid "Create a `.rs` file under `tests/`:" msgstr "" -#: src/exercises/day-2/luhn.md:49 src/exercises/day-2/solutions-afternoon.md:77 +#: src/testing/integration-tests.md:7 msgid "" +"```rust,ignore\n" +"use my_library::init;\n" +"\n" "#[test]\n" -"fn test_two_digit_cc_number() {\n" -" assert!(luhn(\" 0 0 \"));\n" -"}" +"fn test_init() {\n" +" assert!(init().is_ok());\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-2/luhn.md:54 src/exercises/day-2/solutions-afternoon.md:82 -msgid "" -"#[test]\n" -"fn test_valid_cc_number() {\n" -" assert!(luhn(\"4263 9826 4026 9299\"));\n" -" assert!(luhn(\"4539 3195 0343 6467\"));\n" -" assert!(luhn(\"7992 7398 713\"));\n" -"}" +#: src/testing/integration-tests.md:16 +msgid "These tests only have access to the public API of your crate." msgstr "" -#: src/exercises/day-2/luhn.md:61 -msgid "" -"#[test]\n" -"fn test_invalid_cc_number() {\n" -" assert!(!luhn(\"4223 9826 4026 9299\"));\n" -" assert!(!luhn(\"4539 3195 0343 6476\"));\n" -" assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}" +#: src/testing/useful-crates.md:1 +msgid "## Useful crates for writing tests" msgstr "" -#: src/exercises/day-2/strings-iterators.md:1 -msgid "# Strings and Iterators" +#: src/testing/useful-crates.md:3 +msgid "Rust comes with only basic support for writing tests." msgstr "" -#: src/exercises/day-2/strings-iterators.md:3 -msgid "" -"In this exercise, you are implementing a routing component of a web server. " -"The\n" -"server is configured with a number of _path prefixes_ which are matched " -"against\n" -"_request paths_. The path prefixes can contain a wildcard character which\n" -"matches a full segment. See the unit tests below." +#: src/testing/useful-crates.md:5 +msgid "Here are some additional crates which we recommend for writing tests:" msgstr "" -#: src/exercises/day-2/strings-iterators.md:8 +#: src/testing/useful-crates.md:7 msgid "" -"Copy the following code to and make the tests\n" -"pass. Try avoiding allocating a `Vec` for your intermediate results:" +"* [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/exercises/day-2/strings-iterators.md:16 -msgid "" -"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" -" unimplemented!()\n" -"}" +#: src/unsafe.md:1 +msgid "# Unsafe Rust" msgstr "" -#: src/exercises/day-2/strings-iterators.md:20 -msgid "" -"#[test]\n" -"fn test_matches_without_wildcard() {\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/" -"abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/" -"books\"));" +#: src/unsafe.md:3 +msgid "The Rust language has two parts:" msgstr "" -#: src/exercises/day-2/strings-iterators.md:26 -#: src/exercises/day-2/solutions-afternoon.md:146 +#: src/unsafe.md:5 msgid "" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/" -"publishers\"));\n" -"}" +"* **Safe Rust:** memory safe, no undefined behavior possible.\n" +"* **Unsafe Rust:** can trigger undefined behavior if preconditions are " +"violated." msgstr "" -#: src/exercises/day-2/strings-iterators.md:31 -#: src/exercises/day-2/solutions-afternoon.md:151 +#: src/unsafe.md:8 msgid "" -"#[test]\n" -"fn test_matches_with_wildcard() {\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books\"\n" -" ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/bar/books\"\n" -" ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books/book1\"\n" -" ));" +"We will be seeing mostly safe Rust in this course, but it's important to " +"know\n" +"what Unsafe Rust is." msgstr "" -#: src/exercises/day-2/strings-iterators.md:46 +#: src/unsafe.md:11 msgid "" -" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/" -"publishers\"));\n" -" assert!(!prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/booksByAuthor\"\n" -" ));\n" -"}\n" -"```" +"Unsafe code is usually small and isolated, and its correctness should be " +"carefully\n" +"documented. It is usually wrapped in a safe abstraction layer." msgstr "" -#: src/welcome-day-3.md:1 -msgid "# Welcome to Day 3" +#: src/unsafe.md:14 +msgid "Unsafe Rust gives you access to five new capabilities:" msgstr "" -#: src/welcome-day-3.md:3 -msgid "Today, we will cover some more advanced topics of Rust:" +#: src/unsafe.md:16 +msgid "" +"* Dereference raw pointers.\n" +"* Access or modify mutable static variables.\n" +"* Access `union` fields.\n" +"* Call `unsafe` functions, including `extern` functions.\n" +"* Implement `unsafe` traits." msgstr "" -#: src/welcome-day-3.md:5 +#: src/unsafe.md:22 msgid "" -"* Traits: deriving traits, default methods, and important standard library\n" -" traits." +"We will briefly cover unsafe capabilities next. For full details, please " +"see\n" +"[Chapter 19.1 in the Rust Book](https://doc.rust-lang.org/book/ch19-01-" +"unsafe-rust.html)\n" +"and the [Rustonomicon](https://doc.rust-lang.org/nomicon/)." msgstr "" -#: src/welcome-day-3.md:8 +#: src/unsafe.md:28 msgid "" -"* Generics: generic data types, generic methods, monomorphization, and " -"trait\n" -" objects." +"Unsafe Rust does not mean the code is incorrect. It means that developers " +"have\n" +"turned off the compiler safety features and have to write correct code by\n" +"themselves. It means the compiler no longer enforces Rust's memory-safety " +"rules." msgstr "" -#: src/welcome-day-3.md:11 -msgid "* Error handling: panics, `Result`, and the try operator `?`." +#: src/unsafe/raw-pointers.md:1 +msgid "# Dereferencing Raw Pointers" msgstr "" -#: src/welcome-day-3.md:13 -msgid "* Testing: unit tests, documentation tests, and integration tests." +#: src/unsafe/raw-pointers.md:3 +msgid "Creating pointers is safe, but dereferencing them requires `unsafe`:" msgstr "" -#: src/welcome-day-3.md:15 +#: src/unsafe/raw-pointers.md:5 msgid "" -"* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" -" functions." +"```rust,editable\n" +"fn main() {\n" +" let mut num = 5;\n" +"\n" +" 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\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" +" *r1 = 10;\n" +" println!(\"r2 is: {}\", *r2);\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/traits.md:1 -msgid "# Traits" +#: src/unsafe/raw-pointers.md:27 +msgid "" +"It is good practice (and required by the Android Rust style guide) to write " +"a comment for each\n" +"`unsafe` block explaining how the code inside it satisfies the safety " +"requirements of the unsafe\n" +"operations it is doing." msgstr "" -#: src/traits.md:3 +#: src/unsafe/raw-pointers.md:31 msgid "" -"Rust lets you abstract over types with traits. They're similar to interfaces:" +"In the case of pointer dereferences, this means that the pointers must be\n" +"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), i.e.:" msgstr "" -#: src/traits.md:5 +#: src/unsafe/raw-pointers.md:34 msgid "" -"```rust,editable\n" -"trait Greet {\n" -" fn say_hello(&self);\n" -"}" +" * The pointer must be non-null.\n" +" * The pointer must be _dereferenceable_ (within the bounds of a single " +"allocated object).\n" +" * The object must not have been deallocated.\n" +" * There must not be concurrent accesses to the same location.\n" +" * If the pointer was obtained by casting a reference, the underlying object " +"must be live and no\n" +" reference may be used to access the memory." msgstr "" -#: src/traits.md:10 -msgid "" -"struct Dog {\n" -" name: String,\n" -"}" +#: src/unsafe/raw-pointers.md:41 +msgid "In most cases the pointer must also be properly aligned." msgstr "" -#: src/traits.md:14 -msgid "struct Cat; // No name, cats won't respond to it anyway." +#: src/unsafe/mutable-static-variables.md:1 +msgid "# Mutable Static Variables" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:3 +msgid "It is safe to read an immutable static variable:" msgstr "" -#: src/traits.md:16 +#: src/unsafe/mutable-static-variables.md:5 msgid "" -"impl Greet for Dog {\n" -" fn say_hello(&self) {\n" -" println!(\"Wuf, my name is {}!\", self.name);\n" -" }\n" -"}" +"```rust,editable\n" +"static HELLO_WORLD: &str = \"Hello, world!\";\n" +"\n" +"fn main() {\n" +" println!(\"HELLO_WORLD: {HELLO_WORLD}\");\n" +"}\n" +"```" msgstr "" -#: src/traits.md:22 +#: src/unsafe/mutable-static-variables.md:13 msgid "" -"impl Greet for Cat {\n" -" fn say_hello(&self) {\n" -" println!(\"Miau!\");\n" -" }\n" -"}" +"However, since data races can occur, it is unsafe to read and write mutable\n" +"static variables:" msgstr "" -#: src/traits.md:28 +#: src/unsafe/mutable-static-variables.md:16 msgid "" +"```rust,editable\n" +"static mut COUNTER: u32 = 0;\n" +"\n" +"fn add_to_counter(inc: u32) {\n" +" unsafe { COUNTER += inc; } // Potential data race!\n" +"}\n" +"\n" "fn main() {\n" -" let pets: Vec> = vec![\n" -" Box::new(Dog { name: String::from(\"Fido\") }),\n" -" Box::new(Cat),\n" -" ];\n" -" for pet in pets {\n" -" pet.say_hello();\n" -" }\n" +" add_to_counter(42);\n" +"\n" +" unsafe { println!(\"COUNTER: {COUNTER}\"); } // Potential data race!\n" "}\n" "```" msgstr "" -#: src/traits/deriving-traits.md:1 -msgid "# Deriving Traits" +#: src/unsafe/mutable-static-variables.md:32 +msgid "" +"Using a mutable static is generally a bad idea, but there are some cases " +"where it might make sense\n" +"in low-level `no_std` code, such as implementing a heap allocator or working " +"with some C APIs." msgstr "" -#: src/traits/deriving-traits.md:3 -msgid "You can let the compiler derive a number of traits:" +#: src/unsafe/unions.md:1 +msgid "# Unions" msgstr "" -#: src/traits/deriving-traits.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug, Clone, PartialEq, Eq, Default)]\n" -"struct Player {\n" -" name: String,\n" -" strength: u8,\n" -" hit_points: u8,\n" -"}" +#: src/unsafe/unions.md:3 +msgid "Unions are like enums, but you need to track the active field yourself:" msgstr "" -#: src/traits/deriving-traits.md:13 +#: src/unsafe/unions.md:5 msgid "" +"```rust,editable\n" +"#[repr(C)]\n" +"union MyUnion {\n" +" i: u8,\n" +" b: bool,\n" +"}\n" +"\n" "fn main() {\n" -" let p1 = Player::default();\n" -" let p2 = p1.clone();\n" -" println!(\"Is {:?}\\nequal to {:?}?\\nThe answer is {}!\", &p1, &p2,\n" -" if p1 == p2 { \"yes\" } else { \"no\" });\n" +" let u = MyUnion { i: 42 };\n" +" println!(\"int: {}\", unsafe { u.i });\n" +" println!(\"bool: {}\", unsafe { u.b }); // Undefined behavior!\n" "}\n" -"```" -msgstr "" - -#: src/traits/default-methods.md:1 -msgid "# Default Methods" +"```" msgstr "" -#: src/traits/default-methods.md:3 -msgid "Traits can implement behavior in terms of other trait methods:" +#: src/unsafe/unions.md:21 +msgid "" +"Unions are very rarely needed in Rust as you can usually use an enum. They " +"are occasionally needed\n" +"for interacting with C library APIs." msgstr "" -#: src/traits/default-methods.md:5 +#: src/unsafe/unions.md:24 msgid "" -"```rust,editable\n" -"trait Equals {\n" -" fn equal(&self, other: &Self) -> bool;\n" -" fn not_equal(&self, other: &Self) -> bool {\n" -" !self.equal(other)\n" -" }\n" -"}" +"If you just want to reinterpret bytes as a different type, you probably " +"want\n" +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn." +"transmute.html) or a safe\n" +"wrapper such as the [`zerocopy`](https://crates.io/crates/zerocopy) crate." msgstr "" -#: src/traits/default-methods.md:13 -msgid "" -"#[derive(Debug)]\n" -"struct Centimeter(i16);" +#: src/unsafe/calling-unsafe-functions.md:1 +msgid "# Calling Unsafe Functions" msgstr "" -#: src/traits/default-methods.md:16 +#: src/unsafe/calling-unsafe-functions.md:3 msgid "" -"impl Equals for Centimeter {\n" -" fn equal(&self, other: &Centimeter) -> bool {\n" -" self.0 == other.0\n" -" }\n" -"}" +"A function or method can be marked `unsafe` if it has extra preconditions " +"you\n" +"must uphold to avoid undefined behaviour:" msgstr "" -#: src/traits/default-methods.md:22 +#: src/unsafe/calling-unsafe-functions.md:6 msgid "" +"```rust,editable\n" "fn main() {\n" -" let a = Centimeter(10);\n" -" let b = Centimeter(20);\n" -" println!(\"{a:?} equals {b:?}: {}\", a.equal(&b));\n" -" println!(\"{a:?} not_equals {b:?}: {}\", a.not_equal(&b));\n" +" let emojis = \"🗻∈🌏\";\n" +"\n" +" // Safe because the indices are in the correct order, within the bounds " +"of\n" +" // the string slice, and lie on UTF-8 sequence boundaries.\n" +" unsafe {\n" +" println!(\"emoji: {}\", emojis.get_unchecked(0..4));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(4..7));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(7..11));\n" +" }\n" +"\n" +" println!(\"char count: {}\", count_chars(unsafe { emojis." +"get_unchecked(0..7) }));\n" +"\n" +" // Not upholding the UTF-8 encoding requirement breaks memory safety!\n" +" // println!(\"emoji: {}\", unsafe { emojis.get_unchecked(0..3) });\n" +" // println!(\"char count: {}\", count_chars(unsafe { emojis." +"get_unchecked(0..3) }));\n" +"}\n" +"\n" +"fn count_chars(s: &str) -> usize {\n" +" s.chars().map(|_| 1).sum()\n" "}\n" "```" msgstr "" -#: src/traits/important-traits.md:1 -msgid "# Important Traits" +#: src/unsafe/writing-unsafe-functions.md:1 +msgid "# Writing Unsafe Functions" msgstr "" -#: src/traits/important-traits.md:3 +#: src/unsafe/writing-unsafe-functions.md:3 msgid "" -"We will now look at some of the most common traits of the Rust standard " -"library:" +"You can mark your own functions as `unsafe` if they require particular " +"conditions to avoid undefined\n" +"behaviour." msgstr "" -#: src/traits/important-traits.md:5 +#: src/unsafe/writing-unsafe-functions.md:6 msgid "" -"* `Iterator` and `IntoIterator` used in `for` loops,\n" -"* `From` and `Into` used to convert values,\n" -"* `Read` and `Write` used for IO,\n" -"* `Add`, `Mul`, ... used for operator overloading, and\n" -"* `Drop` used for defining destructors." -msgstr "" - -#: src/traits/iterator.md:1 -msgid "# Iterators" +"```rust,editable\n" +"/// Swaps the values pointed to by the given pointers.\n" +"///\n" +"/// # Safety\n" +"///\n" +"/// The pointers must be valid and properly aligned.\n" +"unsafe fn swap(a: *mut u8, b: *mut u8) {\n" +" let temp = *a;\n" +" *a = *b;\n" +" *b = temp;\n" +"}\n" +"\n" +"fn main() {\n" +" let mut a = 42;\n" +" let mut b = 66;\n" +"\n" +" // Safe because ...\n" +" unsafe {\n" +" swap(&mut a, &mut b);\n" +" }\n" +"\n" +" println!(\"a = {}, b = {}\", a, b);\n" +"}\n" +"```" msgstr "" -#: src/traits/iterator.md:3 -msgid "You can implement the `Iterator` trait on your own types:" +#: src/unsafe/writing-unsafe-functions.md:33 +msgid "" +"We wouldn't actually use pointers for this because it can be done safely " +"with references." msgstr "" -#: src/traits/iterator.md:5 +#: src/unsafe/writing-unsafe-functions.md:35 msgid "" -"```rust,editable\n" -"struct Fibonacci {\n" -" curr: u32,\n" -" next: u32,\n" -"}" +"Note that unsafe code is allowed within an unsafe function without an " +"`unsafe` block. We can\n" +"prohibit this with `#[deny(unsafe_op_in_unsafe_fn)]`. Try adding it and see " +"what happens." msgstr "" -#: src/traits/iterator.md:11 -msgid "" -"impl Iterator for Fibonacci {\n" -" type Item = u32;" +#: src/unsafe/extern-functions.md:1 +msgid "# Calling External Code" msgstr "" -#: src/traits/iterator.md:14 +#: src/unsafe/extern-functions.md:3 msgid "" -" fn next(&mut self) -> Option {\n" -" let new_next = self.curr + self.next;\n" -" self.curr = self.next;\n" -" self.next = new_next;\n" -" Some(self.curr)\n" -" }\n" -"}" +"Functions from other languages might violate the guarantees of Rust. " +"Calling\n" +"them is thus unsafe:" msgstr "" -#: src/traits/iterator.md:22 +#: src/unsafe/extern-functions.md:6 msgid "" +"```rust,editable\n" +"extern \"C\" {\n" +" fn abs(input: i32) -> i32;\n" +"}\n" +"\n" "fn main() {\n" -" let fib = Fibonacci { curr: 0, next: 1 };\n" -" for (i, n) in fib.enumerate().take(5) {\n" -" println!(\"fib({i}): {n}\");\n" +" unsafe {\n" +" // Undefined behavior if abs misbehaves.\n" +" println!(\"Absolute value of -3 according to C: {}\", abs(-3));\n" " }\n" "}\n" "```" msgstr "" -#: src/traits/iterator.md:32 +#: src/unsafe/extern-functions.md:21 msgid "" -"`IntoIterator` is the trait that makes for loops work. It is implemented by " -"collection types such as\n" -"`Vec` and references to them such as `&Vec` and `&[T]`. Ranges also " -"implement it." +"This is usually only a problem for extern functions which do things with " +"pointers which might\n" +"violate Rust's memory model, but in general any C function might have " +"undefined behaviour under any\n" +"arbitrary circumstances." msgstr "" -#: src/traits/from-iterator.md:1 -msgid "# FromIterator" +#: src/unsafe/extern-functions.md:25 +msgid "" +"The `\"C\"` in this example is the ABI;\n" +"[other ABIs are available too](https://doc.rust-lang.org/reference/items/" +"external-blocks.html)." msgstr "" -#: src/traits/from-iterator.md:3 -msgid "`FromIterator` lets you build a collection from an `Iterator`." +#: src/unsafe/unsafe-traits.md:1 +msgid "# Implementing Unsafe Traits" msgstr "" -#: src/traits/from-iterator.md:5 +#: src/unsafe/unsafe-traits.md:3 +msgid "" +"Like with functions, you can mark a trait as `unsafe` if the implementation " +"must guarantee\n" +"particular conditions to avoid undefined behaviour." +msgstr "" + +#: src/unsafe/unsafe-traits.md:6 +msgid "" +"For example, the `zerocopy` crate has an unsafe trait that looks\n" +"[something like this](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes." +"html):" +msgstr "" + +#: src/unsafe/unsafe-traits.md:9 msgid "" "```rust,editable\n" -"fn main() {\n" -" let primes = vec![2, 3, 5, 7];\n" -" let prime_squares = primes.into_iter().map(|prime| prime * prime)." -"collect::>();\n" +"use std::mem::size_of_val;\n" +"use std::slice;\n" +"\n" +"/// ...\n" +"/// # Safety\n" +"/// The type must have a defined representation and no padding.\n" +"pub unsafe trait AsBytes {\n" +" fn as_bytes(&self) -> &[u8] {\n" +" unsafe {\n" +" slice::from_raw_parts(self as *const Self as *const u8, " +"size_of_val(self))\n" +" }\n" +" }\n" "}\n" +"\n" +"// Safe because u32 has a defined representation and no padding.\n" +"unsafe impl AsBytes for u32 {}\n" "```" msgstr "" -#: src/traits/from-iterator.md:14 +#: src/unsafe/unsafe-traits.md:30 msgid "" -"`Iterator` implements\n" -"`fn collect(self) -> B\n" -"where\n" -" B: FromIterator,\n" -" Self: Sized`" +"There should be a `# Safety` section on the Rustdoc for the trait explaining " +"the requirements for\n" +"the trait to be safely implemented." msgstr "" -#: src/traits/from-iterator.md:20 +#: src/unsafe/unsafe-traits.md:33 msgid "" -"There are also implementations which let you do cool things like convert an\n" -"`Iterator>` into a `Result, E>`." +"The actual safety section for `AsBytes` is rather longer and more " +"complicated." msgstr "" -#: src/traits/read-write.md:1 -msgid "# `Read` and `Write`" +#: src/unsafe/unsafe-traits.md:35 +msgid "The built-in `Send` and `Sync` traits are unsafe." msgstr "" -#: src/traits/read-write.md:3 -msgid "Using `Read` and `BufRead`, you can abstract over `u8` sources:" +#: src/exercises/day-3/afternoon.md:1 +msgid "# Day 3: Afternoon Exercises" msgstr "" -#: src/traits/read-write.md:5 -msgid "" -"```rust,editable\n" -"use std::io::{BufRead, BufReader, Read, Result};" +#: src/exercises/day-3/afternoon.md:3 +msgid "Let us build a safe wrapper for reading directory content!" msgstr "" -#: src/traits/read-write.md:8 -msgid "" -"fn count_lines(reader: R) -> usize {\n" -" let buf_reader = BufReader::new(reader);\n" -" buf_reader.lines().count()\n" -"}" +#: src/exercises/day-3/afternoon.md:7 +msgid "After looking at the exercise, you can look at the [solution] provided." msgstr "" -#: src/traits/read-write.md:13 -msgid "" -"fn main() -> Result<()> {\n" -" let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" -" println!(\"lines in slice: {}\", count_lines(slice));" +#: src/exercises/day-3/safe-ffi-wrapper.md:1 +msgid "# Safe FFI Wrapper" msgstr "" -#: src/traits/read-write.md:17 +#: src/exercises/day-3/safe-ffi-wrapper.md:3 msgid "" -" let file = std::fs::File::open(std::env::current_exe()?)?;\n" -" println!(\"lines in file: {}\", count_lines(file));\n" -" Ok(())\n" -"}\n" -"```" +"Rust has great support for calling functions through a _foreign function\n" +"interface_ (FFI). We will use this to build a safe wrapper for the `libc`\n" +"functions you would use from C to read the filenames of a directory." msgstr "" -#: src/traits/read-write.md:23 -msgid "Similarly, `Write` lets you abstract over `u8` sinks:" +#: src/exercises/day-3/safe-ffi-wrapper.md:7 +msgid "You will want to consult the manual pages:" msgstr "" -#: src/traits/read-write.md:25 +#: src/exercises/day-3/safe-ffi-wrapper.md:9 msgid "" -"```rust,editable\n" -"use std::io::{Result, Write};" +"* [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)\n" +"* [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)\n" +"* [`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)" msgstr "" -#: src/traits/read-write.md:28 +#: src/exercises/day-3/safe-ffi-wrapper.md:13 msgid "" -"fn log(writer: &mut W, msg: &str) -> Result<()> {\n" -" writer.write_all(msg.as_bytes())?;\n" -" writer.write_all(\"\\n\".as_bytes())\n" -"}" +"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/traits/read-write.md:33 +#: src/exercises/day-3/safe-ffi-wrapper.md:16 msgid "" -"fn main() -> Result<()> {\n" -" let mut buffer = Vec::new();\n" -" log(&mut buffer, \"Hello\")?;\n" -" log(&mut buffer, \"World\")?;\n" -" println!(\"Logged: {:?}\", buffer);\n" -" Ok(())\n" -"}\n" -"```" +"| 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 "" -#: src/traits/operators.md:1 -msgid "# `Add`, `Mul`, ..." +#: src/exercises/day-3/safe-ffi-wrapper.md:22 +msgid "You will convert between all these types:" msgstr "" -#: src/traits/operators.md:3 -msgid "Operator overloading is implemented via traits in `std::ops`:" +#: 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/traits/operators.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug, Copy, Clone)]\n" -"struct Point { x: i32, y: i32 }" +#: src/exercises/day-3/safe-ffi-wrapper.md:34 +msgid "The [Nomicon] also has a very useful chapter about FFI." msgstr "" -#: src/traits/operators.md:9 src/exercises/day-2/solutions-morning.md:46 +#: src/exercises/day-3/safe-ffi-wrapper.md:45 msgid "" -"impl std::ops::Add for Point {\n" -" type Output = Self;" +"Copy the code below to and fill in the " +"missing\n" +"functions and methods:" msgstr "" -#: src/traits/operators.md:12 +#: src/exercises/day-3/safe-ffi-wrapper.md:48 msgid "" -" fn add(self, other: Self) -> Self {\n" -" Self {x: self.x + other.x, y: self.y + other.y}\n" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int};\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" use std::os::raw::{c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::" +"PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-" +"gnu.\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" // Layout as per man entry for dirent\n" +" #[cfg(target_os = \"macos\")]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: u64,\n" +" pub d_seekoff: u64,\n" +" pub d_reclen: u16,\n" +" pub d_namlen: u16,\n" +" pub d_type: u8,\n" +" pub d_name: [c_char; 1024],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}\n" +"\n" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" unimplemented!()\n" " }\n" -"}" +"}\n" +"\n" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/android.md:1 +msgid "# Welcome to Rust in Android" msgstr "" -#: src/traits/operators.md:17 +#: src/android.md:3 msgid "" -"fn main() {\n" -" let p1 = Point { x: 10, y: 20 };\n" -" let p2 = Point { x: 100, y: 200 };\n" -" println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" -"}\n" -"```" +"Rust is supported for native platform development on Android. This means " +"that\n" +"you can write new operating system services in Rust, as well as extending\n" +"existing services." msgstr "" -#: src/traits/drop.md:1 -msgid "# The `Drop` Trait" +#: src/android.md:7 +msgid "" +"> We will attempt to call Rust from one of your own projects today. So try " +"to\n" +"> find a little corner of your code base where we can move some lines of " +"code to\n" +"> Rust. The fewer dependencies and \"exotic\" types the better. Something " +"that\n" +"> parses some raw bytes would be ideal." +msgstr "" + +#: src/android/setup.md:1 +msgid "# Setup" msgstr "" -#: src/traits/drop.md:3 +#: src/android/setup.md:3 msgid "" -"Values which implement `Drop` can specify code to run when they go out of " -"scope:" +"We will be using an Android Virtual Device to test our code. Make sure you " +"have\n" +"access to one or create a new one with:" msgstr "" -#: src/traits/drop.md:5 +#: src/android/setup.md:6 msgid "" -"```rust,editable\n" -"struct Droppable {\n" -" name: &'static str,\n" -"}" +"```shell\n" +"$ source build/envsetup.sh\n" +"$ lunch aosp_cf_x86_64_phone-userdebug\n" +"$ acloud create\n" +"```" msgstr "" -#: src/traits/drop.md:10 +#: src/android/setup.md:12 msgid "" -"impl Drop for Droppable {\n" -" fn drop(&mut self) {\n" -" println!(\"Dropping {}\", self.name);\n" -" }\n" -"}" +"Please see the [Android Developer\n" +"Codelab](https://source.android.com/docs/setup/start) for details." msgstr "" -#: src/traits/drop.md:16 -msgid "" -"fn main() {\n" -" let a = Droppable { name: \"a\" };\n" -" {\n" -" let b = Droppable { name: \"b\" };\n" -" {\n" -" let c = Droppable { name: \"c\" };\n" -" let d = Droppable { name: \"d\" };\n" -" println!(\"Exiting block B\");\n" -" }\n" -" println!(\"Exiting block A\");\n" -" }\n" -" drop(a);\n" -" println!(\"Exiting main\");\n" -"}\n" -"```" +#: src/android/build-rules.md:1 +msgid "# Build Rules" msgstr "" -#: src/generics.md:1 -msgid "# Generics" +#: src/android/build-rules.md:3 +msgid "The Android build system (Soong) supports Rust via a number of modules:" msgstr "" -#: src/generics.md:3 +#: src/android/build-rules.md:5 msgid "" -"Rust support generics, which lets you abstract an algorithm (such as " -"sorting)\n" -"over the types used in the algorithm." +"| Module Type | " +"Description " +"|\n" +"|-------------------|----------------------------------------------------------------------------------------------------|\n" +"| `rust_binary` | Produces a Rust " +"binary. " +"|\n" +"| `rust_library` | Produces a Rust library, and provides both `rlib` and " +"`dylib` variants. |\n" +"| `rust_ffi` | Produces a Rust C library usable by `cc` modules, and " +"provides both static and shared variants. |\n" +"| `rust_proc_macro` | Produces a `proc-macro` Rust library. These are " +"analogous to compiler plugins. |\n" +"| `rust_test` | Produces a Rust test binary that uses the standard " +"Rust test harness. |\n" +"| `rust_fuzz` | Produces a Rust fuzz binary leveraging " +"`libfuzzer`. |\n" +"| `rust_protobuf` | Generates source and produces a Rust library that " +"provides an interface for a particular protobuf. |\n" +"| `rust_bindgen` | Generates source and produces a Rust library " +"containing Rust bindings to C libraries. |" msgstr "" -#: src/generics/data-types.md:1 -msgid "# Generic Data Types" +#: src/android/build-rules.md:16 +msgid "We will look at `rust_binary` and `rust_library` next." msgstr "" -#: src/generics/data-types.md:3 -msgid "You can use generics to abstract over the concrete field type:" +#: src/android/build-rules/binary.md:1 +msgid "# Rust Binaries" msgstr "" -#: src/generics/data-types.md:5 +#: src/android/build-rules/binary.md:3 msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point {\n" -" x: T,\n" -" y: T,\n" -"}" +"Let us start with a simple application. At the root of an AOSP checkout, " +"create\n" +"the following files:" +msgstr "" + +#: src/android/build-rules/binary.md:6 src/android/build-rules/library.md:13 +msgid "_hello_rust/Android.bp_:" msgstr "" -#: src/generics/data-types.md:12 +#: src/android/build-rules/binary.md:8 msgid "" -"fn main() {\n" -" let integer = Point { x: 5, y: 10 };\n" -" let float = Point { x: 1.0, y: 4.0 };\n" -" println!(\"{integer:?} and {float:?}\");\n" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust\",\n" +" crate_name: \"hello_rust\",\n" +" srcs: [\"src/main.rs\"],\n" "}\n" "```" msgstr "" -#: src/generics/methods.md:1 -msgid "# Generic Methods" -msgstr "" - -#: src/generics/methods.md:3 -msgid "You can declare a generic type on your `impl` block:" +#: src/android/build-rules/binary.md:16 src/android/build-rules/library.md:34 +msgid "_hello_rust/src/main.rs_:" msgstr "" -#: src/generics/methods.md:5 +#: src/android/build-rules/binary.md:18 msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(T, T);" +"```rust\n" +"//! Rust demo.\n" +"\n" +"/// Prints a greeting to standard output.\n" +"fn main() {\n" +" println!(\"Hello from Rust!\");\n" +"}\n" +"```" msgstr "" -#: src/generics/methods.md:9 -msgid "" -"impl Point {\n" -" fn x(&self) -> &T {\n" -" &self.0 // + 10\n" -" }" +#: src/android/build-rules/binary.md:27 +msgid "You can now build, push, and run the binary:" msgstr "" -#: src/generics/methods.md:14 +#: src/android/build-rules/binary.md:29 msgid "" -" // fn set_x(&mut self, x: T)\n" -"}" +"```shell\n" +"$ m hello_rust\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust\n" +"Hello from Rust!\n" +"```" msgstr "" -#: src/generics/methods.md:17 -msgid "" -"fn main() {\n" -" let p = Point(5, 10);\n" -" println!(\"p.x = {}\", p.x());\n" -"}\n" -"```" +#: src/android/build-rules/library.md:1 +msgid "# Rust Libraries" msgstr "" -#: src/generics/trait-bounds.md:1 -msgid "# Trait Bounds" +#: src/android/build-rules/library.md:3 +msgid "You use `rust_library` to create a new Rust library for Android." msgstr "" -#: src/generics/trait-bounds.md:3 -msgid "" -"When working with generics, you often want to limit the types. You can do " -"this\n" -"with `T: Trait` or `impl Trait`:" +#: src/android/build-rules/library.md:5 +msgid "Here we declare a dependency on two libraries:" msgstr "" -#: src/generics/trait-bounds.md:6 +#: src/android/build-rules/library.md:7 msgid "" -"```rust,editable\n" -"fn duplicate(a: T) -> (T, T) {\n" -" (a.clone(), a.clone())\n" -"}" +"* `libgreeting`, which we define below,\n" +"* `libtextwrap`, which is a crate already vendored in\n" +" [`external/rust/crates/`][crates]." msgstr "" -#: src/generics/trait-bounds.md:11 -msgid "// struct NotClonable;" +#: src/android/build-rules/library.md:15 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_with_dep\",\n" +" crate_name: \"hello_rust_with_dep\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libgreetings\",\n" +" \"libtextwrap\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"\n" +"rust_library {\n" +" name: \"libgreetings\",\n" +" crate_name: \"greetings\",\n" +" srcs: [\"src/lib.rs\"],\n" +"}\n" +"```" msgstr "" -#: src/generics/trait-bounds.md:13 +#: src/android/build-rules/library.md:36 msgid "" +"```rust,ignore\n" +"//! Rust demo.\n" +"\n" +"use greetings::greeting;\n" +"use textwrap::fill;\n" +"\n" +"/// Prints a greeting to standard output.\n" "fn main() {\n" -" let foo = String::from(\"foo\");\n" -" let pair = duplicate(foo);\n" +" println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" "}\n" "```" msgstr "" -#: src/generics/impl-trait.md:1 -msgid "# `impl Trait`" +#: src/android/build-rules/library.md:48 +msgid "_hello_rust/src/lib.rs_:" msgstr "" -#: src/generics/impl-trait.md:3 +#: src/android/build-rules/library.md:50 msgid "" -"Similar to trait bounds, an `impl Trait` syntax can be used in function\n" -"arguments and return values:" +"```rust,ignore\n" +"//! Greeting library.\n" +"\n" +"/// Greet `name`.\n" +"pub fn greeting(name: &str) -> String {\n" +" format!(\"Hello {name}, it is very nice to meet you!\")\n" +"}\n" +"```" msgstr "" -#: src/generics/impl-trait.md:6 src/generics/trait-objects.md:5 -#: src/generics/trait-objects.md:28 -msgid "" -"```rust,editable\n" -"use std::fmt::Display;" +#: src/android/build-rules/library.md:59 +msgid "You build, push, and run the binary like before:" msgstr "" -#: src/generics/impl-trait.md:9 +#: src/android/build-rules/library.md:61 msgid "" -"fn get_x(name: impl Display) -> impl Display {\n" -" format!(\"Hello {name}\")\n" -"}" +"```shell\n" +"$ m hello_rust_with_dep\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/" +"tmp\n" +"$ adb shell /data/local/tmp/hello_rust_with_dep\n" +"Hello Bob, it is very\n" +"nice to meet you!\n" +"```" msgstr "" -#: src/generics/impl-trait.md:13 -msgid "" -"fn main() {\n" -" let x = get_x(\"foo\");\n" -" println!(\"{x}\");\n" -"}\n" -"```" +#: src/android/aidl.md:1 +msgid "# AIDL" msgstr "" -#: src/generics/impl-trait.md:19 +#: src/android/aidl.md:3 msgid "" -"* `impl Trait` cannot be used with the `::<>` turbo fish syntax.\n" -"* `impl Trait` allows you to work with types which you cannot name." +"The [Android Interface Definition Language\n" +"(AIDL)](https://developer.android.com/guide/components/aidl) is supported in " +"Rust:" msgstr "" -#: src/generics/impl-trait.md:24 +#: src/android/aidl.md:6 msgid "" -"The meaning of `impl Trait` is a bit different in the different positions." +"* Rust code can call existing AIDL servers,\n" +"* You can create new AIDL servers in Rust." msgstr "" -#: src/generics/impl-trait.md:26 -msgid "" -"* For a parameter, `impl Trait` is like an anonymous generic parameter with " -"a trait bound.\n" -"* For a return type, it means that the return type is some concrete type " -"that implements the trait,\n" -" without naming the type. This can be useful when you don't want to expose " -"the concrete type in a\n" -" public API." +#: src/android/aidl/interface.md:1 +msgid "# AIDL Interfaces" msgstr "" -#: src/generics/closures.md:1 -msgid "# Closures" +#: src/android/aidl/interface.md:3 +msgid "You declare the API of your service using an AIDL interface:" msgstr "" -#: src/generics/closures.md:3 +#: src/android/aidl/interface.md:5 msgid "" -"Closures or lambda expressions have types which cannot be named. However, " -"they\n" -"implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" -"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and\n" -"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:" +"*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" msgstr "" -#: src/generics/closures.md:8 +#: src/android/aidl/interface.md:7 msgid "" -"```rust,editable\n" -"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" -" println!(\"Calling function on {input}\");\n" -" func(input)\n" -"}" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years);\n" +"}\n" +"```" msgstr "" -#: src/generics/closures.md:14 -msgid "" -"fn main() {\n" -" let add_3 = |x| x + 3;\n" -" let mul_5 = |x| x * 5;" +#: src/android/aidl/interface.md:17 +msgid "*birthday_service/aidl/Android.bp*:" msgstr "" -#: src/generics/closures.md:18 +#: src/android/aidl/interface.md:19 msgid "" -" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" -" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" +"```javascript\n" +"aidl_interface {\n" +" name: \"com.example.birthdayservice\",\n" +" srcs: [\"com/example/birthdayservice/*.aidl\"],\n" +" unstable: true,\n" +" backend: {\n" +" rust: { // Rust is not enabled by default\n" +" enabled: true,\n" +" },\n" +" },\n" "}\n" "```" msgstr "" -#: src/generics/closures.md:25 -msgid "" -"If you have an `FnOnce`, you may only call it once. It might consume " -"captured values." -msgstr "" - -#: src/generics/closures.md:27 +#: src/android/aidl/interface.md:32 msgid "" -"An `FnMut` might mutate captured values, so you can call it multiple times " -"but not concurrently." +"Add `vendor_available: true` if your AIDL file is used by a binary in the " +"vendor\n" +"partition." msgstr "" -#: src/generics/closures.md:29 -msgid "" -"An `Fn` neither consumes nor mutates captured values, or perhaps captures " -"nothing at all, so it can\n" -"be called multiple times concurrently." +#: src/android/aidl/implementation.md:1 +msgid "# Service Implementation" msgstr "" -#: src/generics/closures.md:32 -msgid "" -"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. " -"I.e. you can use an\n" -"`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever " -"an `FnMut` or `FnOnce`\n" -"is called for." +#: src/android/aidl/implementation.md:3 +msgid "We can now implement the AIDL service:" msgstr "" -#: src/generics/closures.md:36 -msgid "`move` closures only implement `FnOnce`." +#: src/android/aidl/implementation.md:5 +msgid "*birthday_service/src/lib.rs*:" msgstr "" -#: src/generics/monomorphization.md:1 -msgid "# Monomorphization" +#: src/android/aidl/implementation.md:7 +msgid "" +"```rust,ignore\n" +"//! Implementation of the `IBirthdayService` AIDL interface.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::" +"IBirthdayService::IBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"/// The `IBirthdayService` implementation.\n" +"pub struct BirthdayService;\n" +"\n" +"impl binder::Interface for BirthdayService {}\n" +"\n" +"impl IBirthdayService for BirthdayService {\n" +" fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::" +"Result {\n" +" Ok(format!(\n" +" \"Happy Birthday {name}, congratulations with the {years} years!" +"\"\n" +" ))\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/generics/monomorphization.md:3 -msgid "Generic code is turned into non-generic code based on the call sites:" +#: src/android/aidl/implementation.md:26 src/android/aidl/server.md:28 +#: src/android/aidl/client.md:37 +msgid "*birthday_service/Android.bp*:" msgstr "" -#: src/generics/monomorphization.md:5 +#: src/android/aidl/implementation.md:28 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let integer = Some(5);\n" -" let float = Some(5.0);\n" +"```javascript\n" +"rust_library {\n" +" name: \"libbirthdayservice\",\n" +" srcs: [\"src/lib.rs\"],\n" +" crate_name: \"birthdayservice\",\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" "}\n" "```" msgstr "" -#: src/generics/monomorphization.md:12 -msgid "behaves as if you wrote" +#: src/android/aidl/server.md:1 +msgid "# AIDL Server" msgstr "" -#: src/generics/monomorphization.md:14 -msgid "" -"```rust,editable\n" -"enum Option_i32 {\n" -" Some(i32),\n" -" None,\n" -"}" +#: src/android/aidl/server.md:3 +msgid "Finally, we can create a server which exposes the service:" msgstr "" -#: src/generics/monomorphization.md:20 -msgid "" -"enum Option_f64 {\n" -" Some(f64),\n" -" None,\n" -"}" +#: src/android/aidl/server.md:5 +msgid "*birthday_service/src/server.rs*:" msgstr "" -#: src/generics/monomorphization.md:25 +#: src/android/aidl/server.md:7 msgid "" +"```rust,ignore\n" +"//! Birthday service.\n" +"use birthdayservice::BirthdayService;\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::" +"IBirthdayService::BnBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" +"/// Entry point for birthday service.\n" "fn main() {\n" -" let integer = Option_i32::Some(5);\n" -" let float = Option_f64::Some(5.0);\n" +" let birthday_service = BirthdayService;\n" +" let birthday_service_binder = BnBirthdayService::new_binder(\n" +" birthday_service,\n" +" binder::BinderFeatures::default(),\n" +" );\n" +" binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder." +"as_binder())\n" +" .expect(\"Failed to register service\");\n" +" binder::ProcessState::join_thread_pool()\n" "}\n" "```" msgstr "" -#: src/generics/monomorphization.md:31 +#: src/android/aidl/server.md:30 msgid "" -"This is a zero-cost abstraction: you get exactly the same result as if you " -"had\n" -"hand-coded the data structures without the abstraction." -msgstr "" - -#: src/generics/trait-objects.md:1 -msgid "# Trait Objects" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_server\",\n" +" crate_name: \"birthday_server\",\n" +" srcs: [\"src/server.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" \"libbirthdayservice\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" msgstr "" -#: src/generics/trait-objects.md:3 -msgid "We've seen how a function can take arguments which implement a trait:" +#: src/android/aidl/deploy.md:1 +msgid "# Deploy" msgstr "" -#: src/generics/trait-objects.md:8 -msgid "" -"fn print(x: T) {\n" -" println!(\"Your value: {}\", x);\n" -"}" +#: src/android/aidl/deploy.md:3 +msgid "We can now build, push, and start the service:" msgstr "" -#: src/generics/trait-objects.md:12 +#: src/android/aidl/deploy.md:5 msgid "" -"fn main() {\n" -" print(123);\n" -" print(\"Hello\");\n" -"}\n" +"```shell\n" +"$ m birthday_server\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_server\n" "```" msgstr "" -#: src/generics/trait-objects.md:18 -msgid "" -"However, how can we store a collection of mixed types which implement " -"`Display`?" +#: src/android/aidl/deploy.md:11 +msgid "In another terminal, check that the service runs:" msgstr "" -#: src/generics/trait-objects.md:20 +#: src/android/aidl/deploy.md:13 msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let xs = vec![123, \"Hello\"];\n" -"}\n" +"```shell\n" +"$ adb shell service check birthdayservice\n" +"Service birthdayservice: found\n" "```" msgstr "" -#: src/generics/trait-objects.md:26 -msgid "For this, we need _trait objects_:" +#: src/android/aidl/deploy.md:18 +msgid "You can also call the service with `service call`:" msgstr "" -#: src/generics/trait-objects.md:31 +#: src/android/aidl/deploy.md:20 msgid "" -"fn main() {\n" -" let xs: Vec> = vec![Box::new(123), Box::" -"new(\"Hello\")];\n" -" for x in xs {\n" -" println!(\"x: {x}\");\n" -" }\n" -"}\n" +"```shell\n" +"$ $ adb shell service call birthdayservice 1 s16 Bob i32 24\n" +"Result: Parcel(\n" +" 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" +" 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" +" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'\n" +" 0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'\n" +" 0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'\n" +" 0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'\n" +" 0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'\n" +" 0x00000070: 00210073 00000000 's.!..... ')\n" "```" msgstr "" -#: src/generics/trait-objects.md:39 -msgid "Memory layout after allocating `xs`:" +#: src/android/aidl/client.md:1 +msgid "# AIDL Client" msgstr "" -#: src/generics/trait-objects.md:41 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - " -"- - -.\n" -": : : :\n" -": " -"xs : : :\n" -": +-----------+-------+ : : +-----+-----" -"+ :\n" -": | ptr | o---+---+-----+-->| o o | o o " -"| :\n" -": | len | 2 | : : +-|-|-+-|-|-" -"+ :\n" -": | capacity | 2 | : : | | | | +----+----+----+----+----" -"+ :\n" -": +-----------+-------+ : : | | | '-->| H | e | l | l | o " -"| :\n" -": : : | | | +----+----+----+----+----" -"+ :\n" -"`- - - - - - - - - - - - - -' : | | " -"| :\n" -" : | | | " -"+-------------------------+ :\n" -" : | | '---->| \"::" -"fmt\" | :\n" -" : | | " -"+-------------------------+ :\n" -" : | " -"| :\n" -" : | | +----+----+----+----" -"+ :\n" -" : | '-->| 7b | 00 | 00 | 00 " -"| :\n" -" : | +----+----+----+----" -"+ :\n" -" : " -"| :\n" -" : | +-------------------------" -"+ :\n" -" : '---->| \"::fmt\" " -"| :\n" -" : +-------------------------" -"+ :\n" -" : :\n" -" : :\n" -" '- - - - - - - - - - - - - - - - - - - - - " -"- - -'\n" -"```" +#: src/android/aidl/client.md:3 +msgid "Finally, we can create a Rust client for our new service." msgstr "" -#: src/generics/trait-objects.md:69 -msgid "" -"Similarly, you need a trait object if you want to return different values\n" -"implementing a trait:" +#: src/android/aidl/client.md:5 +msgid "*birthday_service/src/client.rs*:" msgstr "" -#: src/generics/trait-objects.md:72 +#: src/android/aidl/client.md:7 msgid "" -"```rust,editable\n" -"fn numbers(n: i32) -> Box> {\n" -" if n > 0 {\n" -" Box::new(0..n)\n" -" } else {\n" -" Box::new((n..0).rev())\n" -" }\n" -"}" +"```rust,ignore\n" +"//! Birthday service.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::" +"IBirthdayService::IBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" +"/// Connect to the BirthdayService.\n" +"pub fn connect() -> Result, binder::" +"StatusCode> {\n" +" binder::get_interface(SERVICE_IDENTIFIER)\n" +"}\n" +"\n" +"/// Call the birthday service.\n" +"fn main() -> Result<(), binder::Status> {\n" +" let name = std::env::args()\n" +" .nth(1)\n" +" .unwrap_or_else(|| String::from(\"Bob\"));\n" +" let years = std::env::args()\n" +" .nth(2)\n" +" .and_then(|arg| arg.parse::().ok())\n" +" .unwrap_or(42);\n" +"\n" +" binder::ProcessState::start_thread_pool();\n" +" let service = connect().expect(\"Failed to connect to " +"BirthdayService\");\n" +" let msg = service.wishHappyBirthday(&name, years)?;\n" +" println!(\"{msg}\");\n" +" Ok(())\n" +"}\n" +"```" msgstr "" -#: src/generics/trait-objects.md:81 +#: src/android/aidl/client.md:39 msgid "" -"fn main() {\n" -" println!(\"{:?}\", numbers(-5).collect::>());\n" -" println!(\"{:?}\", numbers(5).collect::>());\n" -"}" -msgstr "" - -#: src/exercises/day-3/morning.md:1 -msgid "# Day 3: Morning Exercises" -msgstr "" - -#: src/exercises/day-3/morning.md:3 -msgid "We will design a classical GUI library traits and trait objects." -msgstr "" - -#: src/exercises/day-3/simple-gui.md:1 -msgid "# A Simple GUI Library" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_client\",\n" +" crate_name: \"birthday_client\",\n" +" srcs: [\"src/client.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-3/simple-gui.md:3 -msgid "" -"Let us design a classical GUI library using our new knowledge of traits and\n" -"trait objects." +#: src/android/aidl/client.md:52 +msgid "Notice that the client does not depend on `libbirthdayservice`." msgstr "" -#: src/exercises/day-3/simple-gui.md:6 -msgid "We will have a number of widgets in our library:" +#: src/android/aidl/client.md:54 +msgid "Build, push, and run the client on your device:" msgstr "" -#: src/exercises/day-3/simple-gui.md:8 +#: src/android/aidl/client.md:56 msgid "" -"* `Window`: has a `title` and contains other widgets.\n" -"* `Button`: has a `label` and a callback function which is invoked when the\n" -" button is pressed.\n" -"* `Label`: has a `label`." -msgstr "" - -#: src/exercises/day-3/simple-gui.md:13 -msgid "The widgets will implement a `Widget` trait, see below." +"```shell\n" +"$ m birthday_client\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_client Charlie 60\n" +"Happy Birthday Charlie, congratulations with the 60 years!\n" +"```" msgstr "" -#: src/exercises/day-3/simple-gui.md:15 -msgid "" -"Copy the code below to , fill in the missing\n" -"`draw_into` methods so that you implement the `Widget` trait:" +#: src/android/aidl/changing.md:1 +msgid "# Changing API" msgstr "" -#: src/exercises/day-3/simple-gui.md:18 -#: src/exercises/day-3/safe-ffi-wrapper.md:25 +#: src/android/aidl/changing.md:3 msgid "" -"```rust,should_panic\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_imports, unused_variables, dead_code)]" +"Let us extend the API with more functionality: we want to let clients " +"specify a\n" +"list of lines for the birthday card:" msgstr "" -#: src/exercises/day-3/simple-gui.md:22 +#: src/android/aidl/changing.md:6 msgid "" -"pub trait Widget {\n" -" /// Natural width of `self`.\n" -" fn width(&self) -> usize;" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years, in String[] text);\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-3/simple-gui.md:26 -#: src/exercises/day-3/solutions-morning.md:27 -msgid "" -" /// Draw the widget into a buffer.\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);" +#: src/android/logging.md:1 src/bare-metal/aps/logging.md:1 +msgid "# Logging" msgstr "" -#: src/exercises/day-3/simple-gui.md:29 -#: src/exercises/day-3/solutions-morning.md:30 +#: src/android/logging.md:3 msgid "" -" /// Draw the widget on standard output.\n" -" fn draw(&self) {\n" -" let mut buffer = String::new();\n" -" self.draw_into(&mut buffer);\n" -" println!(\"{}\", &buffer);\n" -" }\n" -"}" +"You should use the `log` crate to automatically log to `logcat` (on-device) " +"or\n" +"`stdout` (on-host):" msgstr "" -#: src/exercises/day-3/simple-gui.md:37 -#: src/exercises/day-3/solutions-morning.md:38 -msgid "" -"pub struct Label {\n" -" label: String,\n" -"}" +#: src/android/logging.md:6 +msgid "_hello_rust_logs/Android.bp_:" msgstr "" -#: src/exercises/day-3/simple-gui.md:41 -#: src/exercises/day-3/solutions-morning.md:42 +#: src/android/logging.md:8 msgid "" -"impl Label {\n" -" fn new(label: &str) -> Label {\n" -" Label {\n" -" label: label.to_owned(),\n" -" }\n" -" }\n" -"}" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_logs\",\n" +" crate_name: \"hello_rust_logs\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"liblog_rust\",\n" +" \"liblogger\",\n" +" ],\n" +" prefer_rlib: true,\n" +" host_supported: true,\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-3/simple-gui.md:49 -#: src/exercises/day-3/solutions-morning.md:50 -msgid "" -"pub struct Button {\n" -" label: Label,\n" -" callback: Box,\n" -"}" +#: src/android/logging.md:22 +msgid "_hello_rust_logs/src/main.rs_:" msgstr "" -#: src/exercises/day-3/simple-gui.md:54 -#: src/exercises/day-3/solutions-morning.md:55 +#: src/android/logging.md:24 msgid "" -"impl Button {\n" -" fn new(label: &str, callback: Box) -> Button {\n" -" Button {\n" -" label: Label::new(label),\n" -" callback,\n" -" }\n" -" }\n" -"}" +"```rust,ignore\n" +"//! Rust logging demo.\n" +"\n" +"use log::{debug, error, info};\n" +"\n" +"/// Logs a greeting.\n" +"fn main() {\n" +" logger::init(\n" +" logger::Config::default()\n" +" .with_tag_on_device(\"rust\")\n" +" .with_min_level(log::Level::Trace),\n" +" );\n" +" debug!(\"Starting program.\");\n" +" info!(\"Things are going fine.\");\n" +" error!(\"Something went wrong!\");\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-3/simple-gui.md:63 -#: src/exercises/day-3/solutions-morning.md:64 -msgid "" -"pub struct Window {\n" -" title: String,\n" -" widgets: Vec>,\n" -"}" +#: src/android/logging.md:42 src/android/interoperability/with-c/bindgen.md:98 +#: src/android/interoperability/with-c/rust.md:73 +msgid "Build, push, and run the binary on your device:" msgstr "" -#: src/exercises/day-3/simple-gui.md:68 -#: src/exercises/day-3/solutions-morning.md:69 +#: src/android/logging.md:44 msgid "" -"impl Window {\n" -" fn new(title: &str) -> Window {\n" -" Window {\n" -" title: title.to_owned(),\n" -" widgets: Vec::new(),\n" -" }\n" -" }" +"```shell\n" +"$ m hello_rust_logs\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust_logs\n" +"```" msgstr "" -#: src/exercises/day-3/simple-gui.md:76 -#: src/exercises/day-3/solutions-morning.md:77 -msgid "" -" fn add_widget(&mut self, widget: Box) {\n" -" self.widgets.push(widget);\n" -" }\n" -"}" +#: src/android/logging.md:50 +msgid "The logs show up in `adb logcat`:" msgstr "" -#: src/exercises/day-3/simple-gui.md:82 +#: src/android/logging.md:52 msgid "" -"impl Widget for Label {\n" -" fn width(&self) -> usize {\n" -" unimplemented!()\n" -" }" +"```shell\n" +"$ adb logcat -s rust\n" +"09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.\n" +"09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going " +"fine.\n" +"09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went " +"wrong!\n" +"```" msgstr "" -#: src/exercises/day-3/simple-gui.md:87 src/exercises/day-3/simple-gui.md:97 -#: src/exercises/day-3/simple-gui.md:107 -msgid "" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" unimplemented!()\n" -" }\n" -"}" +#: src/android/interoperability.md:1 +msgid "# Interoperability" msgstr "" -#: src/exercises/day-3/simple-gui.md:92 +#: src/android/interoperability.md:3 msgid "" -"impl Widget for Button {\n" -" fn width(&self) -> usize {\n" -" unimplemented!()\n" -" }" +"Rust has excellent support for interoperability with other languages. This " +"means\n" +"that you can:" msgstr "" -#: src/exercises/day-3/simple-gui.md:102 +#: src/android/interoperability.md:6 msgid "" -"impl Widget for Window {\n" -" fn width(&self) -> usize {\n" -" unimplemented!()\n" -" }" +"* Call Rust functions from other languages.\n" +"* Call functions written in other languages from Rust." msgstr "" -#: src/exercises/day-3/simple-gui.md:112 +#: src/android/interoperability.md:9 msgid "" -"fn main() {\n" -" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" -" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo." -"\")));\n" -" window.add_widget(Box::new(Button::new(\n" -" \"Click me!\",\n" -" Box::new(|| println!(\"You clicked the button!\")),\n" -" )));\n" -" window.draw();\n" -"}\n" -"```" +"When you call functions in a foreign language we say that you're using a\n" +"_foreign function interface_, also known as FFI." msgstr "" -#: src/exercises/day-3/simple-gui.md:123 -msgid "The output of the above program can be something simple like this:" +#: src/android/interoperability/with-c.md:1 +msgid "# Interoperability with C" msgstr "" -#: src/exercises/day-3/simple-gui.md:125 +#: src/android/interoperability/with-c.md:3 msgid "" -"```text\n" -"========\n" -"Rust GUI Demo 1.23\n" -"========" +"Rust has full support for linking object files with a C calling convention.\n" +"Similarly, you can export Rust functions and call them from C." msgstr "" -#: src/exercises/day-3/simple-gui.md:130 -msgid "This is a small text GUI demo." +#: src/android/interoperability/with-c.md:6 +msgid "You can do it by hand if you want:" msgstr "" -#: src/exercises/day-3/simple-gui.md:132 +#: src/android/interoperability/with-c.md:8 msgid "" -"| Click me! |\n" +"```rust\n" +"extern \"C\" {\n" +" fn abs(x: i32) -> i32;\n" +"}\n" +"\n" +"fn main() {\n" +" let x = -42;\n" +" let abs_x = unsafe { abs(x) };\n" +" println!(\"{x}, {abs_x}\");\n" +"}\n" "```" msgstr "" -#: src/exercises/day-3/simple-gui.md:135 +#: src/android/interoperability/with-c.md:20 msgid "" -"If you want to draw aligned text, you can use the\n" -"[fill/alignment](https://doc.rust-lang.org/std/fmt/index." -"html#fillalignment)\n" -"formatting operators. In particular, notice how you can pad with different\n" -"characters (here a `'/'`) and how you can control alignment:" +"We already saw this in the [Safe FFI Wrapper\n" +"exercise](../../exercises/day-3/safe-ffi-wrapper.md)." msgstr "" -#: src/exercises/day-3/simple-gui.md:140 +#: src/android/interoperability/with-c.md:23 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let width = 10;\n" -" println!(\"left aligned: |{:/width$}|\", \"foo\");\n" -"}\n" -"```" +"> This assumes full knowledge of the target platform. Not recommended for\n" +"> production." msgstr "" -#: src/exercises/day-3/simple-gui.md:149 -msgid "" -"Using such alignment tricks, you can for example produce output like this:" +#: src/android/interoperability/with-c.md:26 +msgid "We will look at better options next." msgstr "" -#: src/exercises/day-3/simple-gui.md:151 -msgid "" -"```text\n" -"+--------------------------------+\n" -"| Rust GUI Demo 1.23 |\n" -"+================================+\n" -"| This is a small text GUI demo. |\n" -"| +-----------+ |\n" -"| | Click me! | |\n" -"| +-----------+ |\n" -"+--------------------------------+\n" -"```" +#: src/android/interoperability/with-c/bindgen.md:1 +msgid "# Using Bindgen" msgstr "" -#: src/error-handling.md:1 -msgid "# Error Handling" +#: src/android/interoperability/with-c/bindgen.md:3 +msgid "" +"The [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html) " +"tool\n" +"can auto-generate bindings from a C header file." msgstr "" -#: src/error-handling.md:3 -msgid "Error handling in Rust is done using explicit control flow:" +#: src/android/interoperability/with-c/bindgen.md:6 +msgid "First create a small C library:" msgstr "" -#: src/error-handling.md:5 -msgid "" -"* Functions that can have errors list this in their return type,\n" -"* There are no exceptions." +#: src/android/interoperability/with-c/bindgen.md:8 +msgid "_interoperability/bindgen/libbirthday.h_:" msgstr "" -#: src/error-handling/panics.md:1 -msgid "# Panics" +#: src/android/interoperability/with-c/bindgen.md:10 +msgid "" +"```c\n" +"typedef struct card {\n" +" const char* name;\n" +" int years;\n" +"} card;\n" +"\n" +"void print_card(const card* card);\n" +"```" msgstr "" -#: src/error-handling/panics.md:3 -msgid "Rust will trigger a panic if a fatal error happens at runtime:" +#: src/android/interoperability/with-c/bindgen.md:19 +msgid "_interoperability/bindgen/libbirthday.c_:" msgstr "" -#: src/error-handling/panics.md:5 +#: src/android/interoperability/with-c/bindgen.md:21 msgid "" -"```rust,editable,should_panic\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" println!(\"v[100]: {}\", v[100]);\n" +"```c\n" +"#include \n" +"#include \"libbirthday.h\"\n" +"\n" +"void print_card(const card* card) {\n" +" printf(\"+--------------\\n\");\n" +" printf(\"| Happy Birthday %s!\\n\", card->name);\n" +" printf(\"| Congratulations with the %i years!\\n\", card->years);\n" +" printf(\"+--------------\\n\");\n" "}\n" "```" msgstr "" -#: src/error-handling/panics.md:12 -msgid "" -"* Panics are for unrecoverable and unexpected errors.\n" -" * Panics are symptoms of bugs in the program.\n" -"* Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." +#: src/android/interoperability/with-c/bindgen.md:33 +msgid "Add this to your `Android.bp` file:" msgstr "" -#: src/error-handling/panic-unwind.md:1 -msgid "# Catching the Stack Unwinding" +#: src/android/interoperability/with-c/bindgen.md:35 +#: src/android/interoperability/with-c/bindgen.md:55 +#: src/android/interoperability/with-c/bindgen.md:69 +#: src/android/interoperability/with-c/bindgen.md:108 +msgid "_interoperability/bindgen/Android.bp_:" msgstr "" -#: src/error-handling/panic-unwind.md:3 +#: src/android/interoperability/with-c/bindgen.md:37 msgid "" -"By default, a panic will cause the stack to unwind. The unwinding can be " -"caught:" +"```javascript\n" +"cc_library {\n" +" name: \"libbirthday\",\n" +" srcs: [\"libbirthday.c\"],\n" +"}\n" +"```" msgstr "" -#: src/error-handling/panic-unwind.md:5 +#: src/android/interoperability/with-c/bindgen.md:44 msgid "" -"```rust\n" -"use std::panic;" +"Create a wrapper header file for the library (not strictly needed in this\n" +"example):" msgstr "" -#: src/error-handling/panic-unwind.md:8 -msgid "" -"let result = panic::catch_unwind(|| {\n" -" println!(\"hello!\");\n" -"});\n" -"assert!(result.is_ok());" +#: src/android/interoperability/with-c/bindgen.md:47 +msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" msgstr "" -#: src/error-handling/panic-unwind.md:13 +#: src/android/interoperability/with-c/bindgen.md:49 msgid "" -"let result = panic::catch_unwind(|| {\n" -" panic!(\"oh no!\");\n" -"});\n" -"assert!(result.is_err());\n" +"```c\n" +"#include \"libbirthday.h\"\n" "```" msgstr "" -#: src/error-handling/panic-unwind.md:19 +#: src/android/interoperability/with-c/bindgen.md:53 +msgid "You can now auto-generate the bindings:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:57 msgid "" -"* This can be useful in servers which should keep running even if a single\n" -" request crashes.\n" -"* This does not work if `panic = abort` is set in your `Cargo.toml`." +"```javascript\n" +"rust_bindgen {\n" +" name: \"libbirthday_bindgen\",\n" +" crate_name: \"birthday_bindgen\",\n" +" wrapper_src: \"libbirthday_wrapper.h\",\n" +" source_stem: \"bindings\",\n" +" static_libs: [\"libbirthday\"],\n" +"}\n" +"```" msgstr "" -#: src/error-handling/result.md:1 -msgid "# Structured Error Handling with `Result`" +#: src/android/interoperability/with-c/bindgen.md:67 +msgid "Finally, we can use the bindings in our Rust program:" msgstr "" -#: src/error-handling/result.md:3 +#: src/android/interoperability/with-c/bindgen.md:71 msgid "" -"We have already seen the `Result` enum. This is used pervasively when errors " -"are\n" -"expected as part of normal operation:" +"```javascript\n" +"rust_binary {\n" +" name: \"print_birthday_card\",\n" +" srcs: [\"main.rs\"],\n" +" rustlibs: [\"libbirthday_bindgen\"],\n" +"}\n" +"```" msgstr "" -#: src/error-handling/result.md:6 -msgid "" -"```rust\n" -"use std::fs::File;\n" -"use std::io::Read;" +#: src/android/interoperability/with-c/bindgen.md:79 +msgid "_interoperability/bindgen/main.rs_:" msgstr "" -#: src/error-handling/result.md:10 +#: src/android/interoperability/with-c/bindgen.md:81 msgid "" +"```rust,compile_fail\n" +"//! Bindgen demo.\n" +"\n" +"use birthday_bindgen::{card, print_card};\n" +"\n" "fn main() {\n" -" let file = File::open(\"diary.txt\");\n" -" match file {\n" -" Ok(mut file) => {\n" -" let mut contents = String::new();\n" -" file.read_to_string(&mut contents);\n" -" println!(\"Dear diary: {contents}\");\n" -" },\n" -" Err(err) => {\n" -" println!(\"The diary could not be opened: {err}\");\n" -" }\n" +" let name = std::ffi::CString::new(\"Peter\").unwrap();\n" +" let card = card {\n" +" name: name.as_ptr(),\n" +" years: 42,\n" +" };\n" +" unsafe {\n" +" print_card(&card as *const card);\n" " }\n" "}\n" "```" msgstr "" -#: src/error-handling/try-operator.md:1 -msgid "# Propagating Errors with `?`" +#: src/android/interoperability/with-c/bindgen.md:100 +msgid "" +"```shell\n" +"$ m print_birthday_card\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/" +"tmp\n" +"$ adb shell /data/local/tmp/print_birthday_card\n" +"```" msgstr "" -#: src/error-handling/try-operator.md:3 -msgid "" -"The try-operator `?` is used to return errors to the caller. It lets you " -"turn\n" -"the common" +#: src/android/interoperability/with-c/bindgen.md:106 +msgid "Finally, we can run auto-generated tests to ensure the bindings work:" msgstr "" -#: src/error-handling/try-operator.md:6 +#: src/android/interoperability/with-c/bindgen.md:110 msgid "" -"```rust,ignore\n" -"match some_expression {\n" -" Ok(value) => value,\n" -" Err(err) => return Err(err),\n" +"```javascript\n" +"rust_test {\n" +" name: \"libbirthday_bindgen_test\",\n" +" srcs: [\":libbirthday_bindgen\"],\n" +" crate_name: \"libbirthday_bindgen_test\",\n" +" test_suites: [\"general-tests\"],\n" +" auto_gen_config: true,\n" +" clippy_lints: \"none\", // Generated file, skip linting\n" +" lints: \"none\",\n" "}\n" "```" msgstr "" -#: src/error-handling/try-operator.md:13 -msgid "into the much simpler" -msgstr "" - -#: src/error-handling/try-operator.md:15 +#: src/android/interoperability/with-c/bindgen.md:122 msgid "" -"```rust,ignore\n" -"some_expression?\n" +"```shell\n" +"$ atest libbirthday_bindgen_test\n" "```" msgstr "" -#: src/error-handling/try-operator.md:19 -msgid "We can use this to simplify our error handing code:" +#: src/android/interoperability/with-c/rust.md:1 +msgid "# Calling Rust" msgstr "" -#: src/error-handling/try-operator.md:21 -msgid "" -"```rust,editable\n" -"use std::fs;\n" -"use std::io::{self, Read};" +#: src/android/interoperability/with-c/rust.md:3 +msgid "Exporting Rust functions and types to C is easy:" msgstr "" -#: src/error-handling/try-operator.md:25 -msgid "" -"fn read_username(path: &str) -> Result {\n" -" let username_file_result = fs::File::open(path);" +#: src/android/interoperability/with-c/rust.md:5 +msgid "_interoperability/rust/libanalyze/analyze.rs_" msgstr "" -#: src/error-handling/try-operator.md:28 +#: src/android/interoperability/with-c/rust.md:7 msgid "" -" let mut username_file = match username_file_result {\n" -" Ok(file) => file,\n" -" Err(e) => return Err(e),\n" -" };" -msgstr "" - -#: src/error-handling/try-operator.md:33 -msgid " let mut username = String::new();" +"```rust,editable\n" +"//! Rust FFI demo.\n" +"#![deny(improper_ctypes_definitions)]\n" +"\n" +"use std::os::raw::c_int;\n" +"\n" +"/// Analyze the numbers.\n" +"#[no_mangle]\n" +"pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" +" if x < y {\n" +" println!(\"x ({x}) is smallest!\");\n" +" } else {\n" +" println!(\"y ({y}) is probably larger than x ({x})\");\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/error-handling/try-operator.md:35 -msgid "" -" match username_file.read_to_string(&mut username) {\n" -" Ok(_) => Ok(username),\n" -" Err(e) => Err(e),\n" -" }\n" -"}" +#: src/android/interoperability/with-c/rust.md:24 +msgid "_interoperability/rust/libanalyze/analyze.h_" msgstr "" -#: src/error-handling/try-operator.md:41 +#: src/android/interoperability/with-c/rust.md:26 msgid "" -"fn main() {\n" -" //fs::write(\"config.dat\", \"alice\").unwrap();\n" -" let username = read_username(\"config.dat\");\n" -" println!(\"username or error: {username:?}\");\n" +"```c\n" +"#ifndef ANALYSE_H\n" +"#define ANALYSE_H\n" +"\n" +"extern \"C\" {\n" +"void analyze_numbers(int x, int y);\n" "}\n" +"\n" +"#endif\n" "```" msgstr "" -#: src/error-handling/try-operator.md:52 -#: src/error-handling/converting-error-types.md:57 +#: src/android/interoperability/with-c/rust.md:37 +msgid "_interoperability/rust/libanalyze/Android.bp_" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:39 msgid "" -"* The `username` variable can be either `Ok(string)` or `Err(error)`.\n" -"* Use the `fs::write` call to test out the different scenarios: no file, " -"empty file, file with username." +"```javascript\n" +"rust_ffi {\n" +" name: \"libanalyze_ffi\",\n" +" crate_name: \"analyze_ffi\",\n" +" srcs: [\"analyze.rs\"],\n" +" include_dirs: [\".\"],\n" +"}\n" +"```" msgstr "" -#: src/error-handling/converting-error-types.md:1 -msgid "# Converting Error Types" +#: src/android/interoperability/with-c/rust.md:48 +msgid "We can now call this from a C binary:" msgstr "" -#: src/error-handling/converting-error-types.md:3 -msgid "" -"The effective expansion of `?` is a little more complicated than previously " -"indicated:" +#: src/android/interoperability/with-c/rust.md:50 +msgid "_interoperability/rust/analyze/main.c_" msgstr "" -#: src/error-handling/converting-error-types.md:5 +#: src/android/interoperability/with-c/rust.md:52 msgid "" -"```rust,ignore\n" -"expression?\n" +"```c\n" +"#include \"analyze.h\"\n" +"\n" +"int main() {\n" +" analyze_numbers(10, 20);\n" +" analyze_numbers(123, 123);\n" +" return 0;\n" +"}\n" "```" msgstr "" -#: src/error-handling/converting-error-types.md:9 -msgid "works the same as" +#: src/android/interoperability/with-c/rust.md:62 +msgid "_interoperability/rust/analyze/Android.bp_" msgstr "" -#: src/error-handling/converting-error-types.md:11 +#: src/android/interoperability/with-c/rust.md:64 msgid "" -"```rust,ignore\n" -"match expression {\n" -" Ok(value) => value,\n" -" Err(err) => return Err(From::from(err)),\n" +"```javascript\n" +"cc_binary {\n" +" name: \"analyze_numbers\",\n" +" srcs: [\"main.c\"],\n" +" static_libs: [\"libanalyze_ffi\"],\n" "}\n" "```" msgstr "" -#: src/error-handling/converting-error-types.md:18 +#: src/android/interoperability/with-c/rust.md:75 msgid "" -"The `From::from` call here means we attempt to convert the error type to " -"the\n" -"type returned by the function:" +"```shell\n" +"$ m analyze_numbers\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp\n" +"$ adb shell /data/local/tmp/analyze_numbers\n" +"```" msgstr "" -#: src/error-handling/converting-error-types.md:21 +#: src/android/interoperability/with-c/rust.md:83 msgid "" -"```rust,editable\n" -"use std::{fs, io};\n" -"use std::io::Read;" +"`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol " +"will just be the name of\n" +"the function. You can also use `#[export_name = \"some_name\"]` to specify " +"whatever name you want." msgstr "" -#: src/error-handling/converting-error-types.md:25 -msgid "" -"#[derive(Debug)]\n" -"enum ReadUsernameError {\n" -" IoError(io::Error),\n" -" EmptyUsername(String),\n" -"}" +#: src/android/interoperability/cpp.md:1 +msgid "# With C++" msgstr "" -#: src/error-handling/converting-error-types.md:31 +#: src/android/interoperability/cpp.md:3 msgid "" -"impl From for ReadUsernameError {\n" -" fn from(err: io::Error) -> ReadUsernameError {\n" -" ReadUsernameError::IoError(err)\n" -" }\n" -"}" +"The [CXX crate][1] makes it possible to do safe interoperability between " +"Rust\n" +"and C++." msgstr "" -#: src/error-handling/converting-error-types.md:37 -#: src/error-handling/deriving-error-enums.md:19 -msgid "" -"fn read_username(path: &str) -> Result {\n" -" let mut username = String::with_capacity(100);\n" -" fs::File::open(path)?.read_to_string(&mut username)?;\n" -" if username.is_empty() {\n" -" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" -" }\n" -" Ok(username)\n" -"}" +#: src/android/interoperability/cpp.md:6 +msgid "The overall approach looks like this:" msgstr "" -#: src/error-handling/converting-error-types.md:46 -msgid "" -"fn main() {\n" -" //fs::write(\"config.dat\", \"\").unwrap();\n" -" let username = read_username(\"config.dat\");\n" -" println!(\"username or error: {username:?}\");\n" -"}\n" -"```" +#: src/android/interoperability/cpp.md:8 +msgid "" msgstr "" -#: src/error-handling/deriving-error-enums.md:1 -msgid "# Deriving Error Enums" +#: src/android/interoperability/cpp.md:10 +msgid "See the [CXX tutorial][2] for an full example of using this." msgstr "" -#: src/error-handling/deriving-error-enums.md:3 -msgid "" -"The [thiserror](https://docs.rs/thiserror/) crate is a popular way to create " -"an\n" -"error enum like we did on the previous page:" +#: src/android/interoperability/java.md:1 +msgid "# Interoperability with Java" msgstr "" -#: src/error-handling/deriving-error-enums.md:6 +#: src/android/interoperability/java.md:3 msgid "" -"```rust,editable,compile_fail\n" -"use std::{fs, io};\n" -"use std::io::Read;\n" -"use thiserror::Error;" +"Java can load shared objects via [Java Native Interface\n" +"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). The [`jni`\n" +"crate](https://docs.rs/jni/) allows you to create a compatible library." msgstr "" -#: src/error-handling/deriving-error-enums.md:11 -msgid "" -"#[derive(Error, Debug)]\n" -"enum ReadUsernameError {\n" -" #[error(\"Could not read: {0}\")]\n" -" IoError(#[from] io::Error),\n" -" #[error(\"Found no username in {0}\")]\n" -" EmptyUsername(String),\n" -"}" +#: src/android/interoperability/java.md:7 +msgid "First, we create a Rust function to export to Java:" +msgstr "" + +#: src/android/interoperability/java.md:9 +msgid "_interoperability/java/src/lib.rs_:" msgstr "" -#: src/error-handling/deriving-error-enums.md:28 +#: src/android/interoperability/java.md:11 msgid "" -"fn main() {\n" -" //fs::write(\"config.dat\", \"\").unwrap();\n" -" match read_username(\"config.dat\") {\n" -" Ok(username) => println!(\"Username: {username}\"),\n" -" Err(err) => println!(\"Error: {err}\"),\n" -" }\n" +"```rust,compile_fail\n" +"//! Rust <-> Java FFI demo.\n" +"\n" +"use jni::objects::{JClass, JString};\n" +"use jni::sys::jstring;\n" +"use jni::JNIEnv;\n" +"\n" +"/// HelloWorld::hello method implementation.\n" +"#[no_mangle]\n" +"pub extern \"system\" fn Java_HelloWorld_hello(\n" +" env: JNIEnv,\n" +" _class: JClass,\n" +" name: JString,\n" +") -> jstring {\n" +" let input: String = env.get_string(name).unwrap().into();\n" +" let greeting = format!(\"Hello, {input}!\");\n" +" let output = env.new_string(greeting).unwrap();\n" +" output.into_inner()\n" "}\n" "```" msgstr "" -#: src/error-handling/error-contexts.md:1 -msgid "# Adding Context to Errors" +#: src/android/interoperability/java.md:32 +#: src/android/interoperability/java.md:62 +msgid "_interoperability/java/Android.bp_:" msgstr "" -#: src/error-handling/error-contexts.md:3 +#: src/android/interoperability/java.md:34 msgid "" -"The widely used [anyhow](https://docs.rs/anyhow/) crate can help you add\n" -"contextual information to your errors and allows you to have fewer\n" -"custom error types:" +"```javascript\n" +"rust_ffi_shared {\n" +" name: \"libhello_jni\",\n" +" crate_name: \"hello_jni\",\n" +" srcs: [\"src/lib.rs\"],\n" +" rustlibs: [\"libjni\"],\n" +"}\n" +"```" msgstr "" -#: src/error-handling/error-contexts.md:7 -msgid "" -"```rust,editable,compile_fail\n" -"use std::{fs, io};\n" -"use std::io::Read;\n" -"use thiserror::Error;\n" -"use anyhow::{Context, Result};" +#: src/android/interoperability/java.md:43 +msgid "Finally, we can call this function from Java:" msgstr "" -#: src/error-handling/error-contexts.md:13 -msgid "" -"#[derive(Error, Debug)]\n" -"enum ReadUsernameError {\n" -" #[error(\"Found no username in {0}\")]\n" -" EmptyUsername(String),\n" -"}" +#: src/android/interoperability/java.md:45 +msgid "_interoperability/java/HelloWorld.java_:" msgstr "" -#: src/error-handling/error-contexts.md:19 +#: src/android/interoperability/java.md:47 msgid "" -"fn read_username(path: &str) -> Result {\n" -" let mut username = String::with_capacity(100);\n" -" fs::File::open(path)\n" -" .context(format!(\"Failed to open {path}\"))?\n" -" .read_to_string(&mut username)\n" -" .context(\"Failed to read\")?;\n" -" if username.is_empty() {\n" -" return Err(ReadUsernameError::EmptyUsername(String::from(path)))?;\n" +"```java\n" +"class HelloWorld {\n" +" private static native String hello(String name);\n" +"\n" +" static {\n" +" System.loadLibrary(\"hello_jni\");\n" " }\n" -" Ok(username)\n" -"}" -msgstr "" - -#: src/error-handling/error-contexts.md:31 -msgid "" -"fn main() {\n" -" //fs::write(\"config.dat\", \"\").unwrap();\n" -" match read_username(\"config.dat\") {\n" -" Ok(username) => println!(\"Username: {username}\"),\n" -" Err(err) => println!(\"Error: {err:?}\"),\n" +"\n" +" public static void main(String[] args) {\n" +" String output = HelloWorld.hello(\"Alice\");\n" +" System.out.println(output);\n" " }\n" "}\n" "```" msgstr "" -#: src/testing.md:1 -msgid "# Testing" -msgstr "" - -#: src/testing.md:3 -msgid "Rust and Cargo come with a simple unit test framework:" -msgstr "" - -#: src/testing.md:5 -msgid "* Unit tests are supported throughout your code." -msgstr "" - -#: src/testing.md:7 -msgid "* Integration tests are supported via the `tests/` directory." -msgstr "" - -#: src/testing/unit-tests.md:1 -msgid "# Unit Tests" +#: src/android/interoperability/java.md:64 +msgid "" +"```javascript\n" +"java_binary {\n" +" name: \"helloworld_jni\",\n" +" srcs: [\"HelloWorld.java\"],\n" +" main_class: \"HelloWorld\",\n" +" required: [\"libhello_jni\"],\n" +"}\n" +"```" msgstr "" -#: src/testing/unit-tests.md:3 -msgid "Mark unit tests with `#[test]`:" +#: src/android/interoperability/java.md:73 +msgid "Finally, you can build, sync, and run the binary:" msgstr "" -#: src/testing/unit-tests.md:5 +#: src/android/interoperability/java.md:75 msgid "" -"```rust,editable\n" -"fn first_word(text: &str) -> &str {\n" -" match text.find(' ') {\n" -" Some(idx) => &text[..idx],\n" -" None => &text,\n" -" }\n" -"}" +"```shell\n" +"$ m helloworld_jni\n" +"$ adb sync # requires adb root && adb remount\n" +"$ adb shell /system/bin/helloworld_jni\n" +"```" msgstr "" -#: src/testing/unit-tests.md:13 -msgid "" -"#[test]\n" -"fn test_empty() {\n" -" assert_eq!(first_word(\"\"), \"\");\n" -"}" +#: 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 +msgid "# Exercises" msgstr "" -#: src/testing/unit-tests.md:18 +#: src/exercises/android/morning.md:3 msgid "" -"#[test]\n" -"fn test_single_word() {\n" -" assert_eq!(first_word(\"Hello\"), \"Hello\");\n" -"}" +"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 "" -#: src/testing/unit-tests.md:23 +#: src/exercises/android/morning.md:6 msgid "" -"#[test]\n" -"fn test_multiple_words() {\n" -" assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" -"}\n" -"```" +"* Call your AIDL service with a client written in Rust.\n" +"\n" +"* Move a function from your project to Rust and call it." msgstr "" -#: src/testing/unit-tests.md:29 -msgid "Use `cargo test` to find and run the unit tests." +#: src/exercises/android/morning.md:12 +msgid "" +"No solution is provided here since this is open-ended: it relies on someone " +"in\n" +"the class having a piece of code which you can turn in to Rust on the fly." msgstr "" -#: src/testing/test-modules.md:1 -msgid "# Test Modules" -msgstr "" +#: src/bare-metal.md:1 +#, fuzzy +msgid "# Welcome to Bare Metal Rust" +msgstr "# Velkommen til Comprehensive Rust 🦀" -#: src/testing/test-modules.md:3 +#: src/bare-metal.md:3 msgid "" -"Unit tests are often put in a nested module (run tests on the\n" -"[Playground](https://play.rust-lang.org/)):" +"This is a standalone one-day course about bare-metal Rust, aimed at people " +"who are familiar with the\n" +"basics of Rust (perhaps from completing the Comprehensive Rust course), and " +"ideally also have some\n" +"experience with bare-metal programming in some other language such as C." msgstr "" -#: src/testing/test-modules.md:6 +#: src/bare-metal.md:7 msgid "" -"```rust,editable\n" -"fn helper(a: &str, b: &str) -> String {\n" -" format!(\"{a} {b}\")\n" -"}" +"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/testing/test-modules.md:11 +#: src/bare-metal.md:10 msgid "" -"pub fn main() {\n" -" println!(\"{}\", helper(\"Hello\", \"World\"));\n" -"}" +"- What is `no_std` Rust?\n" +"- Writing firmware for microcontrollers.\n" +"- Writing bootloader / kernel code for application processors.\n" +"- Some useful crates for bare-metal Rust development." msgstr "" -#: src/testing/test-modules.md:19 +#: src/bare-metal.md:15 msgid "" -" #[test]\n" -" fn test_helper() {\n" -" assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" -" }\n" -"}\n" -"```" +"For the microcontroller part of the course we will use the [BBC micro:bit]" +"(https://microbit.org/) v2\n" +"as an example. It's a [development board](https://tech.microbit.org/" +"hardware/) based on the Nordic\n" +"nRF51822 microcontroller with some LEDs and buttons, an I2C-connected " +"accelerometer and compass, and\n" +"an on-board SWD debugger." msgstr "" -#: src/testing/test-modules.md:26 +#: src/bare-metal.md:20 msgid "" -"* This lets you unit test private helpers.\n" -"* The `#[cfg(test)]` attribute is only active when you run `cargo test`." +"To get started, install some tools we'll need later. On gLinux or Debian:" msgstr "" -#: src/testing/doc-tests.md:1 -msgid "# Documentation Tests" +#: src/bare-metal.md:22 +msgid "" +"```bash\n" +"sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom pkg-" +"config qemu-system-arm\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" msgstr "" -#: src/testing/doc-tests.md:3 -msgid "Rust has built-in support for documentation tests:" +#: src/bare-metal.md:30 +msgid "" +"And give users in the `plugdev` group access to the micro:bit programmer:" msgstr "" -#: src/testing/doc-tests.md:5 +#: src/bare-metal.md:32 msgid "" -"```rust\n" -"/// Shortens a string to the given length.\n" -"///\n" -"/// ```\n" -"/// use playground::shorten_string;\n" -"/// assert_eq!(shorten_string(\"Hello World\", 5), \"Hello\");\n" -"/// assert_eq!(shorten_string(\"Hello World\", 20), \"Hello World\");\n" -"/// ```\n" -"pub fn shorten_string(s: &str, length: usize) -> &str {\n" -" &s[..std::cmp::min(length, s.len())]\n" -"}\n" +"```bash\n" +"echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", " +"GROUP=\"plugdev\"' |\\\n" +" sudo tee /etc/udev/rules.d/50-microbit.rules\n" +"sudo udevadm control --reload-rules\n" "```" msgstr "" -#: src/testing/doc-tests.md:18 +#: src/bare-metal.md:38 +msgid "On MacOS:" +msgstr "" + +#: src/bare-metal.md:40 msgid "" -"* Code blocks in `///` comments are automatically seen as Rust code.\n" -"* The code will be compiled and executed as part of `cargo test`.\n" -"* Test the above code on the [Rust Playground](https://play.rust-lang.org/?" -"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." +"```bash\n" +"xcode-select --install\n" +"brew install gdb picocom qemu\n" +"brew install --cask gcc-aarch64-embedded\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" msgstr "" -#: src/testing/integration-tests.md:1 -msgid "# Integration Tests" +#: src/bare-metal/no_std.md:1 +msgid "# `no_std`" msgstr "" -#: src/testing/integration-tests.md:3 -msgid "If you want to test your library as a client, use an integration test." +#: src/bare-metal/no_std.md:3 +msgid "" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"
" msgstr "" -#: src/testing/integration-tests.md:5 -msgid "Create a `.rs` file under `tests/`:" +#: src/bare-metal/no_std.md:7 +msgid "`core`" msgstr "" -#: src/testing/integration-tests.md:7 +#: src/bare-metal/no_std.md:9 src/bare-metal/no_std.md:14 msgid "" -"```rust,ignore\n" -"use my_library::init;" +"" msgstr "" -#: src/testing/integration-tests.md:10 -msgid "" -"#[test]\n" -"fn test_init() {\n" -" assert!(init().is_ok());\n" -"}\n" -"```" +#: src/bare-metal/no_std.md:12 +msgid "`alloc`" msgstr "" -#: src/testing/integration-tests.md:16 -msgid "These tests only have access to the public API of your crate." +#: src/bare-metal/no_std.md:17 +msgid "`std`" msgstr "" -#: src/unsafe.md:1 -msgid "# Unsafe Rust" +#: src/bare-metal/no_std.md:19 +msgid "" +"
" msgstr "" -#: src/unsafe.md:3 -msgid "The Rust language has two parts:" +#: src/bare-metal/no_std.md:24 +msgid "" +"* Slices, `&str`, `CStr`\n" +"* `NonZeroU8`...\n" +"* `Option`, `Result`\n" +"* `Display`, `Debug`, `write!`...\n" +"* `Iterator`\n" +"* `panic!`, `assert_eq!`...\n" +"* `NonNull` and all the usual pointer-related functions\n" +"* `Future` and `async`/`await`\n" +"* `fence`, `AtomicBool`, `AtomicPtr`, `AtomicU32`...\n" +"* `Duration`" msgstr "" -#: src/unsafe.md:5 +#: src/bare-metal/no_std.md:35 src/bare-metal/no_std.md:42 msgid "" -"* **Safe Rust:** memory safe, no undefined behavior possible.\n" -"* **Unsafe Rust:** can trigger undefined behavior if preconditions are " -"violated." +"" msgstr "" -#: src/unsafe.md:8 +#: src/bare-metal/no_std.md:38 msgid "" -"We will be seeing mostly safe Rust in this course, but it's important to " -"know\n" -"what Unsafe Rust is." +"* `Box`, `Cow`, `Arc`, `Rc`\n" +"* `Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque`\n" +"* `String`, `CString`, `format!`" msgstr "" -#: src/unsafe.md:11 -msgid "Unsafe Rust gives you access to five new capabilities:" +#: src/bare-metal/no_std.md:45 +msgid "" +"* `Error`\n" +"* `HashMap`\n" +"* `Mutex`, `Condvar`, `Barrier`, `Once`, `RwLock`, `mpsc`\n" +"* `File` and the rest of `fs`\n" +"* `println!`, `Read`, `Write`, `Stdin`, `Stdout` and the rest of `io`\n" +"* `Path`, `OsString`\n" +"* `net`\n" +"* `Command`, `Child`, `ExitCode`\n" +"* `spawn`, `sleep` and the rest of `thread`\n" +"* `SystemTime`, `Instant`" msgstr "" -#: src/unsafe.md:13 +#: src/bare-metal/no_std.md:56 msgid "" -"* Dereference raw pointers.\n" -"* Access or modify mutable static variables.\n" -"* Access `union` fields.\n" -"* Call `unsafe` functions, including `extern` functions.\n" -"* Implement `unsafe` traits." +"
\n" +"\n" +"
" msgstr "" -#: src/unsafe.md:19 +#: src/bare-metal/no_std.md:62 msgid "" -"We will briefly cover these capabilities next. For full details, please see\n" -"[Chapter 19.1 in the Rust Book](https://doc.rust-lang.org/book/ch19-01-" -"unsafe-rust.html)\n" -"and the [Rustonomicon](https://doc.rust-lang.org/nomicon/)." +"* `HashMap` depends on RNG.\n" +"* `std` re-exports the contents of both `core` and `alloc`." msgstr "" -#: src/unsafe/raw-pointers.md:1 -msgid "# Dereferencing Raw Pointers" +#: src/bare-metal/minimal.md:1 +msgid "# A minimal `no_std` program" msgstr "" -#: src/unsafe/raw-pointers.md:3 -msgid "Creating pointers is safe, but dereferencing them requires `unsafe`:" +#: src/bare-metal/minimal.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::panic::PanicInfo;\n" +"\n" +"#[panic_handler]\n" +"fn panic(_panic: &PanicInfo) -> ! {\n" +" loop {}\n" +"}\n" +"```" msgstr "" -#: src/unsafe/raw-pointers.md:5 +#: src/bare-metal/minimal.md:17 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut num = 5;" +"* This will compile to an empty binary.\n" +"* `std` provides a panic handler; without it we must provide our own.\n" +"* It can also be provided by another crate, such as `panic-halt`.\n" +"* Depending on the target, you may need to compile with `panic = \"abort\"` " +"to avoid an error about\n" +" `eh_personality`.\n" +"* Note that there is no `main` or any other entry point; it's up to you to " +"define your own entry\n" +" point. This will typically involve a linker script and some assembly code " +"to set things up ready\n" +" for Rust code to run." msgstr "" -#: src/unsafe/raw-pointers.md:9 +#: src/bare-metal/alloc.md:1 +msgid "# `alloc`" +msgstr "" + +#: src/bare-metal/alloc.md:3 msgid "" -" let r1 = &mut num as *mut i32;\n" -" let r2 = &num as *const i32;" +"To use `alloc` you must implement a\n" +"[global (heap) allocator](https://doc.rust-lang.org/stable/std/alloc/trait." +"GlobalAlloc.html)." msgstr "" -#: src/unsafe/raw-pointers.md:12 +#: src/bare-metal/alloc.md:6 msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate alloc;\n" +"extern crate panic_halt as _;\n" +"\n" +"use alloc::string::ToString;\n" +"use alloc::vec::Vec;\n" +"use buddy_system_allocator::LockedHeap;\n" +"\n" +"#[global_allocator]\n" +"static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();\n" +"\n" +"static mut HEAP: [u8; 65536] = [0; 65536];\n" +"\n" +"pub fn entry() {\n" +" // Safe because `HEAP` is only used here and `entry` is only called " +"once.\n" " unsafe {\n" -" println!(\"r1 is: {}\", *r1);\n" -" *r1 = 10; // Data race if r1 is being written concurrently!\n" -" println!(\"r2 is: {}\", *r2);\n" +" // Give the allocator some memory to allocate.\n" +" HEAP_ALLOCATOR\n" +" .lock()\n" +" .init(HEAP.as_mut_ptr() as usize, HEAP.len());\n" " }\n" +"\n" +" // Now we can do things that require heap allocation.\n" +" let mut v = Vec::new();\n" +" v.push(\"A string\".to_string());\n" "}\n" "```" msgstr "" -#: src/unsafe/mutable-static-variables.md:1 -msgid "# Mutable Static Variables" +#: src/bare-metal/alloc.md:39 +msgid "" +"* `buddy_system_allocator` is a third-party crate implementing a basic buddy " +"system allocator. Other\n" +" crates are available, or you can write your own or hook into your existing " +"allocator.\n" +"* The const parameter of `LockedHeap` is the max order of the allocator; i." +"e. in this case it can\n" +" allocate regions of up to 2**32 bytes.\n" +"* If any crate in your dependency tree depends on `alloc` then you must have " +"exactly one global\n" +" allocator defined in your binary. Usually this is done in the top-level " +"binary crate.\n" +"* `extern crate panic_halt as _` is necessary to ensure that the " +"`panic_halt` crate is linked in so\n" +" we get its panic handler.\n" +"* This example will build but not run, as it doesn't have an entry point." msgstr "" -#: src/unsafe/mutable-static-variables.md:3 -msgid "It is safe to read an immutable static variable:" +#: src/bare-metal/microcontrollers.md:1 +msgid "# Microcontrollers" msgstr "" -#: src/unsafe/mutable-static-variables.md:5 +#: src/bare-metal/microcontrollers.md:3 msgid "" -"```rust,editable\n" -"static HELLO_WORLD: &str = \"Hello, world!\";" +"The `cortex_m_rt` crate provides (among other things) a reset handler for " +"Cortex M microcontrollers." msgstr "" -#: src/unsafe/mutable-static-variables.md:8 +#: src/bare-metal/microcontrollers.md:5 msgid "" -"fn main() {\n" -" println!(\"name is: {}\", HELLO_WORLD);\n" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use cortex_m_rt::entry;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" loop {}\n" "}\n" "```" msgstr "" -#: src/unsafe/mutable-static-variables.md:13 +#: src/bare-metal/microcontrollers.md:21 msgid "" -"However, since data races can occur, it is unsafe to read and write mutable\n" -"static variables:" +"Next we'll look at how to access peripherals, with increasing levels of " +"abstraction." msgstr "" -#: src/unsafe/mutable-static-variables.md:16 +#: src/bare-metal/microcontrollers.md:25 msgid "" -"```rust,editable\n" -"static mut COUNTER: u32 = 0;" +"* The `cortex_m_rt::entry` macro requires that the function have type `fn() -" +"> !`, because returning\n" +" to the reset handler doesn't make sense.\n" +"* Run the example with `cargo embed --bin minimal`" msgstr "" -#: src/unsafe/mutable-static-variables.md:19 -msgid "" -"fn add_to_counter(inc: u32) {\n" -" unsafe { COUNTER += inc; } // Potential data race!\n" -"}" +#: src/bare-metal/microcontrollers/mmio.md:1 +msgid "# Raw MMIO" msgstr "" -#: src/unsafe/mutable-static-variables.md:23 +#: src/bare-metal/microcontrollers/mmio.md:3 msgid "" -"fn main() {\n" -" add_to_counter(42);" +"Most microcontrollers access peripherals via memory-mapped IO. Let's try " +"turning on an LED on our\n" +"micro:bit:" msgstr "" -#: src/unsafe/mutable-static-variables.md:26 +#: src/bare-metal/microcontrollers/mmio.md:6 msgid "" -" unsafe { println!(\"COUNTER: {}\", COUNTER); } // Potential data race!\n" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use core::mem::size_of;\n" +"use cortex_m_rt::entry;\n" +"\n" +"/// GPIO port 0 peripheral address\n" +"const GPIO_P0: usize = 0x5000_0000;\n" +"\n" +"// GPIO peripheral offsets\n" +"const PIN_CNF: usize = 0x700;\n" +"const OUTSET: usize = 0x508;\n" +"const OUTCLR: usize = 0x50c;\n" +"\n" +"// PIN_CNF fields\n" +"const DIR_OUTPUT: u32 = 0x1;\n" +"const INPUT_DISCONNECT: u32 = 0x1 << 1;\n" +"const PULL_DISABLED: u32 = 0x0 << 2;\n" +"const DRIVE_S0S1: u32 = 0x0 << 8;\n" +"const SENSE_DISABLED: u32 = 0x0 << 16;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let pin_cnf_21 = (GPIO_P0 + PIN_CNF + 21 * size_of::()) as *mut " +"u32;\n" +" let pin_cnf_28 = (GPIO_P0 + PIN_CNF + 28 * size_of::()) as *mut " +"u32;\n" +" // Safe because the pointers are to valid peripheral control registers, " +"and\n" +" // no aliases exist.\n" +" unsafe {\n" +" pin_cnf_21.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | " +"SENSE_DISABLED,\n" +" );\n" +" pin_cnf_28.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | " +"SENSE_DISABLED,\n" +" );\n" +" }\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" let gpio0_outset = (GPIO_P0 + OUTSET) as *mut u32;\n" +" let gpio0_outclr = (GPIO_P0 + OUTCLR) as *mut u32;\n" +" // Safe because the pointers are to valid peripheral control registers, " +"and\n" +" // no aliases exist.\n" +" unsafe {\n" +" gpio0_outclr.write_volatile(1 << 28);\n" +" gpio0_outset.write_volatile(1 << 21);\n" +" }\n" +"\n" +" loop {}\n" "}\n" "```" msgstr "" -#: src/unsafe/unsafe-functions.md:1 -msgid "# Calling Unsafe Functions" +#: src/bare-metal/microcontrollers/mmio.md:64 +msgid "" +"* GPIO 0 pin 21 is connected to the first column of the LED matrix, and pin " +"28 to the first row." +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:66 +#: src/bare-metal/microcontrollers/pacs.md:59 +#: src/bare-metal/microcontrollers/hals.md:43 +#: src/bare-metal/microcontrollers/board-support.md:34 +msgid "Run the example with:" msgstr "" -#: src/unsafe/unsafe-functions.md:3 +#: src/bare-metal/microcontrollers/mmio.md:68 msgid "" -"A function or method can be marked `unsafe` if it has extra preconditions " -"you\n" -"must uphold:" +"```sh\n" +"cargo embed --bin mmio\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:1 +msgid "# Peripheral Access Crates" msgstr "" -#: src/unsafe/unsafe-functions.md:6 +#: src/bare-metal/microcontrollers/pacs.md:3 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let emojis = \"🗻∈🌏\";\n" -" unsafe {\n" -" // Undefined behavior if indices do not lie on UTF-8 sequence " -"boundaries.\n" -" println!(\"{}\", emojis.get_unchecked(0..4));\n" -" println!(\"{}\", emojis.get_unchecked(4..7));\n" -" println!(\"{}\", emojis.get_unchecked(7..11));\n" -" }\n" +"[`svd2rust`](https://crates.io/crates/svd2rust) generates mostly-safe Rust " +"wrappers for\n" +"memory-mapped peripherals from [CMSIS-SVD](https://www.keil.com/pack/doc/" +"CMSIS/SVD/html/index.html)\n" +"files." +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_pac::Peripherals;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p.P0;\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" gpio0.pin_cnf[21].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +" gpio0.pin_cnf[28].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" gpio0.outclr.write(|w| w.pin28().clear());\n" +" gpio0.outset.write(|w| w.pin21().set());\n" +"\n" +" loop {}\n" "}\n" "```" msgstr "" -#: src/unsafe/extern-functions.md:1 -msgid "# Calling External Code" +#: src/bare-metal/microcontrollers/pacs.md:49 +msgid "" +"* SVD (System View Description) files are XML files typically provided by " +"silicon vendors which\n" +" describe the memory map of the device.\n" +" * They are organised by peripheral, register, field and value, with names, " +"descriptions, addresses\n" +" and so on.\n" +" * SVD files are often buggy and incomplete, so there are various projects " +"which patch the\n" +" mistakes, add missing details, and publish the generated crates.\n" +"* `cortex-m-rt` provides the vector table, among other things.\n" +"* If you `cargo install cargo-binutils` then you can run\n" +" `cargo objdump --bin pac -- -d --no-show-raw-insn` to see the resulting " +"binary." msgstr "" -#: src/unsafe/extern-functions.md:3 +#: src/bare-metal/microcontrollers/pacs.md:61 msgid "" -"Functions from other languages might violate the guarantees of Rust. " -"Calling\n" -"them is thus unsafe:" +"```sh\n" +"cargo embed --bin pac\n" +"```" msgstr "" -#: src/unsafe/extern-functions.md:6 +#: src/bare-metal/microcontrollers/hals.md:1 +msgid "# HAL crates" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:3 msgid "" -"```rust,editable\n" -"extern \"C\" {\n" -" fn abs(input: i32) -> i32;\n" -"}" +"[HAL crates](https://github.com/rust-embedded/awesome-embedded-rust#hal-" +"implementation-crates) for\n" +"many microcontrollers provide wrappers around various peripherals. These " +"generally implement traits\n" +"from [`embedded-hal`](https://crates.io/crates/embedded-hal)." msgstr "" -#: src/unsafe/extern-functions.md:11 +#: src/bare-metal/microcontrollers/hals.md:7 msgid "" -"fn main() {\n" -" unsafe {\n" -" // Undefined behavior if abs misbehaves.\n" -" println!(\"Absolute value of -3 according to C: {}\", abs(-3));\n" -" }\n" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_hal::gpio::{p0, Level};\n" +"use nrf52833_hal::pac::Peripherals;\n" +"use nrf52833_hal::prelude::*;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +"\n" +" // Create HAL wrapper for GPIO port 0.\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let mut col1 = gpio0.p0_28.into_push_pull_output(Level::High);\n" +" let mut row1 = gpio0.p0_21.into_push_pull_output(Level::Low);\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" col1.set_low().unwrap();\n" +" row1.set_high().unwrap();\n" +"\n" +" loop {}\n" "}\n" "```" msgstr "" -#: src/unsafe/unions.md:1 -msgid "# Unions" +#: src/bare-metal/microcontrollers/hals.md:39 +msgid "" +" * `set_low` and `set_high` are methods on the `embedded_hal` `OutputPin` " +"trait.\n" +" * HAL crates exist for many Cortex-M and RISC-V devices, including various " +"STM32, GD32, nRF, NXP,\n" +" MSP430, AVR and PIC microcontrollers." msgstr "" -#: src/unsafe/unions.md:3 -msgid "Unions are like enums, but you need to track the active field yourself:" +#: src/bare-metal/microcontrollers/hals.md:45 +msgid "" +"```sh\n" +"cargo embed --bin hal\n" +"```" msgstr "" -#: src/unsafe/unions.md:5 +#: src/bare-metal/microcontrollers/board-support.md:1 +msgid "# Board support crates" +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:3 msgid "" -"```rust,editable\n" -"#[repr(C)]\n" -"union MyUnion {\n" -" i: u8,\n" -" b: bool,\n" -"}" +"Board support crates provide a further level of wrapping for a specific " +"board for convenience." msgstr "" -#: src/unsafe/unions.md:12 +#: src/bare-metal/microcontrollers/board-support.md:5 msgid "" -"fn main() {\n" -" let u = MyUnion { i: 42 };\n" -" println!(\"int: {}\", unsafe { u.i });\n" -" println!(\"bool: {}\", unsafe { u.b }); // Undefined behavior!\n" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use microbit::hal::prelude::*;\n" +"use microbit::Board;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let mut board = Board::take().unwrap();\n" +"\n" +" board.display_pins.col1.set_low().unwrap();\n" +" board.display_pins.row1.set_high().unwrap();\n" +"\n" +" loop {}\n" "}\n" "```" msgstr "" -#: src/exercises/day-3/afternoon.md:1 -msgid "# Day 3: Afternoon Exercises" +#: src/bare-metal/microcontrollers/board-support.md:28 +msgid "" +" * In this case the board support crate is just providing more useful names, " +"and a bit of\n" +" initialisation.\n" +" * The crate may also include drivers for some on-board devices outside of " +"the microcontroller\n" +" itself.\n" +" * `microbit-v2` includes a simple driver for the LED matrix." msgstr "" -#: src/exercises/day-3/afternoon.md:3 -msgid "Let us build a safe wrapper for reading directory content!" +#: src/bare-metal/microcontrollers/board-support.md:36 +msgid "" +"```sh\n" +"cargo embed --bin board_support\n" +"```" msgstr "" -#: src/exercises/day-3/afternoon.md:7 -msgid "After looking at the exercise, you can look at the [solution] provided." +#: src/bare-metal/microcontrollers/type-state.md:1 +msgid "# The type state pattern" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:1 -msgid "# Safe FFI Wrapper" +#: src/bare-metal/microcontrollers/type-state.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" let pin: P0_01 = gpio0.p0_01;\n" +"\n" +" // let gpio0_01_again = gpio0.p0_01; // Error, moved.\n" +" let pin_input: P0_01> = pin.into_floating_input();\n" +" if pin_input.is_high().unwrap() {\n" +" // ...\n" +" }\n" +" let mut pin_output: P0_01> = pin_input\n" +" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, " +"Level::Low);\n" +" pin_output.set_high().unwrap();\n" +" // pin_input.is_high(); // Error, moved.\n" +"\n" +" let _pin2: P0_02> = gpio0\n" +" .p0_02\n" +" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, " +"Level::Low);\n" +" let _pin3: P0_03> = gpio0.p0_03." +"into_push_pull_output(Level::Low);\n" +"\n" +" loop {}\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:3 +#: src/bare-metal/microcontrollers/type-state.md:32 msgid "" -"Rust has great support for calling functions through a _foreign function\n" -"interface_ (FFI). We will use this to build a safe wrapper the `glibc` " -"functions\n" -"you would use from C to read the filenames of a directory." +" * Pins don't implement `Copy` or `Clone`, so only one instance of each can " +"exist. Once a pin is\n" +" moved out of the port struct nobody else can take it.\n" +" * Changing the configuration of a pin consumes the old pin instance, so you " +"can’t keep use the old\n" +" instance afterwards.\n" +" * The type of a value indicates the state that it is in: e.g. in this case, " +"the configuration state\n" +" of a GPIO pin. This encodes the state machine into the type system, and " +"ensures that you don't\n" +" try to use a pin in a certain way without properly configuring it first. " +"Illegal state\n" +" transitions are caught at compile time.\n" +" * You can call `is_high` on an input pin and `set_high` on an output pin, " +"but not vice-versa.\n" +" * Many HAL crates follow this pattern." msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:7 -msgid "You will want to consult the manual pages:" +#: src/bare-metal/microcontrollers/embedded-hal.md:1 +msgid "# `embedded-hal`" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:9 +#: src/bare-metal/microcontrollers/embedded-hal.md:3 msgid "" -"* [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)\n" -"* [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)\n" -"* [`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)" +"The [`embedded-hal`](https://crates.io/crates/embedded-hal) crate provides a " +"number of traits\n" +"covering common microcontroller peripherals." msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:13 +#: src/bare-metal/microcontrollers/embedded-hal.md:6 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." +" * GPIO\n" +" * ADC\n" +" * I2C, SPI, UART, CAN\n" +" * RNG\n" +" * Timers\n" +" * Watchdogs" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:17 +#: src/bare-metal/microcontrollers/embedded-hal.md:13 msgid "" -"[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" -"[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" -"[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" -"[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" +"Other crates then implement\n" +"[drivers](https://github.com/rust-embedded/awesome-embedded-rust#driver-" +"crates) in terms of these\n" +"traits, e.g. an accelerometer driver might need an I2C or SPI bus " +"implementation." msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:22 +#: src/bare-metal/microcontrollers/embedded-hal.md:19 msgid "" -"Copy the code below to and fill in the " -"missing\n" -"functions and methods:" +" * There are implementations for many microcontrollers, as well as other " +"platforms such as Linux on\n" +"Raspberry Pi.\n" +" * There is work in progress on an `async` version of `embedded-hal`, but it " +"isn't stable yet." msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:29 -msgid "" -"mod ffi {\n" -" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};" +#: src/bare-metal/microcontrollers/probe-rs.md:1 +msgid "# `probe-rs`, `cargo-embed`" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:32 -#: src/exercises/day-3/solutions-afternoon.md:26 +#: src/bare-metal/microcontrollers/probe-rs.md:3 msgid "" -" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" -" #[repr(C)]\n" -" pub struct DIR {\n" -" _data: [u8; 0],\n" -" _marker: core::marker::PhantomData<(*mut u8, core::marker::" -"PhantomPinned)>,\n" -" }" +"[probe-rs](https://probe.rs/) is a handy toolset for embedded debugging, " +"like OpenOCD but better\n" +"integrated." msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:39 -#: src/exercises/day-3/solutions-afternoon.md:33 +#: src/bare-metal/microcontrollers/probe-rs.md:6 msgid "" -" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-" -"gnu.\n" -" #[repr(C)]\n" -" pub struct dirent {\n" -" pub d_ino: c_long,\n" -" pub d_off: c_ulong,\n" -" pub d_reclen: c_ushort,\n" -" pub d_type: c_char,\n" -" pub d_name: [c_char; 256],\n" -" }" +"* SWD and JTAG via CMSIS-DAP, ST-" +"Link and J-Link probes\n" +"* GDB stub and Microsoft DAP " +"server\n" +"* Cargo integration" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:49 -#: src/exercises/day-3/solutions-afternoon.md:43 +#: src/bare-metal/microcontrollers/probe-rs.md:10 msgid "" -" extern \"C\" {\n" -" pub fn opendir(s: *const c_char) -> *mut DIR;\n" -" pub fn readdir(s: *mut DIR) -> *const dirent;\n" -" pub fn closedir(s: *mut DIR) -> c_int;\n" -" }\n" -"}" +"`cargo-embed` is a cargo subcommand to build and flash binaries, log\n" +"RTT output and connect GDB. It's " +"configured by an\n" +"`Embed.toml` file in your project directory." msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:56 -#: src/exercises/day-3/solutions-afternoon.md:50 +#: src/bare-metal/microcontrollers/probe-rs.md:16 msgid "" -"use std::ffi::{CStr, CString, OsStr, OsString};\n" -"use std::os::unix::ffi::OsStrExt;" +"* [CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) is " +"an Arm standard\n" +" protocol over USB for an in-circuit debugger to access the CoreSight Debug " +"Access Port of various\n" +" Arm Cortex processors. It's what the on-board debugger on the BBC micro:" +"bit uses.\n" +"* ST-Link is a range of in-circuit debuggers from ST Microelectronics, J-" +"Link is a range from\n" +" SEGGER.\n" +"* The Debug Access Port is usually either a 5-pin JTAG interface or 2-pin " +"Serial Wire Debug.\n" +"* probe-rs is a library which you can integrate into your own tools if you " +"want to.\n" +"* The [Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-" +"adapter-protocol/) lets\n" +" VSCode and other IDEs debug code running on any supported " +"microcontroller.\n" +"* cargo-embed is a binary built using the probe-rs library.\n" +"* RTT (Real Time Transfers) is a mechanism to transfer data between the " +"debug host and the target\n" +" through a number of ringbuffers." msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:59 -msgid "" -"#[derive(Debug)]\n" -"struct DirectoryIterator {\n" -" path: CString,\n" -" dir: *mut ffi::DIR,\n" -"}" +#: src/bare-metal/microcontrollers/debugging.md:1 +msgid "# Debugging" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:3 +msgid "Embed.toml:" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:65 +#: src/bare-metal/microcontrollers/debugging.md:5 msgid "" -"impl DirectoryIterator {\n" -" fn new(path: &str) -> Result {\n" -" // Call opendir and return a Ok value if that worked,\n" -" // otherwise return Err with a message.\n" -" unimplemented!()\n" -" }\n" -"}" +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:13 +msgid "In one terminal under `src/bare-metal/microcontrollers/examples/`:" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:73 +#: src/bare-metal/microcontrollers/debugging.md:15 msgid "" -"impl Iterator for DirectoryIterator {\n" -" type Item = OsString;\n" -" fn next(&mut self) -> Option {\n" -" // Keep calling readdir until we get a NULL pointer back.\n" -" unimplemented!()\n" -" }\n" -"}" +"```sh\n" +"cargo embed --bin board_support debug\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:19 +msgid "In another terminal in the same directory:" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:81 +#: src/bare-metal/microcontrollers/debugging.md:21 msgid "" -"impl Drop for DirectoryIterator {\n" -" fn drop(&mut self) {\n" -" // Call closedir as needed.\n" -" unimplemented!()\n" -" }\n" -"}" +"```sh\n" +"gdb-multiarch target/thumbv7em-none-eabihf/debug/board_support --eval-" +"command=\"target remote :1337\"\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:27 +msgid "In GDB, try running:" msgstr "" -#: src/exercises/day-3/safe-ffi-wrapper.md:88 +#: src/bare-metal/microcontrollers/debugging.md:29 msgid "" -"fn main() -> Result<(), String> {\n" -" let iter = DirectoryIterator::new(\".\")?;\n" -" println!(\"files: {:#?}\", iter.collect::>());\n" -" Ok(())\n" -"}\n" +"```gdb\n" +"b src/bin/board_support.rs:29\n" +"b src/bin/board_support.rs:30\n" +"b src/bin/board_support.rs:32\n" +"c\n" +"c\n" +"c\n" "```" msgstr "" -#: src/welcome-day-4.md:1 -msgid "# Welcome to Day 4" +#: src/bare-metal/microcontrollers/other-projects.md:1 +#: src/bare-metal/aps/other-projects.md:1 +msgid "# Other projects" msgstr "" -#: src/welcome-day-4.md:3 -msgid "Today we will look at two main topics:" +#: src/bare-metal/microcontrollers/other-projects.md:3 +msgid "" +" * [RTIC](https://rtic.rs/)\n" +" * \"Real-Time Interrupt-driven Concurrency\"\n" +" * Shared resource management, message passing, task scheduling, timer " +"queue\n" +" * [Embassy](https://embassy.dev/)\n" +" * `async` executors with priorities, timers, networking, USB\n" +" * [TockOS](https://www.tockos.org/documentation/getting-started)\n" +" * Security-focused RTOS with preemptive scheduling and Memory Protection " +"Unit support\n" +" * [Hubris](https://hubris.oxide.computer/)\n" +" * Microkernel RTOS from Oxide Computer Company with memory protection, " +"unprivileged drivers, IPC\n" +" * [Bindings for FreeRTOS](https://github.com/lobaro/FreeRTOS-rust)\n" +" * Some platforms have `std` implementations, e.g.\n" +" [esp-idf](https://esp-rs.github.io/book/overview/using-the-standard-" +"library.html)." msgstr "" -#: src/welcome-day-4.md:5 -msgid "* Concurrency: threads, channels, shared state, `Send` and `Sync`." +#: src/bare-metal/microcontrollers/other-projects.md:18 +msgid "" +" * RTIC can be considered either an RTOS or a concurrency framework.\n" +" * It doesn't include any HALs.\n" +" * It uses the Cortex-M NVIC (Nested Virtual Interrupt Controller) for " +"scheduling rather than a\n" +" proper kernel.\n" +" * Cortex-M only.\n" +" * Google uses TockOS on the Haven microcontroller for Titan security keys.\n" +" * FreeRTOS is mostly written in C, but there are Rust bindings for writing " +"applications." msgstr "" -#: src/welcome-day-4.md:7 +#: src/exercises/bare-metal/morning.md:3 msgid "" -"* Android: building binaries and libraries, using AIDL, logging, and\n" -" interoperability with C, C++, and Java." +"We will read the direction from an I2C compass, and log the readings to a " +"serial port." msgstr "" -#: src/welcome-day-4.md:10 +#: src/exercises/bare-metal/compass.md:1 +#, fuzzy +msgid "# Compass" +msgstr "Sammenligning" + +#: src/exercises/bare-metal/compass.md:3 msgid "" -"> We will attempt to call Rust from one of your own projects today. So try " -"to\n" -"> find a little corner of your code base where we can move some lines of " -"code to\n" -"> Rust. The fewer dependencies and \"exotic\" types the better. Something " -"that\n" -"> parses some raw bytes would be ideal." +"We will read the direction from an I2C compass, and log the readings to a " +"serial port. If you have\n" +"time, try displaying it on the LEDs somehow too, or use the buttons somehow." msgstr "" -#: src/concurrency.md:1 -msgid "# Fearless Concurrency" +#: src/exercises/bare-metal/compass.md:6 +msgid "Hints:" msgstr "" -#: src/concurrency.md:3 +#: src/exercises/bare-metal/compass.md:8 msgid "" -"Rust has full support for concurrency using OS threads with mutexes and\n" -"channels." +"- Check the documentation for the [`lsm303agr`](https://docs.rs/lsm303agr/" +"latest/lsm303agr/) and\n" +" [`microbit-v2`](https://docs.rs/microbit-v2/latest/microbit/) crates, as " +"well as the\n" +" [micro:bit hardware](https://tech.microbit.org/hardware/).\n" +"- The LSM303AGR Inertial Measurement Unit is connected to the internal I2C " +"bus.\n" +"- TWI is another name for I2C, so the I2C master peripheral is called TWIM.\n" +"- The LSM303AGR driver needs something implementing the `embedded_hal::" +"blocking::i2c::WriteRead`\n" +" trait. The\n" +" [`microbit::hal::Twim`](https://docs.rs/microbit-v2/latest/microbit/hal/" +"struct.Twim.html) struct\n" +" implements this.\n" +"- You have a [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/" +"struct.Board.html)\n" +" struct with fields for the various pins and peripherals.\n" +"- You can also look at the\n" +" [nRF52833 datasheet](https://infocenter.nordicsemi.com/pdf/" +"nRF52833_PS_v1.5.pdf) if you want, but\n" +" it shouldn't be necessary for this exercise." msgstr "" -#: src/concurrency.md:6 +#: src/exercises/bare-metal/compass.md:23 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." +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and " +"look in the `compass`\n" +"directory for the following files." msgstr "" -#: src/concurrency/threads.md:1 -msgid "# Threads" +#: src/exercises/bare-metal/compass.md:26 src/exercises/bare-metal/rtc.md:19 +#: src/exercises/concurrency/elevator.md:17 +msgid "`src/main.rs`:" msgstr "" -#: src/concurrency/threads.md:3 -msgid "Rust threads work similarly to threads in other languages:" +#: 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 +#: src/exercises/concurrency/elevator.md:19 +msgid "" msgstr "" -#: src/concurrency/threads.md:5 +#: src/exercises/bare-metal/compass.md:30 msgid "" -"```rust,editable\n" -"use std::thread;\n" -"use std::time::Duration;" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"use microbit::{hal::uarte::{Baudrate, Parity, Uarte}, Board};\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // TODO\n" +"\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // TODO\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/concurrency/threads.md:9 -msgid "" -"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" -" });" +#: src/exercises/bare-metal/compass.md:64 src/exercises/bare-metal/rtc.md:385 +#: src/exercises/concurrency/elevator.md:365 +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/elevator.md:367 +msgid "" msgstr "" -#: src/concurrency/threads.md:17 +#: src/exercises/bare-metal/compass.md:68 msgid "" -" for i in 1..5 {\n" -" println!(\"Main thread: {i}\");\n" -" thread::sleep(Duration::from_millis(5));\n" -" }\n" -"}\n" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"compass\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"cortex-m-rt = \"0.7.3\"\n" +"embedded-hal = \"0.2.6\"\n" +"lsm303agr = \"0.2.2\"\n" +"microbit-v2 = \"0.13.0\"\n" +"panic-halt = \"0.2.0\"\n" "```" msgstr "" -#: src/concurrency/threads.md:24 -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`." +#: src/exercises/bare-metal/compass.md:85 +msgid "`Embed.toml` (you shouldn't need to change this):" msgstr "" -#: src/concurrency/threads.md:32 -msgid "" -"* Notice that the thread is stopped before it reaches 10 — the main thread " -"is\n" -" not waiting." +#: src/exercises/bare-metal/compass.md:87 +msgid "" msgstr "" -#: src/concurrency/threads.md:35 +#: src/exercises/bare-metal/compass.md:89 msgid "" -"* Use `let handle = thread::spawn(...)` and later `handle.join()` to wait " -"for\n" -" the thread to finish." +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"\n" +"[debug.reset]\n" +"halt_afterwards = true\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:100 src/exercises/bare-metal/rtc.md:985 +msgid "`.cargo/config.toml` (you shouldn't need to change this):" msgstr "" -#: src/concurrency/threads.md:38 -msgid "* Trigger a panic in the thread, notice how this doesn't affect `main`." +#: src/exercises/bare-metal/compass.md:102 src/exercises/bare-metal/rtc.md:987 +msgid "" msgstr "" -#: src/concurrency/threads.md:40 +#: src/exercises/bare-metal/compass.md:104 msgid "" -"* 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`]." +"```toml\n" +"[build]\n" +"target = \"thumbv7em-none-eabihf\" # Cortex-M4F\n" +"\n" +"[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))']\n" +"rustflags = [\"-C\", \"link-arg=-Tlink.x\"]\n" +"```" msgstr "" -#: src/concurrency/threads.md:43 -msgid "[`Any`]: https://doc.rust-lang.org/std/any/index.html" +#: src/exercises/bare-metal/compass.md:112 +msgid "See the serial output on Linux with:" msgstr "" -#: src/concurrency/scoped-threads.md:1 -msgid "# Scoped Threads" +#: src/exercises/bare-metal/compass.md:114 +msgid "" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/ttyACM0\n" +"```" msgstr "" -#: src/concurrency/scoped-threads.md:3 -msgid "Normal threads cannot borrow from their environment:" +#: src/exercises/bare-metal/compass.md:118 +msgid "" +"Or on Mac OS something like (the device name may be slightly different):" msgstr "" -#: src/concurrency/scoped-threads.md:5 +#: src/exercises/bare-metal/compass.md:120 msgid "" -"```rust,editable,compile_fail\n" -"use std::thread;" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:124 +msgid "Use Ctrl+A Ctrl+Q to quit picocom." msgstr "" -#: src/concurrency/scoped-threads.md:8 src/concurrency/scoped-threads.md:22 +#: src/bare-metal/aps.md:1 +msgid "# Application processors" +msgstr "" + +#: src/bare-metal/aps.md:3 msgid "" -"fn main() {\n" -" let s = String::from(\"Hello\");" +"So far we've talked about microcontrollers, such as the Arm Cortex-M series. " +"Now let's try writing\n" +"something for Cortex-A. For simplicity we'll just work with QEMU's aarch64\n" +"['virt'](https://qemu-project.gitlab.io/qemu/system/arm/virt.html) board." msgstr "" -#: src/concurrency/scoped-threads.md:11 +#: src/bare-metal/aps.md:9 msgid "" -" thread::spawn(|| {\n" -" println!(\"Length: {}\", s.len());\n" -" });\n" -"}\n" -"```" +"* Broadly speaking, microcontrollers don't have an MMU or multiple levels of " +"privilege (exception\n" +" levels on Arm CPUs, rings on x86), while application processors do.\n" +"* QEMU supports emulating various different machines or board models for " +"each architecture. The\n" +" 'virt' board doesn't correspond to any particular real hardware, but is " +"designed purely for\n" +" virtual machines." msgstr "" -#: src/concurrency/scoped-threads.md:17 -msgid "However, you can use a [scoped thread][1] for this:" +#: src/bare-metal/aps/inline-assembly.md:1 +msgid "# Inline assembly" msgstr "" -#: src/concurrency/scoped-threads.md:19 +#: src/bare-metal/aps/inline-assembly.md:3 msgid "" -"```rust,editable\n" -"use std::thread;" +"Sometimes we need to use assembly to do things that aren't possible with " +"Rust code. For example,\n" +"to make an HVC to tell the firmware " +"to power off the system:" msgstr "" -#: src/concurrency/scoped-threads.md:25 +#: src/bare-metal/aps/inline-assembly.md:6 msgid "" -" thread::scope(|scope| {\n" -" scope.spawn(|| {\n" -" println!(\"Length: {}\", s.len());\n" -" });\n" -" });\n" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::arch::asm;\n" +"use core::panic::PanicInfo;\n" +"\n" +"mod exceptions;\n" +"\n" +"const PSCI_SYSTEM_OFF: u32 = 0x84000008;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) {\n" +" // Safe because this only uses the declared registers and doesn't do\n" +" // anything with memory.\n" +" unsafe {\n" +" asm!(\"hvc #0\",\n" +" inout(\"w0\") PSCI_SYSTEM_OFF => _,\n" +" inout(\"w1\") 0 => _,\n" +" inout(\"w2\") 0 => _,\n" +" inout(\"w3\") 0 => _,\n" +" inout(\"w4\") 0 => _,\n" +" inout(\"w5\") 0 => _,\n" +" inout(\"w6\") 0 => _,\n" +" inout(\"w7\") 0 => _,\n" +" options(nomem, nostack)\n" +" );\n" +" }\n" +"\n" +" loop {}\n" "}\n" "```" msgstr "" -#: src/concurrency/scoped-threads.md:33 -msgid "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html" +#: src/bare-metal/aps/inline-assembly.md:39 +msgid "" +"(If you actually want to do this, use the [`smccc`][1] crate which has " +"wrappers for all these functions.)" msgstr "" -#: src/concurrency/channels.md:1 -msgid "# Channels" +#: src/bare-metal/aps/inline-assembly.md:43 +msgid "" +"* PSCI is the Arm Power State Coordination Interface, a standard set of " +"functions to manage system\n" +" and CPU power states, among other things. It is implemented by EL3 " +"firmware and hypervisors on\n" +" many systems.\n" +"* The `0 => _` syntax means initialise the register to 0 before running the " +"inline assembly code,\n" +" and ignore its contents afterwards. We need to use `inout` rather than " +"`in` because the call could\n" +" potentially clobber the contents of the registers.\n" +"* This `main` function needs to be `#[no_mangle]` and `extern \"C\"` because " +"it is called from our\n" +" entry point in `entry.S`.\n" +"* `_x0`–`_x3` are the values of registers `x0`–`x3`, which are " +"conventionally used by the bootloader\n" +" to pass things like a pointer to the device tree. According to the " +"standard aarch64 calling\n" +" convention (which is what `extern \"C\"` specifies to use), registers `x0`–" +"`x7` are used for the\n" +" first 8 arguments passed to a function, so `entry.S` doesn't need to do " +"anything special except\n" +" make sure it doesn't change these registers.\n" +"* Run the example in QEMU with `make qemu_psci` under `src/bare-metal/aps/" +"examples`." msgstr "" -#: src/concurrency/channels.md:3 -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." +#: src/bare-metal/aps/mmio.md:1 +msgid "# Volatile memory access for MMIO" msgstr "" -#: src/concurrency/channels.md:6 +#: src/bare-metal/aps/mmio.md:3 msgid "" -"```rust,editable\n" -"use std::sync::mpsc;\n" -"use std::thread;" +" * Use `pointer::read_volatile` and `pointer::write_volatile`.\n" +" * Never hold a reference.\n" +" * `addr_of!` lets you get fields of structs without creating an " +"intermediate reference." msgstr "" -#: src/concurrency/channels.md:10 src/concurrency/channels/unbounded.md:10 +#: src/bare-metal/aps/mmio.md:9 msgid "" -"fn main() {\n" -" let (tx, rx) = mpsc::channel();" +" * Volatile access: read or write operations may have side-effects, so " +"prevent the compiler or\n" +" hardware from reordering, duplicating or eliding them.\n" +" * Usually if you write and then read, e.g. via a mutable reference, the " +"compiler may assume that\n" +" the value read is the same as the value just written, and not bother " +"actually reading memory.\n" +" * Some existing crates for volatile access to hardware do hold references, " +"but this is unsound.\n" +" Whenever a reference exist, the compiler may choose to dereference it.\n" +" * Use the `addr_of!` macro to get struct field pointers from a pointer to " +"the struct." msgstr "" -#: src/concurrency/channels.md:13 -msgid "" -" tx.send(10).unwrap();\n" -" tx.send(20).unwrap();" +#: src/bare-metal/aps/uart.md:1 +msgid "# Let's write a UART driver" msgstr "" -#: src/concurrency/channels.md:16 +#: src/bare-metal/aps/uart.md:3 msgid "" -" println!(\"Received: {:?}\", rx.recv());\n" -" println!(\"Received: {:?}\", rx.recv());" +"The QEMU 'virt' machine has a [PL011][1] UART, so let's write a driver for " +"that." msgstr "" -#: src/concurrency/channels.md:19 +#: src/bare-metal/aps/uart.md:5 msgid "" -" let tx2 = tx.clone();\n" -" tx2.send(30).unwrap();\n" -" println!(\"Received: {:?}\", rx.recv());\n" +"```rust,editable\n" +"const FLAG_REGISTER_OFFSET: usize = 0x18;\n" +"const FR_BUSY: u8 = 1 << 3;\n" +"const FR_TXFF: u8 = 1 << 5;\n" +"\n" +"/// Minimal driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" base_address: *mut u8,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at " +"the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of " +"a\n" +" /// PL011 device, which must be mapped into the address space of the " +"process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u8) -> Self {\n" +" Self { base_address }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register() & FR_TXFF != 0 {}\n" +"\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" self.base_address.write_volatile(byte);\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register() & FR_BUSY != 0 {}\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> u8 {\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { self.base_address.add(FLAG_REGISTER_OFFSET)." +"read_volatile() }\n" +" }\n" "}\n" "```" msgstr "" -#: src/concurrency/channels/unbounded.md:1 -msgid "# Unbounded Channels" +#: src/bare-metal/aps/uart.md:55 +msgid "" +"* Note that `Uart::new` is unsafe while the other methods are safe. This is " +"because as long as the\n" +" caller of `Uart::new` guarantees that its safety requirements are met (i." +"e. that there is only\n" +" ever one instance of the driver for a given UART, and nothing else " +"aliasing its address space),\n" +" then it is always safe to call `write_byte` later because we can assume " +"the necessary\n" +" preconditions.\n" +"* We could have done it the other way around (making `new` safe but " +"`write_byte` unsafe), but that\n" +" would be much less convenient to use as every place that calls " +"`write_byte` would need to reason\n" +" about the safety\n" +"* This is a common pattern for writing safe wrappers of unsafe code: moving " +"the burden of proof for\n" +" soundness from a large number of places to a smaller number of places." msgstr "" -#: src/concurrency/channels/unbounded.md:3 -msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" +#: src/bare-metal/aps/uart.md:66 +msgid "" msgstr "" -#: src/concurrency/channels/unbounded.md:5 -#: src/concurrency/channels/bounded.md:5 -msgid "" -"```rust,editable\n" -"use std::sync::mpsc;\n" -"use std::thread;\n" -"use std::time::Duration;" +#: src/bare-metal/aps/uart/traits.md:1 +msgid "# More traits" msgstr "" -#: src/concurrency/channels/unbounded.md:13 -#: src/concurrency/channels/bounded.md:13 +#: src/bare-metal/aps/uart/traits.md:3 msgid "" -" 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));" +"We derived the `Debug` trait. It would be useful to implement a few more " +"traits too." msgstr "" -#: src/concurrency/channels/unbounded.md:23 -#: src/concurrency/channels/bounded.md:23 +#: src/bare-metal/aps/uart/traits.md:5 msgid "" -" for msg in rx.iter() {\n" -" println!(\"Main: got {}\", msg);\n" +"```rust,editable,compile_fail\n" +"use core::fmt::{self, Write};\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" " }\n" "}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" "```" msgstr "" -#: src/concurrency/channels/bounded.md:1 -msgid "# Bounded Channels" +#: src/bare-metal/aps/uart/traits.md:24 +msgid "" +"* Implementing `Write` lets us use the `write!` and `writeln!` macros with " +"our `Uart` type.\n" +"* Run the example in QEMU with `make qemu_minimal` under `src/bare-metal/aps/" +"examples`." msgstr "" -#: src/concurrency/channels/bounded.md:3 -msgid "Bounded and synchronous channels make `send` block the current thread:" +#: src/bare-metal/aps/better-uart.md:1 +msgid "# A better UART driver" msgstr "" -#: src/concurrency/channels/bounded.md:10 +#: src/bare-metal/aps/better-uart.md:3 msgid "" -"fn main() {\n" -" let (tx, rx) = mpsc::sync_channel(3);" +"The PL011 actually has [a bunch more registers][1], and adding offsets to " +"construct pointers to access\n" +"them is error-prone and hard to read. Plus, some of them are bit fields " +"which would be nice to\n" +"access in a structured way." msgstr "" -#: src/concurrency/shared_state.md:1 -msgid "# Shared State" +#: src/bare-metal/aps/better-uart.md:7 +msgid "" +"| Offset | Register name | Width |\n" +"| ------ | ------------- | ----- |\n" +"| 0x00 | DR | 12 |\n" +"| 0x04 | RSR | 4 |\n" +"| 0x18 | FR | 9 |\n" +"| 0x20 | ILPR | 8 |\n" +"| 0x24 | IBRD | 16 |\n" +"| 0x28 | FBRD | 6 |\n" +"| 0x2c | LCR_H | 8 |\n" +"| 0x30 | CR | 16 |\n" +"| 0x34 | IFLS | 6 |\n" +"| 0x38 | IMSC | 11 |\n" +"| 0x3c | RIS | 11 |\n" +"| 0x40 | MIS | 11 |\n" +"| 0x44 | ICR | 11 |\n" +"| 0x48 | DMACR | 3 |" msgstr "" -#: src/concurrency/shared_state.md:3 +#: src/bare-metal/aps/better-uart.md:26 +msgid "- There are also some ID registers which have been omitted for brevity." +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:1 +msgid "# Bitflags" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:3 msgid "" -"Rust uses the type system to enforce synchronization of shared data. This " -"is\n" -"primarily done via two types:" +"The [`bitflags`](https://crates.io/crates/bitflags) crate is useful for " +"working with bitflags." msgstr "" -#: src/concurrency/shared_state.md:6 +#: src/bare-metal/aps/better-uart/bitflags.md:5 msgid "" -"* [`Arc`][1], atomic reference counted `T`: handled sharing between " -"threads and\n" -" takes care to deallocate `T` when the last thread exits,\n" -"* [`Mutex`][2]: ensures mutual exclusion access to the `T` value." +"```rust,editable,compile_fail\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"```" msgstr "" -#: src/concurrency/shared_state.md:10 +#: src/bare-metal/aps/better-uart/bitflags.md:37 msgid "" -"[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" -"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" +"* The `bitflags!` macro creates a newtype something like `Flags(u16)`, along " +"with a bunch of method\n" +" implementations to get and set flags." msgstr "" -#: src/concurrency/shared_state/arc.md:1 -msgid "# `Arc`" +#: src/bare-metal/aps/better-uart/registers.md:1 +msgid "# Multiple registers" msgstr "" -#: src/concurrency/shared_state/arc.md:3 -msgid "[`Arc`][1] allows shared read-only access via its `clone` method:" +#: src/bare-metal/aps/better-uart/registers.md:3 +msgid "" +"We can use a struct to represent the memory layout of the UART's registers." msgstr "" -#: src/concurrency/shared_state/arc.md:5 +#: src/bare-metal/aps/better-uart/registers.md:5 msgid "" -"```rust,editable\n" -"use std::thread;\n" -"use std::sync::Arc;" +"```rust,editable,compile_fail\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"```" msgstr "" -#: src/concurrency/shared_state/arc.md:9 +#: src/bare-metal/aps/better-uart/registers.md:41 msgid "" -"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" -" }" +"* [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-" +"representation) tells\n" +" the compiler to lay the struct fields out in order, following the same " +"rules as C. This is\n" +" necessary for our struct to have a predictable layout, as default Rust " +"representation allows the\n" +" compiler to (among other things) reorder fields however it sees fit." +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:1 +msgid "# Driver" msgstr "" -#: src/concurrency/shared_state/arc.md:20 +#: src/bare-metal/aps/better-uart/driver.md:3 +msgid "Now let's use the new `Registers` struct in our driver." +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:5 msgid "" -" handles.into_iter().for_each(|h| h.join().unwrap());\n" -" println!(\"v: {v:?}\");\n" +"```rust,editable,compile_fail\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at " +"the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of " +"a\n" +" /// PL011 device, which must be mapped into the address space of the " +"process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been " +"received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr)." +"read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" "}\n" "```" msgstr "" -#: src/concurrency/shared_state/arc.md:25 -msgid "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" +#: src/bare-metal/aps/better-uart/driver.md:64 +msgid "" +"* Note the use of `addr_of!` / `addr_of_mut!` to get pointers to individual " +"fields without creating\n" +" an intermediate reference, which would be unsound." +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:1 +#: src/bare-metal/aps/logging/using.md:1 +msgid "# Using it" msgstr "" -#: src/concurrency/shared_state/mutex.md:1 -msgid "# `Mutex`" +#: src/bare-metal/aps/better-uart/using.md:3 +msgid "" +"Let's write a small program using our driver to write to the serial console, " +"and echo incoming\n" +"bytes." msgstr "" -#: src/concurrency/shared_state/mutex.md:3 +#: src/bare-metal/aps/better-uart/using.md:6 msgid "" -"[`Mutex`][1] ensures mutual exclusion _and_ allows mutable access to `T`\n" -"behind a read-only interface:" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use core::panic::PanicInfo;\n" +"use log::error;\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" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +"\n" +" writeln!(uart, \"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\").unwrap();\n" +"\n" +" loop {\n" +" if let Some(b) = uart.read_byte() {\n" +" uart.write_byte(b);\n" +" match b {\n" +" b'\\r' => {\n" +" uart.write_byte(b'\\n');\n" +" }\n" +" b'q' => break,\n" +" _ => {}\n" +" }\n" +" }\n" +" }\n" +"\n" +" writeln!(uart, \"Bye!\").unwrap();\n" +" system_off::().unwrap();\n" +"}\n" +"```" msgstr "" -#: src/concurrency/shared_state/mutex.md:6 +#: src/bare-metal/aps/better-uart/using.md:51 msgid "" -"```rust,editable\n" -"use std::sync::Mutex;" +"* As in the [inline assembly](../inline-assembly.md) example, this `main` " +"function is called from our\n" +" entry point code in `entry.S`. See the speaker notes there for details.\n" +"* Run the example in QEMU with `make qemu` under `src/bare-metal/aps/" +"examples`." +msgstr "" + +#: src/bare-metal/aps/logging.md:3 +msgid "" +"It would be nice to be able to use the logging macros from the [`log`][1] " +"crate. We can do this by\n" +"implementing the `Log` trait." +msgstr "" + +#: src/bare-metal/aps/logging.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" +" }\n" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), " +"SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" msgstr "" -#: src/concurrency/shared_state/mutex.md:9 +#: src/bare-metal/aps/logging.md:50 msgid "" -"fn main() {\n" -" let v: Mutex> = Mutex::new(vec![10, 20, 30]);\n" -" println!(\"v: {:?}\", v.lock().unwrap());" +"* The unwrap in `log` is safe because we initialise `LOGGER` before calling " +"`set_logger`." msgstr "" -#: src/concurrency/shared_state/mutex.md:13 -msgid "" -" {\n" -" let v: &Mutex> = &v;\n" -" let mut guard = v.lock().unwrap();\n" -" guard.push(40);\n" -" }" +#: src/bare-metal/aps/logging/using.md:3 +msgid "We need to initialise the logger before we use it." msgstr "" -#: src/concurrency/shared_state/mutex.md:19 +#: src/bare-metal/aps/logging/using.md:5 msgid "" -" println!(\"v: {:?}\", v.lock().unwrap());\n" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, LevelFilter};\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" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\");\n" +"\n" +" assert_eq!(x1, 42);\n" +"\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off::().unwrap();\n" +" loop {}\n" "}\n" "```" msgstr "" -#: src/concurrency/shared_state/mutex.md:23 +#: src/bare-metal/aps/logging/using.md:46 msgid "" -"Notice how we have a [`impl Sync for Mutex`][2] blanket\n" -"implementation." +"* 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`." msgstr "" -#: src/concurrency/shared_state/mutex.md:26 +#: src/bare-metal/aps/other-projects.md:3 msgid "" -"[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" -"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-" -"Mutex%3CT%3E\n" -"[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" +" * [oreboot](https://github.com/oreboot/oreboot)\n" +" * \"coreboot without the C\"\n" +" * Supports x86, aarch64 and RISC-V.\n" +" * Relies on LinuxBoot rather than having many drivers itself.\n" +" * [Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-" +"raspberrypi-OS-tutorials)\n" +" * Initialisation, UART driver, simple bootloader, JTAG, exception levels, " +"exception handling, page tables\n" +" * Not all very well written, so beware.\n" +" * [`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)\n" +" * Static analysis to determine maximum stack usage." msgstr "" -#: src/concurrency/shared_state/example.md:3 -msgid "Let us see `Arc` and `Mutex` in action:" +#: src/bare-metal/useful-crates.md:1 +msgid "# Useful crates" msgstr "" -#: src/concurrency/shared_state/example.md:5 +#: src/bare-metal/useful-crates.md:3 msgid "" -"```rust,editable,compile_fail\n" -"use std::thread;\n" -"// use std::sync::{Arc, Mutex};" +"We'll go over a few crates which solve some common problems in bare-metal " +"programming." +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:1 +msgid "# `zerocopy`" msgstr "" -#: src/concurrency/shared_state/example.md:9 +#: src/bare-metal/useful-crates/zerocopy.md:3 msgid "" -"fn main() {\n" -" let mut v = vec![10, 20, 30];\n" -" let handle = thread::spawn(|| {\n" -" v.push(10);\n" -" });\n" -" v.push(1000);" +"The [`zerocopy`][1] crate (from Fuchsia) provides traits and macros for " +"safely converting between\n" +"byte sequences and other types." msgstr "" -#: src/concurrency/shared_state/example.md:16 +#: src/bare-metal/useful-crates/zerocopy.md:6 msgid "" -" handle.join().unwrap();\n" -" println!(\"v: {v:?}\");\n" +"```rust,editable,compile_fail\n" +"use zerocopy::AsBytes;\n" +"\n" +"#[repr(u32)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"enum RequestType {\n" +" #[default]\n" +" In = 0,\n" +" Out = 1,\n" +" Flush = 4,\n" +"}\n" +"\n" +"#[repr(C)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"struct VirtioBlockRequest {\n" +" request_type: RequestType,\n" +" reserved: u32,\n" +" sector: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let request = VirtioBlockRequest {\n" +" request_type: RequestType::Flush,\n" +" sector: 42,\n" +" ..Default::default()\n" +" };\n" +"\n" +" assert_eq!(\n" +" request.as_bytes(),\n" +" &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0]\n" +" );\n" "}\n" "```" msgstr "" -#: src/concurrency/send-sync.md:1 -msgid "# `Send` and `Sync`" -msgstr "" - -#: src/concurrency/send-sync.md:3 +#: src/bare-metal/useful-crates/zerocopy.md:40 msgid "" -"How does Rust know to forbid shared access across thread? The answer is in " -"two traits:" +"This is not suitable for MMIO (as it doesn't use volatile reads and writes), " +"but can be useful for\n" +"working with structures shared with hardware e.g. by DMA, or sent over some " +"external interface." msgstr "" -#: src/concurrency/send-sync.md:5 +#: src/bare-metal/useful-crates/zerocopy.md:45 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." +"* `FromBytes` can be implemented for types for which any byte pattern is " +"valid, and so can safely be\n" +" converted from an untrusted sequence of bytes.\n" +"* Attempting to derive `FromBytes` for these types would fail, because " +"`RequestType` doesn't use all\n" +" possible u32 values as discriminants, so not all byte patterns are valid.\n" +"* `zerocopy::byteorder` has types for byte-order aware numeric primitives.\n" +"* Run the example with `cargo run` under `src/bare-metal/useful-crates/" +"zerocopy-example/`. (It won't\n" +" run in the Playground because of the crate dependency.)" msgstr "" -#: src/concurrency/send-sync.md:10 -msgid "" -"[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" -"[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html" +#: src/bare-metal/useful-crates/aarch64-paging.md:1 +msgid "# `aarch64-paging`" msgstr "" -#: src/concurrency/send-sync/send.md:1 -msgid "# `Send`" +#: src/bare-metal/useful-crates/aarch64-paging.md:3 +msgid "" +"The [`aarch64-paging`][1] crate lets you create page tables according to the " +"AArch64 Virtual Memory\n" +"System Architecture." msgstr "" -#: src/concurrency/send-sync/send.md:3 +#: src/bare-metal/useful-crates/aarch64-paging.md:6 msgid "" -"> A type `T` is [`Send`][1] if it is safe to move a `T` value to another " -"thread." +"```rust,editable,compile_fail\n" +"use aarch64_paging::{\n" +" idmap::IdMap,\n" +" paging::{Attributes, MemoryRegion},\n" +"};\n" +"\n" +"const ASID: usize = 1;\n" +"const ROOT_LEVEL: usize = 1;\n" +"\n" +"// Create a new page table with identity mapping.\n" +"let mut idmap = IdMap::new(ASID, ROOT_LEVEL);\n" +"// Map a 2 MiB region of memory as read-only.\n" +"idmap.map_range(\n" +" &MemoryRegion::new(0x80200000, 0x80400000),\n" +" Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,\n" +").unwrap();\n" +"// Set `TTBR0_EL1` to activate the page table.\n" +"idmap.activate();\n" +"```" msgstr "" -#: src/concurrency/send-sync/send.md:5 +#: src/bare-metal/useful-crates/aarch64-paging.md:28 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." +"* For now it only supports EL1, but support for other exception levels " +"should be straightforward to\n" +" add.\n" +"* This is used in Android for the [Protected VM Firmware][2].\n" +"* There's no easy way to run this example, as it needs to run on real " +"hardware or under QEMU." msgstr "" -#: src/concurrency/send-sync/send.md:9 -msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" +#: src/bare-metal/useful-crates/buddy_system_allocator.md:1 +msgid "# `buddy_system_allocator`" msgstr "" -#: src/concurrency/send-sync/sync.md:1 -msgid "# `Sync`" +#: src/bare-metal/useful-crates/buddy_system_allocator.md:3 +msgid "" +"[`buddy_system_allocator`][1] is a third-party crate implementing a basic " +"buddy system allocator.\n" +"It can be used both for [`LockedHeap`][2] implementing [`GlobalAlloc`][3] so " +"you can use the\n" +"standard `alloc` crate (as we saw [before][4]), or for allocating other " +"address space. For example,\n" +"we might want to allocate MMIO space for PCI BARs:" msgstr "" -#: src/concurrency/send-sync/sync.md:3 +#: src/bare-metal/useful-crates/buddy_system_allocator.md:8 msgid "" -"> A type `T` is [`Sync`][1] if it is safe to access a `T` value from " -"multiple\n" -"> threads at the same time." +"```rust,editable,compile_fail\n" +"use buddy_system_allocator::FrameAllocator;\n" +"use core::alloc::Layout;\n" +"\n" +"fn main() {\n" +" let mut allocator = FrameAllocator::<32>::new();\n" +" allocator.add_frame(0x200_0000, 0x400_0000);\n" +"\n" +" let layout = Layout::from_size_align(0x100, 0x100).unwrap();\n" +" let bar = allocator\n" +" .alloc_aligned(layout)\n" +" .expect(\"Failed to allocate 0x100 byte MMIO region\");\n" +" println!(\"Allocated 0x100 byte MMIO region at {:#x}\", bar);\n" +"}\n" +"```" msgstr "" -#: src/concurrency/send-sync/sync.md:6 -msgid "More precisely, the definition is:" +#: src/bare-metal/useful-crates/buddy_system_allocator.md:26 +msgid "" +"* PCI BARs always have alignment equal to their size.\n" +"* Run the example with `cargo run` under `src/bare-metal/useful-crates/" +"allocator-example/`. (It won't\n" +" run in the Playground because of the crate dependency.)" msgstr "" -#: src/concurrency/send-sync/sync.md:8 -msgid "> `T` is `Sync` if and only if `&T` is `Send`" +#: src/bare-metal/useful-crates/tinyvec.md:1 +msgid "# `tinyvec`" msgstr "" -#: src/concurrency/send-sync/sync.md:10 -msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Sync.html" +#: src/bare-metal/useful-crates/tinyvec.md:3 +msgid "" +"Sometimes you want something which can be resized like a `Vec`, but without " +"heap allocation.\n" +"[`tinyvec`][1] provides this: a vector backed by an array or slice, which " +"could be statically\n" +"allocated or on the stack, which keeps track of how many elements are used " +"and panics if you try to\n" +"use more than are allocated." msgstr "" -#: src/concurrency/send-sync/examples.md:1 -msgid "# Examples" +#: src/bare-metal/useful-crates/tinyvec.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use tinyvec::{array_vec, ArrayVec};\n" +"\n" +"fn main() {\n" +" let mut numbers: ArrayVec<[u32; 5]> = array_vec!(42, 66);\n" +" println!(\"{numbers:?}\");\n" +" numbers.push(7);\n" +" println!(\"{numbers:?}\");\n" +" numbers.remove(1);\n" +" println!(\"{numbers:?}\");\n" +"}\n" +"```" msgstr "" -#: src/concurrency/send-sync/examples.md:3 -msgid "## `Send + Sync`" +#: src/bare-metal/useful-crates/tinyvec.md:23 +msgid "" +"* `tinyvec` requires that the element type implement `Default` for " +"initialisation.\n" +"* The Rust Playground includes `tinyvec`, so this example will run fine " +"inline." msgstr "" -#: src/concurrency/send-sync/examples.md:5 -msgid "Most types you come across are `Send + Sync`:" +#: src/bare-metal/useful-crates/spin.md:1 +msgid "# `spin`" msgstr "" -#: src/concurrency/send-sync/examples.md:7 +#: src/bare-metal/useful-crates/spin.md:3 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." +"`std::sync::Mutex` and the other synchronisation primitives from `std::sync` " +"are not available in\n" +"`core` or `alloc`. How can we manage synchronisation or interior mutability, " +"such as for sharing\n" +"state between different CPUs?" msgstr "" -#: src/concurrency/send-sync/examples.md:14 +#: src/bare-metal/useful-crates/spin.md:7 msgid "" -"The generic types are typically `Send + Sync` when the type parameters are\n" -"`Send + Sync`." -msgstr "" - -#: src/concurrency/send-sync/examples.md:17 -msgid "## `Send + !Sync`" +"The [`spin`][1] crate provides spinlock-based equivalents of many of these " +"primitives." msgstr "" -#: src/concurrency/send-sync/examples.md:19 +#: src/bare-metal/useful-crates/spin.md:9 msgid "" -"These types can be moved to other threads, but they're not thread-safe.\n" -"Typically because of interior mutability:" +"```rust,editable,compile_fail\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static counter: SpinMutex = SpinMutex::new(0);\n" +"\n" +"fn main() {\n" +" println!(\"count: {}\", counter.lock());\n" +" *counter.lock() += 2;\n" +" println!(\"count: {}\", counter.lock());\n" +"}\n" +"```" msgstr "" -#: src/concurrency/send-sync/examples.md:22 +#: src/bare-metal/useful-crates/spin.md:23 msgid "" -"* `mpsc::Sender`\n" -"* `mpsc::Receiver`\n" -"* `Cell`\n" -"* `RefCell`" +"* Be careful to avoid deadlock if you take locks in interrupt handlers.\n" +"* `spin` also has a ticket lock mutex implementation; equivalents of " +"`RwLock`, `Barrier` and `Once`\n" +" from `std::sync`; and `Lazy` for lazy initialisation.\n" +"* The [`once_cell`][2] crate also has some useful types for late " +"initialisation with a slightly\n" +" different approach to `spin::once::Once`.\n" +"* The Rust Playground includes `spin`, so this example will run fine inline." msgstr "" -#: src/concurrency/send-sync/examples.md:27 -msgid "## `!Send + Sync`" +#: src/bare-metal/android.md:1 +msgid "# Android" msgstr "" -#: src/concurrency/send-sync/examples.md:29 +#: src/bare-metal/android.md:3 msgid "" -"These types are thread-safe, but they cannot be moved to another thread:" +"To build a bare-metal Rust binary in AOSP, you need to use a " +"`rust_ffi_static` Soong rule to build\n" +"your Rust code, then a `cc_binary` with a linker script to produce the " +"binary itself, and then a\n" +"`raw_binary` to convert the ELF to a raw binary ready to be run." msgstr "" -#: src/concurrency/send-sync/examples.md:31 +#: src/bare-metal/android.md:7 msgid "" -"* `MutexGuard`: Uses OS level primitives which must be deallocated on " -"the\n" -" thread which created them." +"```soong\n" +"rust_ffi_static {\n" +" name: \"libvmbase_example\",\n" +" defaults: [\"vmbase_ffi_defaults\"],\n" +" crate_name: \"vmbase_example\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libvmbase\",\n" +" ],\n" +"}\n" +"\n" +"cc_binary {\n" +" name: \"vmbase_example\",\n" +" defaults: [\"vmbase_elf_defaults\"],\n" +" srcs: [\n" +" \"idmap.S\",\n" +" ],\n" +" static_libs: [\n" +" \"libvmbase_example\",\n" +" ],\n" +" linker_scripts: [\n" +" \"image.ld\",\n" +" \":vmbase_sections\",\n" +" ],\n" +"}\n" +"\n" +"raw_binary {\n" +" name: \"vmbase_example_bin\",\n" +" stem: \"vmbase_example.bin\",\n" +" src: \":vmbase_example\",\n" +" enabled: false,\n" +" target: {\n" +" android_arm64: {\n" +" enabled: true,\n" +" },\n" +" },\n" +"}\n" +"```" msgstr "" -#: src/concurrency/send-sync/examples.md:34 -msgid "## `!Send + !Sync`" +#: src/bare-metal/android/vmbase.md:1 +msgid "# vmbase" msgstr "" -#: src/concurrency/send-sync/examples.md:36 -msgid "These types are not thread-safe and cannot be moved to other threads:" +#: src/bare-metal/android/vmbase.md:3 +msgid "" +"For VMs running under crosvm on aarch64, the [vmbase][1] library provides a " +"linker script and useful\n" +"defaults for the build rules, along with an entry point, UART console " +"logging and more." msgstr "" -#: src/concurrency/send-sync/examples.md:38 +#: src/bare-metal/android/vmbase.md:6 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." +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use vmbase::{main, println};\n" +"\n" +"main!(main);\n" +"\n" +"pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {\n" +" println!(\"Hello world\");\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-4/morning.md:1 src/exercises/day-4/afternoon.md:1 -msgid "# Exercises" +#: src/bare-metal/android/vmbase.md:21 +msgid "" +"* The `main!` macro marks your main function, to be called from the `vmbase` " +"entry point.\n" +"* The `vmbase` entry point handles console initialisation, and issues a " +"PSCI_SYSTEM_OFF to shutdown\n" +" the VM if your main function returns." msgstr "" -#: src/exercises/day-4/morning.md:3 -msgid "Let us practice our new concurrency skills with" +#: src/exercises/bare-metal/afternoon.md:3 +msgid "We will write a driver for the PL031 real-time clock device." msgstr "" -#: src/exercises/day-4/morning.md:5 -msgid "* Dining philosophers: a classic problem in concurrency." +#: src/exercises/bare-metal/rtc.md:1 +msgid "# RTC driver" msgstr "" -#: src/exercises/day-4/morning.md:7 +#: src/exercises/bare-metal/rtc.md:3 msgid "" -"* Multi-threaded link checker: a larger project where you'll use Cargo to\n" -" download dependencies and then check links in parallel." +"The QEMU aarch64 virt machine has a [PL031][1] real-time clock at 0x9010000. " +"For this exercise, you\n" +"should write a driver for it." msgstr "" -#: src/exercises/day-4/dining-philosophers.md:1 -msgid "# Dining Philosophers" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:3 -msgid "The dining philosophers problem is a classic problem in concurrency:" +#: src/exercises/bare-metal/rtc.md:6 +msgid "" +"1. Use it to print the current time to the serial console. You can use the " +"[`chrono`][2] crate for\n" +" date/time formatting.\n" +"2. Use the match register and raw interrupt status to busy-wait until a " +"given time, e.g. 3 seconds\n" +" 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`][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/day-4/dining-philosophers.md:5 +#: src/exercises/bare-metal/rtc.md:16 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." +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and " +"look in the `rtc`\n" +"directory for the following files." msgstr "" -#: src/exercises/day-4/dining-philosophers.md:13 +#: src/exercises/bare-metal/rtc.md:23 msgid "" -"You will need a local [Cargo installation](../../cargo/running-locally.md) " -"for\n" -"this exercise. Copy the code below to `src/main.rs` file, fill out the " -"blanks,\n" -"and test that `cargo run` does not deadlock:" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use arm_gic::gicv3::GicV3;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, trace, LevelFilter};\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" +"const GICR_BASE_ADDRESS: *mut u64 = 0x80A_0000 as _;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +"\n" +" // Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the " +"base\n" +" // addresses of a GICv3 distributor and redistributor respectively, and\n" +" // nothing else accesses those address ranges.\n" +" let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, " +"GICR_BASE_ADDRESS) };\n" +" gic.setup();\n" +"\n" +" // TODO: Create instance of RTC driver and print current time.\n" +"\n" +" // TODO: Wait for 3 seconds.\n" +"\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off::().unwrap();\n" +" loop {}\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:17 +#: src/exercises/bare-metal/rtc.md:75 msgid "" -"```rust,compile_fail\n" -"use std::sync::mpsc;\n" -"use std::sync::{Arc, Mutex};\n" -"use std::thread;\n" -"use std::time::Duration;" +"`src/exceptions.rs` (you should only need to change this for the 3rd part of " +"the exercise):" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:23 -#: src/exercises/day-4/solutions-morning.md:28 -msgid "struct Fork;" +#: src/exercises/bare-metal/rtc.md:77 +msgid "" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:25 +#: src/exercises/bare-metal/rtc.md:79 msgid "" -"struct Philosopher {\n" -" name: String,\n" -" // left_fork: ...\n" -" // right_fork: ...\n" -" // thoughts: ...\n" -"}" +"```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" +"use arm_gic::gicv3::GicV3;\n" +"use log::{error, info, trace};\n" +"use smccc::psci::system_off;\n" +"use smccc::Hvc;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_exception_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" +" trace!(\"irq_current\");\n" +" let intid = GicV3::get_and_acknowledge_interrupt().expect(\"No pending " +"interrupt\");\n" +" info!(\"IRQ {intid:?}\");\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"```" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:32 -msgid "" -"impl Philosopher {\n" -" fn think(&self) {\n" -" self.thoughts\n" -" .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" -" .unwrap();\n" -" }" +#: 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:151 +msgid "" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:39 +#: src/exercises/bare-metal/rtc.md:153 msgid "" -" fn eat(&self) {\n" -" // Pick up forks...\n" -" println!(\"{} is eating...\", &self.name);\n" -" thread::sleep(Duration::from_millis(10));\n" +"```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: main\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" " }\n" -"}" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), " +"SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: 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:212 +msgid "" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:46 -#: src/exercises/day-4/solutions-morning.md:60 +#: src/exercises/bare-metal/rtc.md:214 msgid "" -"static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];" +"```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" +"#![allow(unused)]\n" +"\n" +"use core::fmt::{self, Write};\n" +"use core::ptr::{addr_of, addr_of_mut};\n" +"\n" +"// ANCHOR: Flags\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"// ANCHOR_END: Flags\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART Receive Status Register / Error Clear Register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct ReceiveStatus: u16 {\n" +" /// Framing error.\n" +" const FE = 1 << 0;\n" +" /// Parity error.\n" +" const PE = 1 << 1;\n" +" /// Break error.\n" +" const BE = 1 << 2;\n" +" /// Overrun error.\n" +" const OE = 1 << 3;\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Registers\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"// ANCHOR_END: Registers\n" +"\n" +"// ANCHOR: Uart\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at " +"the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of " +"a\n" +" /// PL011 device, which must be mapped into the address space of the " +"process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been " +"received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr)." +"read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" +"}\n" +"// ANCHOR_END: Uart\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" +"```" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:49 +#: src/exercises/bare-metal/rtc.md:389 msgid "" -"fn main() {\n" -" // Create forks" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"rtc\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"arm-gic = \"0.1.0\"\n" +"bitflags = \"2.0.0\"\n" +"chrono = { version = \"0.4.24\", default-features = false }\n" +"log = \"0.4.17\"\n" +"smccc = \"0.1.1\"\n" +"spin = \"0.9.8\"\n" +"\n" +"[build-dependencies]\n" +"cc = \"1.0.73\"\n" +"```" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:52 -msgid " // Create philosophers" +#: src/exercises/bare-metal/rtc.md:410 +msgid "`build.rs` (you shouldn't need to change this):" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:54 -msgid " // Make them think and eat" +#: src/exercises/bare-metal/rtc.md:412 +msgid "" msgstr "" -#: src/exercises/day-4/dining-philosophers.md:56 +#: src/exercises/bare-metal/rtc.md:414 +#, fuzzy msgid "" -" // Output their thoughts\n" +"```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" +"use cc::Build;\n" +"use std::env;\n" +"\n" +"fn main() {\n" +" #[cfg(target_os = \"linux\")]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-linux-gnu\");\n" +" #[cfg(not(target_os = \"linux\"))]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-none-elf\");\n" +"\n" +" Build::new()\n" +" .file(\"entry.S\")\n" +" .file(\"exceptions.S\")\n" +" .file(\"idmap.S\")\n" +" .compile(\"empty\")\n" "}\n" "```" msgstr "" +"```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." -#: src/exercises/day-4/link-checker.md:1 -msgid "# Multi-threaded Link Checker" -msgstr "" - -#: src/exercises/day-4/link-checker.md:3 -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." +#: src/exercises/bare-metal/rtc.md:446 +msgid "`entry.S` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:448 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:450 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".macro adr_l, reg:req, sym:req\n" +"\tadrp \\reg, \\sym\n" +"\tadd \\reg, \\reg, :lo12:\\sym\n" +".endm\n" +"\n" +".macro mov_i, reg:req, imm:req\n" +"\tmovz \\reg, :abs_g3:\\imm\n" +"\tmovk \\reg, :abs_g2_nc:\\imm\n" +"\tmovk \\reg, :abs_g1_nc:\\imm\n" +"\tmovk \\reg, :abs_g0_nc:\\imm\n" +".endm\n" +"\n" +".set .L_MAIR_DEV_nGnRE,\t0x04\n" +".set .L_MAIR_MEM_WBWA,\t0xff\n" +".set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8)\n" +"\n" +"/* 4 KiB granule size for TTBR0_EL1. */\n" +".set .L_TCR_TG0_4KB, 0x0 << 14\n" +"/* 4 KiB granule size for TTBR1_EL1. */\n" +".set .L_TCR_TG1_4KB, 0x2 << 30\n" +"/* Disable translation table walk for TTBR1_EL1, generating a translation " +"fault instead. */\n" +".set .L_TCR_EPD1, 0x1 << 23\n" +"/* Translation table walks for TTBR0_EL1 are inner sharable. */\n" +".set .L_TCR_SH_INNER, 0x3 << 12\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are outer write-back read-allocate " +"write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_OWB, 0x1 << 10\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are inner write-back read-allocate " +"write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_IWB, 0x1 << 8\n" +"/* Size offset for TTBR0_EL1 is 2**39 bytes (512 GiB). */\n" +".set .L_TCR_T0SZ_512, 64 - 39\n" +".set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_TG1_4KB | .L_TCR_EPD1 | ." +"L_TCR_RGN_OWB\n" +".set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | ." +"L_TCR_T0SZ_512\n" +"\n" +"/* Stage 1 instruction access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_I, 0x1 << 12\n" +"/* SP alignment fault if SP is not aligned to a 16 byte boundary. */\n" +".set .L_SCTLR_ELx_SA, 0x1 << 3\n" +"/* Stage 1 data access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_C, 0x1 << 2\n" +"/* EL0 and EL1 stage 1 MMU enabled. */\n" +".set .L_SCTLR_ELx_M, 0x1 << 0\n" +"/* Privileged Access Never is unchanged on taking an exception to EL1. */\n" +".set .L_SCTLR_EL1_SPAN, 0x1 << 23\n" +"/* SETEND instruction disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_SED, 0x1 << 8\n" +"/* Various IT instructions are disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_ITD, 0x1 << 7\n" +".set .L_SCTLR_EL1_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << " +"28) | (0x1 << 29)\n" +".set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | ." +"L_SCTLR_EL1_ITD | .L_SCTLR_EL1_SED\n" +".set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL1_SPAN | ." +"L_SCTLR_EL1_RES1\n" +"\n" +"/**\n" +" * This is a generic entry point for an image. It carries out the operations " +"required to prepare the\n" +" * loaded image to be run. Specifically, it zeroes the bss section using " +"registers x25 and above,\n" +" * prepares the stack, enables floating point, and sets up the exception " +"vector. It preserves x0-x3\n" +" * for the Rust entry point, as these may contain boot parameters.\n" +" */\n" +".section .init.entry, \"ax\"\n" +".global entry\n" +"entry:\n" +"\t/* Load and apply the memory management configuration, ready to enable MMU " +"and caches. */\n" +"\tadrp x30, idmap\n" +"\tmsr ttbr0_el1, x30\n" +"\n" +"\tmov_i x30, .Lmairval\n" +"\tmsr mair_el1, x30\n" +"\n" +"\tmov_i x30, .Ltcrval\n" +"\t/* Copy the supported PA range into TCR_EL1.IPS. */\n" +"\tmrs x29, id_aa64mmfr0_el1\n" +"\tbfi x30, x29, #32, #4\n" +"\n" +"\tmsr tcr_el1, x30\n" +"\n" +"\tmov_i x30, .Lsctlrval\n" +"\n" +"\t/*\n" +"\t * Ensure everything before this point has completed, then invalidate any " +"potentially stale\n" +"\t * local TLB entries before they start being used.\n" +"\t */\n" +"\tisb\n" +"\ttlbi vmalle1\n" +"\tic iallu\n" +"\tdsb nsh\n" +"\tisb\n" +"\n" +"\t/*\n" +"\t * Configure sctlr_el1 to enable MMU and cache and don't proceed until " +"this has completed.\n" +"\t */\n" +"\tmsr sctlr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Disable trapping floating point access in EL1. */\n" +"\tmrs x30, cpacr_el1\n" +"\torr x30, x30, #(0x3 << 20)\n" +"\tmsr cpacr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Zero out the bss section. */\n" +"\tadr_l x29, bss_begin\n" +"\tadr_l x30, bss_end\n" +"0:\tcmp x29, x30\n" +"\tb.hs 1f\n" +"\tstp xzr, xzr, [x29], #16\n" +"\tb 0b\n" +"\n" +"1:\t/* Prepare the stack. */\n" +"\tadr_l x30, boot_stack_end\n" +"\tmov sp, x30\n" +"\n" +"\t/* Set up exception vector. */\n" +"\tadr x30, vector_table_el1\n" +"\tmsr vbar_el1, x30\n" +"\n" +"\t/* Call into Rust code. */\n" +"\tbl main\n" +"\n" +"\t/* Loop forever waiting for interrupts. */\n" +"2:\twfi\n" +"\tb 2b\n" +"```" msgstr "" -#: src/exercises/day-4/link-checker.md:8 -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:" +#: src/exercises/bare-metal/rtc.md:595 +msgid "`exceptions.S` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:597 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:599 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +"/**\n" +" * Saves the volatile registers onto the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers with 18 " +"instructions\n" +" * left.\n" +" *\n" +" * On return, x0 and x1 are initialised to elr_el2 and spsr_el2 " +"respectively,\n" +" * which can be used as the first and second arguments of a subsequent " +"call.\n" +" */\n" +".macro save_volatile_to_stack\n" +"\t/* Reserve stack space and save registers x0-x18, x29 & x30. */\n" +"\tstp x0, x1, [sp, #-(8 * 24)]!\n" +"\tstp x2, x3, [sp, #8 * 2]\n" +"\tstp x4, x5, [sp, #8 * 4]\n" +"\tstp x6, x7, [sp, #8 * 6]\n" +"\tstp x8, x9, [sp, #8 * 8]\n" +"\tstp x10, x11, [sp, #8 * 10]\n" +"\tstp x12, x13, [sp, #8 * 12]\n" +"\tstp x14, x15, [sp, #8 * 14]\n" +"\tstp x16, x17, [sp, #8 * 16]\n" +"\tstr x18, [sp, #8 * 18]\n" +"\tstp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/*\n" +"\t * Save elr_el1 & spsr_el1. This such that we can take nested exception\n" +"\t * and still be able to unwind.\n" +"\t */\n" +"\tmrs x0, elr_el1\n" +"\tmrs x1, spsr_el1\n" +"\tstp x0, x1, [sp, #8 * 22]\n" +".endm\n" +"\n" +"/**\n" +" * Restores the volatile registers from the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers while still leaving " +"18\n" +" * instructions left; if paired with save_volatile_to_stack, there are 4\n" +" * instructions to spare.\n" +" */\n" +".macro restore_volatile_from_stack\n" +"\t/* Restore registers x2-x18, x29 & x30. */\n" +"\tldp x2, x3, [sp, #8 * 2]\n" +"\tldp x4, x5, [sp, #8 * 4]\n" +"\tldp x6, x7, [sp, #8 * 6]\n" +"\tldp x8, x9, [sp, #8 * 8]\n" +"\tldp x10, x11, [sp, #8 * 10]\n" +"\tldp x12, x13, [sp, #8 * 12]\n" +"\tldp x14, x15, [sp, #8 * 14]\n" +"\tldp x16, x17, [sp, #8 * 16]\n" +"\tldr x18, [sp, #8 * 18]\n" +"\tldp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/* Restore registers elr_el1 & spsr_el1, using x0 & x1 as scratch. */\n" +"\tldp x0, x1, [sp, #8 * 22]\n" +"\tmsr elr_el1, x0\n" +"\tmsr spsr_el1, x1\n" +"\n" +"\t/* Restore x0 & x1, and release stack space. */\n" +"\tldp x0, x1, [sp], #8 * 24\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while " +"using\n" +" * SP0. It behaves similarly to the SPx case by first switching to SPx, " +"doing\n" +" * the work, then switching back to SP0 before returning.\n" +" *\n" +" * Switching to SPx and calling the Rust handler takes 16 instructions. To\n" +" * restore and return we need an additional 16 instructions, so we can " +"implement\n" +" * the whole handler within the allotted 32 instructions.\n" +" */\n" +".macro current_exception_sp0 handler:req\n" +"\tmsr spsel, #1\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\tmsr spsel, #0\n" +"\teret\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while " +"using\n" +" * SPx. It saves volatile registers, calls the Rust handler, restores " +"volatile\n" +" * registers, then returns.\n" +" *\n" +" * This also works for exceptions taken from EL0, if we don't care about\n" +" * non-volatile registers.\n" +" *\n" +" * Saving state and jumping to the Rust handler takes 15 instructions, and\n" +" * restoring and returning also takes 15 instructions, so we can fit the " +"whole\n" +" * handler in 30 instructions, under the limit of 32.\n" +" */\n" +".macro current_exception_spx handler:req\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\teret\n" +".endm\n" +"\n" +".section .text.vector_table_el1, \"ax\"\n" +".global vector_table_el1\n" +".balign 0x800\n" +"vector_table_el1:\n" +"sync_cur_sp0:\n" +"\tcurrent_exception_sp0 sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_sp0:\n" +"\tcurrent_exception_sp0 irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_sp0:\n" +"\tcurrent_exception_sp0 fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_sp0:\n" +"\tcurrent_exception_sp0 serr_current\n" +"\n" +".balign 0x80\n" +"sync_cur_spx:\n" +"\tcurrent_exception_spx sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_spx:\n" +"\tcurrent_exception_spx irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_spx:\n" +"\tcurrent_exception_spx fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_spx:\n" +"\tcurrent_exception_spx serr_current\n" +"\n" +".balign 0x80\n" +"sync_lower_64:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_64:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_64:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_64:\n" +"\tcurrent_exception_spx serr_lower\n" +"\n" +".balign 0x80\n" +"sync_lower_32:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_32:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_32:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_32:\n" +"\tcurrent_exception_spx serr_lower\n" +"```" msgstr "" -#: 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" +#: src/exercises/bare-metal/rtc.md:780 +msgid "`idmap.S` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:782 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:784 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".set .L_TT_TYPE_BLOCK, 0x1\n" +".set .L_TT_TYPE_PAGE, 0x3\n" +".set .L_TT_TYPE_TABLE, 0x3\n" +"\n" +"/* Access flag. */\n" +".set .L_TT_AF, 0x1 << 10\n" +"/* Not global. */\n" +".set .L_TT_NG, 0x1 << 11\n" +".set .L_TT_XN, 0x3 << 53\n" +"\n" +".set .L_TT_MT_DEV, 0x0 << 2\t\t\t// MAIR #0 (DEV_nGnRE)\n" +".set .L_TT_MT_MEM, (0x1 << 2) | (0x3 << 8)\t// MAIR #1 (MEM_WBWA), inner " +"shareable\n" +"\n" +".set .L_BLOCK_DEV, .L_TT_TYPE_BLOCK | .L_TT_MT_DEV | .L_TT_AF | .L_TT_XN\n" +".set .L_BLOCK_MEM, .L_TT_TYPE_BLOCK | .L_TT_MT_MEM | .L_TT_AF | .L_TT_NG\n" +"\n" +".section \".rodata.idmap\", \"a\", %progbits\n" +".global idmap\n" +".align 12\n" +"idmap:\n" +"\t/* level 1 */\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x0\t\t // 1 GiB of device mappings\n" +"\t.quad\t\t.L_BLOCK_MEM | 0x40000000\t// 1 GiB of DRAM\n" +"\t.fill\t\t254, 8, 0x0\t\t\t// 254 GiB of unmapped VA space\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x4000000000 // 1 GiB of device mappings\n" +"\t.fill\t\t255, 8, 0x0\t\t\t// 255 GiB of remaining VA space\n" "```" msgstr "" -#: src/exercises/day-4/link-checker.md:17 -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." +#: src/exercises/bare-metal/rtc.md:829 +msgid "`image.ld` (you shouldn't need to change this):" msgstr "" -#: src/exercises/day-4/link-checker.md:20 -msgid "" -"You will also need a way to find links. We can use [`scraper`][2] for that:" +#: src/exercises/bare-metal/rtc.md:831 +msgid "" msgstr "" -#: src/exercises/day-4/link-checker.md:22 +#: src/exercises/bare-metal/rtc.md:833 msgid "" -"```shell\n" -"$ cargo add scraper\n" +"```ld\n" +"/*\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" +" * https://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" +"\n" +"/*\n" +" * Code will start running at this symbol which is placed at the start of " +"the\n" +" * image.\n" +" */\n" +"ENTRY(entry)\n" +"\n" +"MEMORY\n" +"{\n" +"\timage : ORIGIN = 0x40080000, LENGTH = 2M\n" +"}\n" +"\n" +"SECTIONS\n" +"{\n" +"\t/*\n" +"\t * Collect together the code.\n" +"\t */\n" +"\t.init : ALIGN(4096) {\n" +"\t\ttext_begin = .;\n" +"\t\t*(.init.entry)\n" +"\t\t*(.init.*)\n" +"\t} >image\n" +"\t.text : {\n" +"\t\t*(.text.*)\n" +"\t} >image\n" +"\ttext_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together read-only data.\n" +"\t */\n" +"\t.rodata : ALIGN(4096) {\n" +"\t\trodata_begin = .;\n" +"\t\t*(.rodata.*)\n" +"\t} >image\n" +"\t.got : {\n" +"\t\t*(.got)\n" +"\t} >image\n" +"\trodata_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together the read-write data including .bss at the end which\n" +"\t * will be zero'd by the entry code.\n" +"\t */\n" +"\t.data : ALIGN(4096) {\n" +"\t\tdata_begin = .;\n" +"\t\t*(.data.*)\n" +"\t\t/*\n" +"\t\t * The entry point code assumes that .data is a multiple of 32\n" +"\t\t * bytes long.\n" +"\t\t */\n" +"\t\t. = ALIGN(32);\n" +"\t\tdata_end = .;\n" +"\t} >image\n" +"\n" +"\t/* Everything beyond this point will not be included in the binary. */\n" +"\tbin_end = .;\n" +"\n" +"\t/* The entry point code assumes that .bss is 16-byte aligned. */\n" +"\t.bss : ALIGN(16) {\n" +"\t\tbss_begin = .;\n" +"\t\t*(.bss.*)\n" +"\t\t*(COMMON)\n" +"\t\t. = ALIGN(16);\n" +"\t\tbss_end = .;\n" +"\t} >image\n" +"\n" +"\t.stack (NOLOAD) : ALIGN(4096) {\n" +"\t\tboot_stack_begin = .;\n" +"\t\t. += 40 * 4096;\n" +"\t\t. = ALIGN(4096);\n" +"\t\tboot_stack_end = .;\n" +"\t} >image\n" +"\n" +"\t. = ALIGN(4K);\n" +"\tPROVIDE(dma_region = .);\n" +"\n" +"\t/*\n" +"\t * Remove unused sections from the image.\n" +"\t */\n" +"\t/DISCARD/ : {\n" +"\t\t/* The image loads itself so doesn't need these sections. */\n" +"\t\t*(.gnu.hash)\n" +"\t\t*(.hash)\n" +"\t\t*(.interp)\n" +"\t\t*(.eh_frame_hdr)\n" +"\t\t*(.eh_frame)\n" +"\t\t*(.note.gnu.build-id)\n" +"\t}\n" +"}\n" "```" msgstr "" -#: src/exercises/day-4/link-checker.md:26 -msgid "" -"Finally, we'll need some way of handling errors. We [`thiserror`][3] for " -"that:" +#: src/exercises/bare-metal/rtc.md:940 +msgid "`Makefile` (you shouldn't need to change this):" msgstr "" -#: src/exercises/day-4/link-checker.md:28 -msgid "" -"```shell\n" -"$ cargo add thiserror\n" -"```" +#: src/exercises/bare-metal/rtc.md:942 +msgid "" msgstr "" -#: src/exercises/day-4/link-checker.md:32 +#: src/exercises/bare-metal/rtc.md:944 +#, fuzzy msgid "" -"The `cargo add` calls will update the `Cargo.toml` file to look like this:" +"```makefile\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" +"UNAME := $(shell uname -s)\n" +"ifeq ($(UNAME),Linux)\n" +"\tTARGET = aarch64-linux-gnu\n" +"else\n" +"\tTARGET = aarch64-none-elf\n" +"endif\n" +"OBJCOPY = $(TARGET)-objcopy\n" +"\n" +".PHONY: build qemu_minimal qemu qemu_logger\n" +"\n" +"all: rtc.bin\n" +"\n" +"build:\n" +"\tcargo build\n" +"\n" +"rtc.bin: build\n" +"\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 $< -s\n" +"\n" +"clean:\n" +"\tcargo clean\n" +"\trm -f *.bin\n" +"```" msgstr "" +"```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." -#: src/exercises/day-4/link-checker.md:34 +#: src/exercises/bare-metal/rtc.md:989 msgid "" "```toml\n" -"[dependencies]\n" -"reqwest = { version = \"0.11.12\", features = [\"blocking\", \"rustls-" -"tls\"] }\n" -"scraper = \"0.13.0\"\n" -"thiserror = \"1.0.37\"\n" +"[build]\n" +"target = \"aarch64-unknown-none\"\n" +"rustflags = [\"-C\", \"link-arg=-Timage.ld\"]\n" "```" msgstr "" -#: src/exercises/day-4/link-checker.md:41 -msgid "" -"You can now download the start page. Try with a small site such as\n" -"`https://www.google.org/`." -msgstr "" - -#: src/exercises/day-4/link-checker.md:44 -msgid "Your `src/main.rs` file should look something like this:" +#: src/exercises/bare-metal/rtc.md:995 +msgid "Run the code in QEMU with `make qemu`." msgstr "" -#: src/exercises/day-4/link-checker.md:46 -msgid "" -"```rust,compile_fail\n" -"use reqwest::blocking::{get, Response};\n" -"use reqwest::Url;\n" -"use scraper::{Html, Selector};\n" -"use thiserror::Error;" -msgstr "" +#: src/concurrency.md:1 +#, fuzzy +msgid "# Welcome to Concurrency in Rust" +msgstr "# Velkommen til Comprehensive Rust 🦀" -#: src/exercises/day-4/link-checker.md:52 +#: src/concurrency.md:3 msgid "" -"#[derive(Error, Debug)]\n" -"enum Error {\n" -" #[error(\"request error: {0}\")]\n" -" ReqwestError(#[from] reqwest::Error),\n" -"}" +"Rust has full support for concurrency using OS threads with mutexes and\n" +"channels." msgstr "" -#: src/exercises/day-4/link-checker.md:58 +#: src/concurrency.md:6 msgid "" -"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();" +"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 "" -#: src/exercises/day-4/link-checker.md:64 -msgid "" -" 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" -" }" +#: src/concurrency/threads.md:1 +msgid "# Threads" msgstr "" -#: src/exercises/day-4/link-checker.md:76 -msgid "" -" Ok(valid_urls)\n" -"}" +#: src/concurrency/threads.md:3 +msgid "Rust threads work similarly to threads in other languages:" msgstr "" -#: src/exercises/day-4/link-checker.md:79 +#: src/concurrency/threads.md:5 msgid "" +"```rust,editable\n" +"use std::thread;\n" +"use std::time::Duration;\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" +" 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/exercises/day-4/link-checker.md:89 -msgid "Run the code in `src/main.rs` with" +#: src/concurrency/threads.md:24 +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 "" -#: src/exercises/day-4/link-checker.md:91 +#: src/concurrency/threads.md:32 msgid "" -"```shell\n" -"$ cargo run\n" -"```" +"* 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/exercises/day-4/link-checker.md:95 -msgid "## Tasks" +#: src/concurrency/scoped-threads.md:1 +msgid "# Scoped Threads" msgstr "" -#: src/exercises/day-4/link-checker.md:97 -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." +#: src/concurrency/scoped-threads.md:3 +msgid "Normal threads cannot borrow from their environment:" msgstr "" -#: src/exercises/day-4/link-checker.md:103 +#: src/concurrency/scoped-threads.md:5 msgid "" -"[1]: https://docs.rs/reqwest/\n" -"[2]: https://docs.rs/scraper/\n" -"[3]: https://docs.rs/thiserror/" +"```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/android.md:1 -msgid "# Android" +#: src/concurrency/scoped-threads.md:17 +msgid "However, you can use a [scoped thread][1] for this:" +msgstr "" + +#: 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/android.md:3 +#: src/concurrency/scoped-threads.md:37 msgid "" -"Rust is supported for native platform development on Android. This means " -"that\n" -"you can write new operating system services in Rust, as well as extending\n" -"existing services." +"* 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 "" -#: src/android/setup.md:1 -msgid "# Setup" +#: src/concurrency/channels.md:1 +msgid "# Channels" msgstr "" -#: src/android/setup.md:3 +#: src/concurrency/channels.md:3 msgid "" -"We will be using an Android Virtual Device to test our code. Make sure you " -"have\n" -"access to one or create a new one with:" +"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 "" -#: src/android/setup.md:6 +#: src/concurrency/channels.md:6 msgid "" -"```shell\n" -"$ source build/envsetup.sh\n" -"$ lunch aosp_cf_x86_64_phone-userdebug\n" -"$ acloud create\n" +"```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/android/setup.md:12 +#: src/concurrency/channels.md:27 msgid "" -"Please see the [Android Developer\n" -"Codelab](https://source.android.com/docs/setup/start) for details." +"* `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 "" -#: src/android/build-rules.md:1 -msgid "# Build Rules" +#: src/concurrency/channels/unbounded.md:1 +msgid "# Unbounded Channels" msgstr "" -#: src/android/build-rules.md:3 -msgid "The Android build system (Soong) supports Rust via a number of modules:" +#: src/concurrency/channels/unbounded.md:3 +msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" msgstr "" -#: src/android/build-rules.md:5 +#: src/concurrency/channels/unbounded.md:5 msgid "" -"| Module Type | " -"Description " -"|\n" -"|-------------------|----------------------------------------------------------------------------------------------------|\n" -"| `rust_binary` | Produces a Rust " -"binary. " -"|\n" -"| `rust_library` | Produces a Rust library, and provides both `rlib` and " -"`dylib` variants. |\n" -"| `rust_ffi` | Produces a Rust C library usable by `cc` modules, and " -"provides both static and shared variants. |\n" -"| `rust_proc_macro` | Produces a `proc-macro` Rust library. These are " -"analogous to compiler plugins. |\n" -"| `rust_test` | Produces a Rust test binary that uses the standard " -"Rust test harness. |\n" -"| `rust_fuzz` | Produces a Rust fuzz binary leveraging " -"`libfuzzer`. |\n" -"| `rust_protobuf` | Generates source and produces a Rust library that " -"provides an interface for a particular protobuf. |\n" -"| `rust_bindgen` | Generates source and produces a Rust library " -"containing Rust bindings to C libraries. |" +"```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/android/build-rules.md:16 -msgid "We will look at `rust_binary` and `rust_library` next." +#: src/concurrency/channels/bounded.md:1 +msgid "# Bounded Channels" msgstr "" -#: src/android/build-rules/binary.md:1 -msgid "# Rust Binaries" +#: src/concurrency/channels/bounded.md:3 +msgid "Bounded and synchronous channels make `send` block the current thread:" msgstr "" -#: src/android/build-rules/binary.md:3 +#: src/concurrency/channels/bounded.md:5 msgid "" -"Let us start with a simple application. At the root of an AOSP checkout, " -"create\n" -"the following files:" +"```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/android/build-rules/binary.md:6 src/android/build-rules/library.md:13 -msgid "_hello_rust/Android.bp_:" +#: src/concurrency/send-sync.md:1 +msgid "# `Send` and `Sync`" msgstr "" -#: src/android/build-rules/binary.md:8 +#: src/concurrency/send-sync.md:3 msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"hello_rust\",\n" -" crate_name: \"hello_rust\",\n" -" srcs: [\"src/main.rs\"],\n" -"}\n" -"```" +"How does Rust know to forbid shared access across thread? The answer is in " +"two traits:" msgstr "" -#: src/android/build-rules/binary.md:16 src/android/build-rules/library.md:34 -msgid "_hello_rust/src/main.rs_:" +#: src/concurrency/send-sync.md:5 +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 "" -#: src/android/build-rules/binary.md:18 +#: src/concurrency/send-sync.md:10 msgid "" -"```rust\n" -"//! Rust demo." +"`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 "" -#: src/android/build-rules/binary.md:21 +#: src/concurrency/send-sync.md:20 msgid "" -"/// Prints a greeting to standard output.\n" -"fn main() {\n" -" println!(\"Hello from Rust!\");\n" -"}\n" -"```" +"* 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 "" -#: src/android/build-rules/binary.md:27 -msgid "You can now build, push, and run the binary:" +#: src/concurrency/send-sync/send.md:1 +msgid "# `Send`" msgstr "" -#: src/android/build-rules/binary.md:29 +#: src/concurrency/send-sync/send.md:3 msgid "" -"```shell\n" -"$ m hello_rust\n" -"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\n" -"$ adb shell /data/local/tmp/hello_rust\n" -"Hello from Rust!\n" -"```" +"> A type `T` is [`Send`][1] if it is safe to move a `T` value to another " +"thread." msgstr "" -#: src/android/build-rules/library.md:1 -msgid "# Rust Libraries" +#: src/concurrency/send-sync/send.md:5 +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 "" -#: src/android/build-rules/library.md:3 -msgid "You use `rust_library` to create a new Rust library for Android." +#: 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/android/build-rules/library.md:5 -msgid "Here we declare a dependency on two libraries:" +#: src/concurrency/send-sync/sync.md:1 +msgid "# `Sync`" msgstr "" -#: src/android/build-rules/library.md:7 +#: src/concurrency/send-sync/sync.md:3 msgid "" -"* `libgreeting`, which we define below,\n" -"* `libtextwrap`, which is a crate already vendored in\n" -" [`external/rust/crates/`][crates]." +"> A type `T` is [`Sync`][1] if it is safe to access a `T` value from " +"multiple\n" +"> threads at the same time." msgstr "" -#: src/android/build-rules/library.md:11 -msgid "" -"[crates]: https://cs.android.com/android/platform/superproject/+/master:" -"external/rust/crates/" +#: src/concurrency/send-sync/sync.md:6 +msgid "More precisely, the definition is:" msgstr "" -#: src/android/build-rules/library.md:15 -msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"hello_rust_with_dep\",\n" -" crate_name: \"hello_rust_with_dep\",\n" -" srcs: [\"src/main.rs\"],\n" -" rustlibs: [\n" -" \"libgreetings\",\n" -" \"libtextwrap\",\n" -" ],\n" -" prefer_rlib: true,\n" -"}" +#: src/concurrency/send-sync/sync.md:8 +msgid "> `T` is `Sync` if and only if `&T` is `Send`" msgstr "" -#: src/android/build-rules/library.md:27 +#: src/concurrency/send-sync/sync.md:14 msgid "" -"rust_library {\n" -" name: \"libgreetings\",\n" -" crate_name: \"greetings\",\n" -" srcs: [\"src/lib.rs\"],\n" -"}\n" -"```" +"This statement is essentially a shorthand way of saying that if a type is " +"thread-safe for shared use, it is also thread-safe to pass references of it " +"across threads." msgstr "" -#: src/android/build-rules/library.md:36 +#: src/concurrency/send-sync/sync.md:16 msgid "" -"```rust,ignore\n" -"//! Rust demo." +"This is because if a type is Sync it means that it can be shared across " +"multiple threads without the risk of data races or other synchronization " +"issues, so it is safe to move it to another thread. A reference to the type " +"is also safe to move to another thread, because the data it references can " +"be accessed from any thread safely." msgstr "" -#: src/android/build-rules/library.md:39 -msgid "" -"use greetings::greeting;\n" -"use textwrap::fill;" +#: src/concurrency/send-sync/examples.md:1 +msgid "# Examples" msgstr "" -#: src/android/build-rules/library.md:42 -msgid "" -"/// Prints a greeting to standard output.\n" -"fn main() {\n" -" println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" -"}\n" -"```" +#: src/concurrency/send-sync/examples.md:3 +msgid "## `Send + Sync`" msgstr "" -#: src/android/build-rules/library.md:48 -msgid "_hello_rust/src/lib.rs_:" +#: src/concurrency/send-sync/examples.md:5 +msgid "Most types you come across are `Send + Sync`:" msgstr "" -#: src/android/build-rules/library.md:50 +#: src/concurrency/send-sync/examples.md:7 msgid "" -"```rust,ignore\n" -"//! Greeting library." +"* `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/android/build-rules/library.md:53 +#: src/concurrency/send-sync/examples.md:14 msgid "" -"/// Greet `name`.\n" -"pub fn greeting(name: &str) -> String {\n" -" format!(\"Hello {name}, it is very nice to meet you!\")\n" -"}\n" -"```" +"The generic types are typically `Send + Sync` when the type parameters are\n" +"`Send + Sync`." msgstr "" -#: src/android/build-rules/library.md:59 -msgid "You build, push, and run the binary like before:" +#: src/concurrency/send-sync/examples.md:17 +msgid "## `Send + !Sync`" +msgstr "" + +#: src/concurrency/send-sync/examples.md:19 +msgid "" +"These types can be moved to other threads, but they're not thread-safe.\n" +"Typically because of interior mutability:" msgstr "" -#: src/android/build-rules/library.md:61 +#: src/concurrency/send-sync/examples.md:22 msgid "" -"```shell\n" -"$ m hello_rust_with_dep\n" -"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/" -"tmp\n" -"$ adb shell /data/local/tmp/hello_rust_with_dep\n" -"Hello Bob, it is very\n" -"nice to meet you!\n" -"```" +"* `mpsc::Sender`\n" +"* `mpsc::Receiver`\n" +"* `Cell`\n" +"* `RefCell`" msgstr "" -#: src/android/aidl.md:1 -msgid "# AIDL" +#: src/concurrency/send-sync/examples.md:27 +msgid "## `!Send + Sync`" msgstr "" -#: src/android/aidl.md:3 +#: src/concurrency/send-sync/examples.md:29 msgid "" -"The [Android Interface Definition Language\n" -"(AIDL)](https://developer.android.com/guide/components/aidl) is supported in " -"Rust:" +"These types are thread-safe, but they cannot be moved to another thread:" msgstr "" -#: src/android/aidl.md:6 +#: src/concurrency/send-sync/examples.md:31 msgid "" -"* Rust code can call existing AIDL servers,\n" -"* You can create new AIDL servers in Rust." +"* `MutexGuard`: Uses OS level primitives which must be deallocated on " +"the\n" +" thread which created them." msgstr "" -#: src/android/aidl/interface.md:1 -msgid "# AIDL Interfaces" +#: src/concurrency/send-sync/examples.md:34 +msgid "## `!Send + !Sync`" msgstr "" -#: src/android/aidl/interface.md:3 -msgid "You declare the API of your service using an AIDL interface:" +#: src/concurrency/send-sync/examples.md:36 +msgid "These types are not thread-safe and cannot be moved to other threads:" msgstr "" -#: src/android/aidl/interface.md:5 +#: src/concurrency/send-sync/examples.md:38 msgid "" -"*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" +"* `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 "" + +#: src/concurrency/shared_state.md:1 +msgid "# Shared State" msgstr "" -#: src/android/aidl/interface.md:7 src/android/aidl/changing.md:6 +#: src/concurrency/shared_state.md:3 msgid "" -"```java\n" -"package com.example.birthdayservice;" +"Rust uses the type system to enforce synchronization of shared data. This " +"is\n" +"primarily done via two types:" msgstr "" -#: src/android/aidl/interface.md:10 +#: src/concurrency/shared_state.md:6 msgid "" -"/** Birthday service interface. */\n" -"interface IBirthdayService {\n" -" /** Generate a Happy Birthday message. */\n" -" String wishHappyBirthday(String name, int years);\n" -"}\n" -"```" +"* [`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 "" -#: src/android/aidl/interface.md:17 -msgid "*birthday_service/aidl/Android.bp*:" +#: src/concurrency/shared_state/arc.md:1 +msgid "# `Arc`" msgstr "" -#: src/android/aidl/interface.md:19 +#: src/concurrency/shared_state/arc.md:3 +msgid "[`Arc`][1] allows shared read-only access via `Arc::clone`:" +msgstr "" + +#: src/concurrency/shared_state/arc.md:5 msgid "" -"```javascript\n" -"aidl_interface {\n" -" name: \"com.example.birthdayservice\",\n" -" srcs: [\"com/example/birthdayservice/*.aidl\"],\n" -" unstable: true,\n" -" backend: {\n" -" rust: { // Rust is not enabled by default\n" -" enabled: true,\n" -" },\n" -" },\n" +"```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/android/aidl/interface.md:32 +#: src/concurrency/shared_state/arc.md:29 msgid "" -"Add `vendor_available: true` if your AIDL file is used by a binary in the " -"vendor\n" -"partition." +"* `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 "" -#: src/android/aidl/implementation.md:1 -msgid "# Service Implementation" +#: src/concurrency/shared_state/mutex.md:1 +msgid "# `Mutex`" msgstr "" -#: src/android/aidl/implementation.md:3 -msgid "We can now implement the AIDL service:" +#: src/concurrency/shared_state/mutex.md:3 +msgid "" +"[`Mutex`][1] ensures mutual exclusion _and_ allows mutable access to `T`\n" +"behind a read-only interface:" msgstr "" -#: src/android/aidl/implementation.md:5 -msgid "*birthday_service/src/lib.rs*:" +#: 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/android/aidl/implementation.md:7 +#: src/concurrency/shared_state/mutex.md:22 msgid "" -"```rust,ignore\n" -"//! Implementation of the `IBirthdayService` AIDL interface.\n" -"use com_example_birthdayservice::aidl::com::example::birthdayservice::" -"IBirthdayService::IBirthdayService;\n" -"use com_example_birthdayservice::binder;" +"Notice how we have a [`impl Sync for Mutex`][2] blanket\n" +"implementation." msgstr "" -#: src/android/aidl/implementation.md:12 +#: src/concurrency/shared_state/mutex.md:31 msgid "" -"/// The `IBirthdayService` implementation.\n" -"pub struct BirthdayService;" +"* `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 "" -#: src/android/aidl/implementation.md:15 -msgid "impl binder::Interface for BirthdayService {}" +#: src/concurrency/shared_state/example.md:3 +msgid "Let us see `Arc` and `Mutex` in action:" msgstr "" -#: src/android/aidl/implementation.md:17 +#: src/concurrency/shared_state/example.md:5 msgid "" -"impl IBirthdayService for BirthdayService {\n" -" fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::" -"Result {\n" -" Ok(format!(\n" -" \"Happy Birthday {name}, congratulations with the {years} years!" -"\"\n" -" ))\n" -" }\n" +"```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/android/aidl/implementation.md:26 src/android/aidl/server.md:28 -#: src/android/aidl/client.md:37 -msgid "*birthday_service/Android.bp*:" +#: src/concurrency/shared_state/example.md:23 +msgid "Possible solution:" msgstr "" -#: src/android/aidl/implementation.md:28 +#: src/concurrency/shared_state/example.md:25 msgid "" -"```javascript\n" -"rust_library {\n" -" name: \"libbirthdayservice\",\n" -" srcs: [\"src/lib.rs\"],\n" -" crate_name: \"birthdayservice\",\n" -" rustlibs: [\n" -" \"com.example.birthdayservice-rust\",\n" -" \"libbinder_rs\",\n" -" ],\n" +"```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/android/aidl/server.md:1 -msgid "# AIDL Server" +#: src/concurrency/shared_state/example.md:49 +msgid "Notable parts:" msgstr "" -#: src/android/aidl/server.md:3 -msgid "Finally, we can create a server which exposes the service:" +#: src/concurrency/shared_state/example.md:51 +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 "" -#: src/android/aidl/server.md:5 -msgid "*birthday_service/src/server.rs*:" +#: src/exercises/concurrency/morning.md:3 +msgid "Let us practice our new concurrency skills with" msgstr "" -#: src/android/aidl/server.md:7 +#: src/exercises/concurrency/morning.md:5 msgid "" -"```rust,ignore\n" -"//! Birthday service.\n" -"use birthdayservice::BirthdayService;\n" -"use com_example_birthdayservice::aidl::com::example::birthdayservice::" -"IBirthdayService::BnBirthdayService;\n" -"use com_example_birthdayservice::binder;" +"* 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 "" + +#: src/exercises/concurrency/dining-philosophers.md:1 +msgid "# Dining Philosophers" msgstr "" -#: src/android/aidl/server.md:13 src/android/aidl/client.md:12 -msgid "const SERVICE_IDENTIFIER: &str = \"birthdayservice\";" +#: src/exercises/concurrency/dining-philosophers.md:3 +msgid "The dining philosophers problem is a classic problem in concurrency:" msgstr "" -#: src/android/aidl/server.md:15 +#: src/exercises/concurrency/dining-philosophers.md:5 msgid "" -"/// Entry point for birthday service.\n" -"fn main() {\n" -" let birthday_service = BirthdayService;\n" -" let birthday_service_binder = BnBirthdayService::new_binder(\n" -" birthday_service,\n" -" binder::BinderFeatures::default(),\n" -" );\n" -" binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder." -"as_binder())\n" -" .expect(\"Failed to register service\");\n" -" binder::ProcessState::join_thread_pool()\n" -"}\n" -"```" +"> 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 "" -#: src/android/aidl/server.md:30 +#: src/exercises/concurrency/dining-philosophers.md:13 msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"birthday_server\",\n" -" crate_name: \"birthday_server\",\n" -" srcs: [\"src/server.rs\"],\n" -" rustlibs: [\n" -" \"com.example.birthdayservice-rust\",\n" -" \"libbinder_rs\",\n" -" \"libbirthdayservice\",\n" -" ],\n" -" prefer_rlib: true,\n" +"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 "" + +#: 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/android/aidl/deploy.md:1 -msgid "# Deploy" -msgstr "" - -#: src/android/aidl/deploy.md:3 -msgid "We can now build, push, and start the service:" +#: src/exercises/concurrency/dining-philosophers.md:61 +msgid "You can use the following `Cargo.toml`:" msgstr "" -#: src/android/aidl/deploy.md:5 +#: src/exercises/concurrency/dining-philosophers.md:65 msgid "" -"```shell\n" -"$ m birthday_server\n" -"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp\n" -"$ adb shell /data/local/tmp/birthday_server\n" +"```toml\n" +"[package]\n" +"name = \"dining-philosophers\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" "```" msgstr "" -#: src/android/aidl/deploy.md:11 -msgid "In another terminal, check that the service runs:" +#: src/exercises/concurrency/link-checker.md:1 +msgid "# Multi-threaded Link Checker" msgstr "" -#: src/android/aidl/deploy.md:13 +#: src/exercises/concurrency/link-checker.md:3 msgid "" -"```shell\n" -"$ adb shell service check birthdayservice\n" -"Service birthdayservice: found\n" -"```" +"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 "" -#: src/android/aidl/deploy.md:18 -msgid "You can also call the service with `service call`:" +#: src/exercises/concurrency/link-checker.md:8 +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 "" -#: src/android/aidl/deploy.md:20 +#: src/exercises/concurrency/link-checker.md:11 msgid "" "```shell\n" -"$ $ adb shell service call birthdayservice 1 s16 Bob i32 24\n" -"Result: Parcel(\n" -" 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" -" 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" -" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'\n" -" 0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'\n" -" 0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'\n" -" 0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'\n" -" 0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'\n" -" 0x00000070: 00210073 00000000 's.!..... ')\n" +"$ cargo new link-checker\n" +"$ cd link-checker\n" +"$ cargo add --features blocking,rustls-tls reqwest\n" "```" msgstr "" -#: src/android/aidl/client.md:1 -msgid "# AIDL Client" +#: src/exercises/concurrency/link-checker.md:17 +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 "" -#: src/android/aidl/client.md:3 -msgid "Finally, we can create a Rust client for our new service." +#: src/exercises/concurrency/link-checker.md:20 +msgid "" +"You will also need a way to find links. We can use [`scraper`][2] for that:" msgstr "" -#: src/android/aidl/client.md:5 -msgid "*birthday_service/src/client.rs*:" +#: src/exercises/concurrency/link-checker.md:22 +msgid "" +"```shell\n" +"$ cargo add scraper\n" +"```" msgstr "" -#: src/android/aidl/client.md:7 +#: src/exercises/concurrency/link-checker.md:26 msgid "" -"```rust,ignore\n" -"//! Birthday service.\n" -"use com_example_birthdayservice::aidl::com::example::birthdayservice::" -"IBirthdayService::IBirthdayService;\n" -"use com_example_birthdayservice::binder;" +"Finally, we'll need some way of handling errors. We use [`thiserror`][3] " +"for\n" +"that:" msgstr "" -#: src/android/aidl/client.md:14 +#: src/exercises/concurrency/link-checker.md:29 msgid "" -"/// Connect to the BirthdayService.\n" -"pub fn connect() -> Result, binder::" -"StatusCode> {\n" -" binder::get_interface(SERVICE_IDENTIFIER)\n" -"}" +"```shell\n" +"$ cargo add thiserror\n" +"```" msgstr "" -#: src/android/aidl/client.md:19 +#: src/exercises/concurrency/link-checker.md:33 msgid "" -"/// Call the birthday service.\n" -"fn main() -> Result<(), binder::Status> {\n" -" let name = std::env::args()\n" -" .nth(1)\n" -" .unwrap_or_else(|| String::from(\"Bob\"));\n" -" let years = std::env::args()\n" -" .nth(2)\n" -" .and_then(|arg| arg.parse::().ok())\n" -" .unwrap_or(42);" +"The `cargo add` calls will update the `Cargo.toml` file to look like this:" msgstr "" -#: src/android/aidl/client.md:29 +#: src/exercises/concurrency/link-checker.md:37 msgid "" -" binder::ProcessState::start_thread_pool();\n" -" let service = connect().expect(\"Failed to connect to " -"BirthdayService\");\n" -" let msg = service.wishHappyBirthday(&name, years)?;\n" -" println!(\"{msg}\");\n" -" Ok(())\n" -"}\n" +"```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/android/aidl/client.md:39 +#: src/exercises/concurrency/link-checker.md:50 msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"birthday_client\",\n" -" crate_name: \"birthday_client\",\n" -" srcs: [\"src/client.rs\"],\n" -" rustlibs: [\n" -" \"com.example.birthdayservice-rust\",\n" -" \"libbinder_rs\",\n" -" ],\n" -" prefer_rlib: true,\n" -"}\n" -"```" +"You can now download the start page. Try with a small site such as\n" +"`https://www.google.org/`." msgstr "" -#: src/android/aidl/client.md:52 -msgid "Notice that the client does not depend on `libbirthdayservice`." +#: src/exercises/concurrency/link-checker.md:53 +msgid "Your `src/main.rs` file should look something like this:" msgstr "" -#: src/android/aidl/client.md:54 -msgid "Build, push, and run the client on your device:" +#: 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/android/aidl/client.md:56 +#: src/exercises/concurrency/link-checker.md:100 +msgid "Run the code in `src/main.rs` with" +msgstr "" + +#: src/exercises/concurrency/link-checker.md:102 msgid "" "```shell\n" -"$ m birthday_client\n" -"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp\n" -"$ adb shell /data/local/tmp/birthday_client Charlie 60\n" -"Happy Birthday Charlie, congratulations with the 60 years!\n" +"$ cargo run\n" "```" msgstr "" -#: src/android/aidl/changing.md:1 -msgid "# Changing API" +#: src/exercises/concurrency/link-checker.md:106 +msgid "## Tasks" msgstr "" -#: src/android/aidl/changing.md:3 +#: src/exercises/concurrency/link-checker.md:108 msgid "" -"Let us extend the API with more functionality: we want to let clients " -"specify a\n" -"list of lines for the birthday card:" +"* 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 "" -#: src/android/aidl/changing.md:9 -msgid "" -"/** Birthday service interface. */\n" -"interface IBirthdayService {\n" -" /** Generate a Happy Birthday message. */\n" -" String wishHappyBirthday(String name, int years, in String[] text);\n" -"}\n" -"```" +#: src/async.md:1 +msgid "# Async Rust" msgstr "" -#: src/android/logging.md:1 -msgid "# Logging" +#: 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/android/logging.md:3 +#: src/async.md:10 msgid "" -"You should use the `log` crate to automatically log to `logcat` (on-device) " -"or\n" -"`stdout` (on-host):" +"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/android/logging.md:6 -msgid "_hello_rust_logs/Android.bp_:" +#: src/async.md:14 +msgid "" +"Futures are polled by an async runtime, and several different runtimes are\n" +"available." msgstr "" -#: src/android/logging.md:8 +#: src/async.md:17 +#, fuzzy +msgid "## Comparisons" +msgstr "Sammenligning" + +#: src/async.md:19 msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"hello_rust_logs\",\n" -" crate_name: \"hello_rust_logs\",\n" -" srcs: [\"src/main.rs\"],\n" -" rustlibs: [\n" -" \"liblog_rust\",\n" -" \"liblogger\",\n" -" ],\n" -" prefer_rlib: true,\n" -" host_supported: true,\n" -"}\n" -"```" +" * 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/android/logging.md:22 -msgid "_hello_rust_logs/src/main.rs_:" +#: src/async/async-await.md:1 +msgid "# `async`/`await`" msgstr "" -#: src/android/logging.md:24 +#: src/async/async-await.md:3 msgid "" -"```rust,ignore\n" -"//! Rust logging demo." -msgstr "" - -#: src/android/logging.md:27 -msgid "use log::{debug, error};" +"At a high level, async Rust code looks very much like \"normal\" sequential " +"code:" msgstr "" -#: src/android/logging.md:29 +#: src/async/async-await.md:5 msgid "" -"/// Logs a greeting.\n" +"```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" -" logger::init(\n" -" logger::Config::default()\n" -" .with_tag_on_device(\"rust\")\n" -" .with_min_level(log::Level::Trace),\n" -" );\n" -" debug!(\"Starting program.\");\n" -" error!(\"Something went wrong!\");\n" +" block_on(async_main(10));\n" "}\n" "```" msgstr "" -#: src/android/logging.md:41 src/android/interoperability/with-c/bindgen.md:98 -#: src/android/interoperability/with-c/rust.md:73 -msgid "Build, push, and run the binary on your device:" +#: 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 +msgid "# Futures" msgstr "" -#: src/android/logging.md:43 +#: src/async/futures.md:3 msgid "" -"```shell\n" -"$ m hello_rust_logs\n" -"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/tmp\n" -"$ adb shell /data/local/tmp/hello_rust_logs\n" +"[`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/android/logging.md:49 -msgid "The logs show up in `adb logcat`:" +#: 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/android/logging.md:51 +#: src/async/futures.md:32 msgid "" -"```shell\n" -"$ adb logcat -s rust\n" -"09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.\n" -"09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going " -"fine.\n" -"09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went " -"wrong!\n" -"```" +"* 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/android/interoperability.md:1 -msgid "# Interoperability" +#: src/async/runtimes.md:1 +msgid "# Runtimes" msgstr "" -#: src/android/interoperability.md:3 +#: src/async/runtimes.md:3 msgid "" -"Rust has excellent support for interoperability with other languages. This " -"means\n" -"that you can:" +"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/android/interoperability.md:6 +#: src/async/runtimes.md:7 msgid "" -"* Call Rust functions from other languages.\n" -"* Call functions written in other languages from Rust." +" * [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/android/interoperability.md:9 +#: src/async/runtimes.md:14 msgid "" -"When you call functions in a foreign language we say that you're using a\n" -"_foreign function interface_, also known as FFI." +"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/android/interoperability/with-c.md:1 -msgid "# Interoperability with C" +#: 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/android/interoperability/with-c.md:3 -msgid "" -"Rust has full support for linking object files with a C calling convention.\n" -"Similarly, you can export Rust functions and call them from C." +#: src/async/runtimes/tokio.md:1 +msgid "# Tokio" msgstr "" -#: src/android/interoperability/with-c.md:6 -msgid "You can do it by hand if you want:" +#: src/async/runtimes/tokio.md:4 +msgid "Tokio provides: " msgstr "" -#: src/android/interoperability/with-c.md:8 +#: src/async/runtimes/tokio.md:6 msgid "" -"```rust\n" -"extern \"C\" {\n" -" fn abs(x: i32) -> i32;\n" -"}" +"* A multi-threaded runtime for executing asynchronous code.\n" +"* An asynchronous version of the standard library.\n" +"* A large ecosystem of libraries." msgstr "" -#: src/android/interoperability/with-c.md:13 +#: src/async/runtimes/tokio.md:10 msgid "" -"fn main() {\n" -" let x = -42;\n" -" let abs_x = unsafe { abs(x) };\n" -" println!(\"{x}, {abs_x}\");\n" +"```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/android/interoperability/with-c.md:20 +#: src/async/runtimes/tokio.md:33 msgid "" -"We already saw this in the [Safe FFI Wrapper\n" -"exercise](../../exercises/day-3/safe-ffi-wrapper.md)." +"* 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/android/interoperability/with-c.md:23 -msgid "" -"> This assumes full knowledge of the target platform. Not recommended for\n" -"> production." +#: src/async/runtimes/tokio.md:39 +msgid "**Further exploration:**" msgstr "" -#: src/android/interoperability/with-c.md:26 -msgid "We will look at better options next." +#: 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/android/interoperability/with-c/bindgen.md:1 -msgid "# Using Bindgen" +#: src/async/tasks.md:1 +msgid "# Tasks" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:3 +#: src/async/tasks.md:3 msgid "" -"The [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html) " -"tool\n" -"can auto-generate bindings from a C header file." +"Runtimes have the concept of a \"task\", similar to a thread but much\n" +"less resource-intensive." msgstr "" -#: src/android/interoperability/with-c/bindgen.md:6 -msgid "First create a small C library:" +#: 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/android/interoperability/with-c/bindgen.md:8 -msgid "_interoperability/bindgen/libbirthday.h_:" +#: 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/android/interoperability/with-c/bindgen.md:10 +#: src/async/tasks.md:53 src/async/control-flow/join.md:36 msgid "" -"```c\n" -"typedef struct card {\n" -" const char* name;\n" -" int years;\n" -"} card;" +"Copy this example into your prepared `src/main.rs` and run it from there." msgstr "" -#: src/android/interoperability/with-c/bindgen.md:16 +#: src/async/tasks.md:55 msgid "" -"void print_card(const card* card);\n" -"```" +"* 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/android/interoperability/with-c/bindgen.md:19 -msgid "_interoperability/bindgen/libbirthday.c_:" +#: src/async/channels.md:1 +msgid "# Async Channels" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:21 +#: src/async/channels.md:3 msgid "" -"```c\n" -"#include \n" -"#include \"libbirthday.h\"" +"Several crates have support for `async`/`await`. For instance `tokio` " +"channels:" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:25 +#: src/async/channels.md:5 msgid "" -"void print_card(const card* card) {\n" -" printf(\"+--------------\\n\");\n" -" printf(\"| Happy Birthday %s!\\n\", card->name);\n" -" printf(\"| Congratulations with the %i years!\\n\", card->years);\n" -" printf(\"+--------------\\n\");\n" +"```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/android/interoperability/with-c/bindgen.md:33 -msgid "Add this to your `Android.bp` file:" +#: 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/android/interoperability/with-c/bindgen.md:35 -#: src/android/interoperability/with-c/bindgen.md:55 -#: src/android/interoperability/with-c/bindgen.md:69 -#: src/android/interoperability/with-c/bindgen.md:108 -msgid "_interoperability/bindgen/Android.bp_:" +#: src/async/control-flow.md:1 +msgid "# Futures Control Flow" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:37 +#: src/async/control-flow.md:3 msgid "" -"```javascript\n" -"cc_library {\n" -" name: \"libbirthday\",\n" -" srcs: [\"libbirthday.c\"],\n" -"}\n" -"```" +"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/android/interoperability/with-c/bindgen.md:44 +#: src/async/control-flow.md:6 msgid "" -"Create a wrapper header file for the library (not strictly needed in this\n" -"example):" +"- [Join](control-flow/join.md)\n" +"- [Select](control-flow/select.md)" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:47 -msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" +#: src/async/control-flow/join.md:1 +msgid "# Join" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:49 +#: src/async/control-flow/join.md:3 msgid "" -"```c\n" -"#include \"libbirthday.h\"\n" -"```" -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:53 -msgid "You can now auto-generate the bindings:" +"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/android/interoperability/with-c/bindgen.md:57 +#: src/async/control-flow/join.md:7 msgid "" -"```javascript\n" -"rust_bindgen {\n" -" name: \"libbirthday_bindgen\",\n" -" crate_name: \"birthday_bindgen\",\n" -" wrapper_src: \"libbirthday_wrapper.h\",\n" -" source_stem: \"bindings\",\n" -" static_libs: [\"libbirthday\"],\n" +"```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/android/interoperability/with-c/bindgen.md:67 -msgid "Finally, we can use the bindings in our Rust program:" -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:71 +#: src/async/control-flow/join.md:38 msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"print_birthday_card\",\n" -" srcs: [\"main.rs\"],\n" -" rustlibs: [\"libbirthday_bindgen\"],\n" -"}\n" -"```" +"* 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/android/interoperability/with-c/bindgen.md:79 -msgid "_interoperability/bindgen/main.rs_:" +#: src/async/control-flow/select.md:1 +msgid "# Select" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:81 +#: src/async/control-flow/select.md:3 msgid "" -"```rust,compile_fail\n" -"//! Bindgen demo." +"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/android/interoperability/with-c/bindgen.md:84 -msgid "use birthday_bindgen::{card, print_card};" +#: 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/android/interoperability/with-c/bindgen.md:86 +#: src/async/control-flow/select.md:12 msgid "" -"fn main() {\n" -" let name = std::ffi::CString::new(\"Peter\").unwrap();\n" -" let card = card {\n" -" name: name.as_ptr(),\n" -" years: 42,\n" -" };\n" -" unsafe {\n" -" print_card(&card as *const card);\n" +"```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/android/interoperability/with-c/bindgen.md:100 +#: src/async/control-flow/select.md:61 msgid "" -"```shell\n" -"$ m print_birthday_card\n" -"$ adb push $ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/" -"tmp\n" -"$ adb shell /data/local/tmp/print_birthday_card\n" -"```" +"* 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/android/interoperability/with-c/bindgen.md:106 -msgid "Finally, we can run auto-generated tests to ensure the bindings work:" +#: src/async/pitfalls.md:1 +msgid "# Pitfalls of async/await" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:110 +#: src/async/pitfalls.md:3 msgid "" -"```javascript\n" -"rust_test {\n" -" name: \"libbirthday_bindgen_test\",\n" -" srcs: [\":libbirthday_bindgen\"],\n" -" crate_name: \"libbirthday_bindgen_test\",\n" -" test_suites: [\"general-tests\"],\n" -" auto_gen_config: true,\n" -" clippy_lints: \"none\", // Generated file, skip linting\n" -" lints: \"none\",\n" -"}\n" -"```" +"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/android/interoperability/with-c/bindgen.md:122 +#: src/async/pitfalls.md:5 msgid "" -"```shell\n" -"$ atest libbirthday_bindgen_test\n" -"```" +"- [Blocking the Executor](pitfalls/blocking-executor.md)\n" +"- [Pin](pitfalls/pin.md)\n" +"- [Async Traits](pitfall/async-traits.md)" msgstr "" -#: src/android/interoperability/with-c/rust.md:1 -msgid "# Calling Rust" +#: src/async/pitfalls/blocking-executor.md:1 +msgid "# Blocking the executor" msgstr "" -#: src/android/interoperability/with-c/rust.md:3 -msgid "Exporting Rust functions and types to C is easy:" +#: 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/android/interoperability/with-c/rust.md:5 -msgid "_interoperability/rust/libanalyze/analyze.rs_" +#: 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/android/interoperability/with-c/rust.md:7 +#: 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 "" -"```rust,editable\n" -"//! Rust FFI demo.\n" -"#![deny(improper_ctypes_definitions)]" +"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/android/interoperability/with-c/rust.md:11 -msgid "use std::os::raw::c_int;" +#: 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/android/interoperability/with-c/rust.md:13 +#: src/async/pitfalls/pin.md:12 msgid "" -"/// Analyze the numbers.\n" -"#[no_mangle]\n" -"pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" -" if x < y {\n" -" println!(\"x ({x}) is smallest!\");\n" -" } else {\n" -" println!(\"y ({y}) is probably larger than x ({x})\");\n" +"```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/android/interoperability/with-c/rust.md:24 -msgid "_interoperability/rust/libanalyze/analyze.h_" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:26 -msgid "" -"```c\n" -"#ifndef ANALYSE_H\n" -"#define ANALYSE_H" +#: 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/android/interoperability/with-c/rust.md:30 -msgid "" -"extern \"C\" {\n" -"void analyze_numbers(int x, int y);\n" -"}" +#: src/async/pitfalls/async-traits.md:1 +msgid "# Async Traits" msgstr "" -#: src/android/interoperability/with-c/rust.md:34 +#: src/async/pitfalls/async-traits.md:3 msgid "" -"#endif\n" -"```" +"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/android/interoperability/with-c/rust.md:37 -msgid "_interoperability/rust/libanalyze/Android.bp_" +#: 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/android/interoperability/with-c/rust.md:39 +#: src/async/pitfalls/async-traits.md:7 msgid "" -"```javascript\n" -"rust_ffi {\n" -" name: \"libanalyze_ffi\",\n" -" crate_name: \"analyze_ffi\",\n" -" srcs: [\"analyze.rs\"],\n" -" include_dirs: [\".\"],\n" +"```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/android/interoperability/with-c/rust.md:48 -msgid "We can now call this from a C binary:" +#: src/async/pitfalls/async-traits.md:49 +msgid "
" msgstr "" -#: src/android/interoperability/with-c/rust.md:50 -msgid "_interoperability/rust/analyze/main.c_" +#: 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/android/interoperability/with-c/rust.md:52 +#: src/exercises/concurrency/afternoon.md:3 msgid "" -"```c\n" -"#include \"analyze.h\"" +"To practice your Async Rust skills, we have again two exercises for you:" msgstr "" -#: src/android/interoperability/with-c/rust.md:55 +#: src/exercises/concurrency/afternoon.md:5 msgid "" -"int main() {\n" -" analyze_numbers(10, 20);\n" -" analyze_numbers(123, 123);\n" -" return 0;\n" -"}\n" -"```" +"* Dining philosophers: we already saw this problem in the morning. This " +"time\n" +" you are going to implement it with Async Rust.\n" +"\n" +"* The Elevator Problem: this is a larger project that allows you experiment\n" +" with more advanced Async Rust features and some of its pitfalls!" msgstr "" -#: src/android/interoperability/with-c/rust.md:62 -msgid "_interoperability/rust/analyze/Android.bp_" +#: src/exercises/concurrency/dining-philosophers-async.md:1 +msgid "# Dining Philosophers - Async" msgstr "" -#: src/android/interoperability/with-c/rust.md:64 +#: src/exercises/concurrency/dining-philosophers-async.md:3 msgid "" -"```javascript\n" -"cc_binary {\n" -" name: \"analyze_numbers\",\n" -" srcs: [\"main.c\"],\n" -" static_libs: [\"libanalyze_ffi\"],\n" -"}\n" -"```" +"See [dining philosophers](dining-philosophers.md) for a description of the\n" +"problem." msgstr "" -#: src/android/interoperability/with-c/rust.md:75 +#: src/exercises/concurrency/dining-philosophers-async.md:6 msgid "" -"```shell\n" -"$ m analyze_numbers\n" -"$ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp\n" -"$ adb shell /data/local/tmp/analyze_numbers\n" -"```" -msgstr "" - -#: src/android/interoperability/cpp.md:1 -msgid "# With C++" +"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 "" -#: src/android/interoperability/cpp.md:3 +#: src/exercises/concurrency/dining-philosophers-async.md:13 msgid "" -"The [CXX crate][1] makes it possible to do safe interoperability between " -"Rust\n" -"and C++." -msgstr "" - -#: src/android/interoperability/cpp.md:6 -msgid "The overall approach looks like this:" +"```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/android/interoperability/cpp.md:8 -msgid "" +#: 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/android/interoperability/cpp.md:10 -msgid "See the [CXX tutorial][2] for an full example of using this." +#: 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/android/interoperability/cpp.md:12 +#: src/exercises/concurrency/dining-philosophers-async.md:72 msgid "" -"[1]: https://cxx.rs/\n" -"[2]: https://cxx.rs/tutorial.html" +"Also note that this time you have to use the `Mutex` and the `mpsc` module\n" +"from the `tokio` crate." msgstr "" -#: src/android/interoperability/java.md:1 -msgid "# Interoperability with Java" +#: src/exercises/concurrency/dining-philosophers-async.md:77 +msgid "* Can you make your implementation single-threaded? " msgstr "" -#: src/android/interoperability/java.md:3 -msgid "" -"Java can load shared objects via [Java Native Interface\n" -"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). The [`jni`\n" -"crate](https://docs.rs/jni/) allows you to create a compatible library." +#: src/exercises/concurrency/elevator.md:1 +msgid "# Elevator Operation" msgstr "" -#: src/android/interoperability/java.md:7 -msgid "First, we create a Rust function to export to Java:" +#: src/exercises/concurrency/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/android/interoperability/java.md:9 -msgid "_interoperability/java/src/lib.rs_:" +#: src/exercises/concurrency/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/android/interoperability/java.md:11 -msgid "" -"```rust,compile_fail\n" -"//! Rust <-> Java FFI demo." +#: src/exercises/concurrency/elevator.md:12 +msgid "## Getting Started" msgstr "" -#: src/android/interoperability/java.md:14 +#: src/exercises/concurrency/elevator.md:14 msgid "" -"use jni::objects::{JClass, JString};\n" -"use jni::sys::jstring;\n" -"use jni::JNIEnv;" +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and " +"look in the `elevator`\n" +"directory for the following files." msgstr "" -#: src/android/interoperability/java.md:18 +#: src/exercises/concurrency/elevator.md:21 msgid "" -"/// HelloWorld::hello method implementation.\n" -"#[no_mangle]\n" -"pub extern \"system\" fn Java_HelloWorld_hello(\n" -" env: JNIEnv,\n" -" _class: JClass,\n" -" name: JString,\n" -") -> jstring {\n" -" let input: String = env.get_string(name).unwrap().into();\n" -" let greeting = format!(\"Hello, {input}!\");\n" -" let output = env.new_string(greeting).unwrap();\n" -" output.into_inner()\n" +"```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/android/interoperability/java.md:32 -#: src/android/interoperability/java.md:62 -msgid "_interoperability/java/Android.bp_:" +#: src/exercises/concurrency/elevator.md:47 +msgid "`src/building.rs`:" msgstr "" -#: src/android/interoperability/java.md:34 +#: src/exercises/concurrency/elevator.md:49 +msgid "" +msgstr "" + +#: src/exercises/concurrency/elevator.md:51 msgid "" -"```javascript\n" -"rust_ffi_shared {\n" -" name: \"libhello_jni\",\n" -" crate_name: \"hello_jni\",\n" -" srcs: [\"src/lib.rs\"],\n" -" rustlibs: [\"libjni\"],\n" +"```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/android/interoperability/java.md:43 -msgid "Finally, we can call this function from Java:" +#: src/exercises/concurrency/elevator.md:288 +msgid "`src/driver.rs`:" msgstr "" -#: src/android/interoperability/java.md:45 -msgid "_interoperability/java/HelloWorld.java_:" +#: src/exercises/concurrency/elevator.md:290 +msgid "" msgstr "" -#: src/android/interoperability/java.md:47 +#: src/exercises/concurrency/elevator.md:292 msgid "" -"```java\n" -"class HelloWorld {\n" -" private static native String hello(String name);" +"```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/android/interoperability/java.md:51 -msgid "" -" static {\n" -" System.loadLibrary(\"hello_jni\");\n" -" }" +#: src/exercises/concurrency/elevator.md:330 +msgid "`src/controller.rs`:" +msgstr "" + +#: src/exercises/concurrency/elevator.md:332 +msgid "" msgstr "" -#: src/android/interoperability/java.md:55 +#: src/exercises/concurrency/elevator.md:334 msgid "" -" public static void main(String[] args) {\n" -" String output = HelloWorld.hello(\"Alice\");\n" -" System.out.println(output);\n" +"```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/android/interoperability/java.md:64 +#: src/exercises/concurrency/elevator.md:369 msgid "" -"```javascript\n" -"java_binary {\n" -" name: \"helloworld_jni\",\n" -" srcs: [\"HelloWorld.java\"],\n" -" main_class: \"HelloWorld\",\n" -" required: [\"libhello_jni\"],\n" -"}\n" +"```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/android/interoperability/java.md:73 -msgid "Finally, you can build, sync, and run the binary:" +#: src/exercises/concurrency/elevator.md:381 +msgid "Use `cargo run` to run the elevator simulation." msgstr "" -#: src/android/interoperability/java.md:75 -msgid "" -"```shell\n" -"$ m helloworld_jni\n" -"$ adb sync # requires adb root && adb remount\n" -"$ adb shell /system/bin/helloworld_jni\n" -"```" -msgstr "" +#: src/exercises/concurrency/elevator.md:383 +#, fuzzy +msgid "## Exercises" +msgstr "Øvelser" -#: src/exercises/day-4/afternoon.md:3 +#: src/exercises/concurrency/elevator.md:385 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:" -msgstr "" - -#: src/exercises/day-4/afternoon.md:6 -msgid "* Call your AIDL service with a client written in Rust." +"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/afternoon.md:8 -msgid "* Move a function from your project to Rust and call it." +#: src/exercises/concurrency/elevator.md:389 +msgid "" +"Once you have this done, make the problem more complex. Suggested tasks:" msgstr "" -#: src/exercises/day-4/afternoon.md:12 +#: src/exercises/concurrency/elevator.md:391 msgid "" -"No solution is provided here since this is open-ended: it relies on someone " -"in\n" -"the class having a piece of code which you can turn in to Rust on the fly." +" * 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 @@ -10734,10 +16712,14 @@ msgid "" " 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." +"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 "" -#: src/other-resources.md:59 +#: src/other-resources.md:63 msgid "" "Please see the [Little Book of Rust Books](https://lborb.github.io/book/) " "for\n" @@ -10761,7 +16743,7 @@ msgstr "" msgid "" "The material of Comprehensive Rust is licensed under the terms of the Apache " "2.0\n" -"license, please see [`LICENSE.txt`](../LICENSE.txt) for details." +"license, please see [`LICENSE`](../LICENSE) for details." msgstr "" #: src/credits.md:10 @@ -10838,13 +16820,6 @@ msgid "([back to exercise](for-loops.md))" msgstr "" #: src/exercises/day-1/solutions-morning.md:7 -#: src/exercises/day-1/solutions-afternoon.md:7 -#: src/exercises/day-2/solutions-morning.md:7 -#: src/exercises/day-2/solutions-afternoon.md:7 -#: src/exercises/day-2/solutions-afternoon.md:102 -#: src/exercises/day-3/solutions-morning.md:7 -#: src/exercises/day-3/solutions-afternoon.md:7 -#: src/exercises/day-4/solutions-morning.md:7 msgid "" "```rust\n" "// Copyright 2022 Google LLC\n" @@ -10858,26 +16833,9 @@ msgid "" "// 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." -msgstr "" -"```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." - -#: src/exercises/day-1/solutions-morning.md:22 -msgid "" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: transpose\n" "fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" " // ANCHOR_END: transpose\n" @@ -10888,22 +16846,16 @@ msgid "" " }\n" " }\n" " return result;\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:34 -msgid "" +"}\n" +"\n" "// ANCHOR: pretty_print\n" "fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" " // ANCHOR_END: pretty_print\n" " for row in matrix {\n" " println!(\"{row:?}\");\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:42 -msgid "" +"}\n" +"\n" "// ANCHOR: tests\n" "#[test]\n" "fn test_transpose() {\n" @@ -10922,34 +16874,34 @@ msgid "" " ]\n" " );\n" "}\n" -"// ANCHOR_END: tests" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:62 -msgid "" +"// ANCHOR_END: tests\n" +"\n" "// ANCHOR: main\n" "fn main() {\n" " let matrix = [\n" " [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" " [201, 202, 203],\n" " [301, 302, 303],\n" -" ];" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:73 -msgid "" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" " let transposed = transpose(matrix);\n" " println!(\"transposed:\");\n" " pretty_print(&transposed);\n" "}\n" -"```\n" -"### Bonus question" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:78 +msgid "### Bonus question" msgstr "" #: src/exercises/day-1/solutions-morning.md:80 msgid "" -"It honestly doesn't work so well. It might seem that we could use a slice-of-" -"slices (`&[&[i32]]`) as the input type to transpose and thus make our " +"It requires more advanced concepts. It might seem that we could use a slice-" +"of-slices (`&[&[i32]]`) as the input type to transpose and thus make our " "function handle any size of matrix. However, this quickly breaks down: the " "return type cannot be `&[&[i32]]` since it needs to own the data you return." msgstr "" @@ -10957,8 +16909,50 @@ msgstr "" #: src/exercises/day-1/solutions-morning.md:82 msgid "" "You can attempt to use something like `Vec>`, but this doesn't work " -"very well either: it's hard to convert from `Vec>` to `&[&[i32]]` " -"so now you cannot easily use `pretty_print` either." +"out-of-the-box either: it's hard to convert from `Vec>` to " +"`&[&[i32]]` so now you cannot easily use `pretty_print` either." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:84 +msgid "" +"Once we get to traits and generics, we'll be able to use the [`std::convert::" +"AsRef`][1] trait to abstract over anything that can be referenced as a slice." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:86 +msgid "" +"```rust\n" +"use std::convert::AsRef;\n" +"use std::fmt::Debug;\n" +"\n" +"fn pretty_print(matrix: Matrix)\n" +"where\n" +" T: Debug,\n" +" // A line references a slice of items\n" +" Line: AsRef<[T]>,\n" +" // A matrix references a slice of lines\n" +" Matrix: AsRef<[Line]>\n" +"{\n" +" for row in matrix.as_ref() {\n" +" println!(\"{:?}\", row.as_ref());\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" // &[&[i32]]\n" +" pretty_print(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" +" // [[&str; 2]; 2]\n" +" pretty_print([[\"a\", \"b\"], [\"c\", \"d\"]]);\n" +" // Vec>\n" +" pretty_print(vec![vec![1, 2], vec![3, 4]]);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:113 +msgid "" +"In addition, the type itself would not enforce that the child slices are of " +"the same length, so such variable could contain an invalid matrix." msgstr "" #: src/exercises/day-1/solutions-afternoon.md:1 @@ -10973,165 +16967,169 @@ msgstr "" msgid "([back to exercise](book-library.md))" msgstr "" -#: src/exercises/day-1/solutions-afternoon.md:22 +#: src/exercises/day-1/solutions-afternoon.md:7 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: setup\n" "struct Library {\n" " books: Vec,\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:42 -msgid "" -"// 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" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" " }\n" "}\n" -"// ANCHOR_END: setup" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:50 -msgid "" -"// ANCHOR: Library_new\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" +" // ANCHOR_END: setup\n" +"\n" +" // ANCHOR: Library_new\n" " fn new() -> Library {\n" " // ANCHOR_END: Library_new\n" " Library { books: Vec::new() }\n" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:57 -msgid "" +" }\n" +"\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" " self.books.len()\n" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:66 -msgid "" +" }\n" +"\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" " self.books.is_empty()\n" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:75 -msgid "" +" }\n" +"\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" " self.books.push(book)\n" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:84 -msgid "" +" }\n" +"\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" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:95 -msgid "" +" }\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" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:105 -msgid "" +"}\n" +"\n" "// ANCHOR: main\n" "// This shows the desired behavior. Uncomment the code below and\n" "// implement the missing methods. You will need to update the\n" "// method signatures, including the \"self\" parameter! You may\n" "// also need to update the variable bindings within main.\n" "fn main() {\n" -" let library = Library::new();" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:113 -msgid "" -" //println!(\"Our library is empty: {}\", library.is_empty());\n" +" let library = Library::new();\n" +"\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" +" //println!(\"The library has {} books\", library.len());\n" +" //library.print_books();\n" "}\n" -"// ANCHOR_END: main" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:129 -msgid "" +"// ANCHOR_END: main\n" +"\n" "#[test]\n" "fn test_library_len() {\n" " let mut library = Library::new();\n" " assert_eq!(library.len(), 0);\n" -" assert!(library.is_empty());" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:135 -msgid "" +" assert!(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" " assert_eq!(library.len(), 2);\n" " assert!(!library.is_empty());\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:141 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_library_is_empty() {\n" " let mut library = Library::new();\n" -" assert!(library.is_empty());" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:146 -msgid "" +" assert!(library.is_empty());\n" +"\n" " library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" " assert!(!library.is_empty());\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:150 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_library_print_books() {\n" " let mut library = Library::new();\n" @@ -11141,28 +17139,19 @@ msgid "" " // We could try and capture stdout, but let us just call the\n" " // method to start with.\n" " library.print_books();\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:160 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_library_oldest_book() {\n" " let mut library = Library::new();\n" -" assert!(library.oldest_book().is_none());" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:165 -msgid "" +" assert!(library.oldest_book().is_none());\n" +"\n" " library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" " assert_eq!(\n" " library.oldest_book().map(|b| b.title.as_str()),\n" " Some(\"Lord of the Rings\")\n" -" );" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:171 -msgid "" +" );\n" +"\n" " library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " "1865));\n" " assert_eq!(\n" @@ -11185,120 +17174,99 @@ msgstr "" msgid "([back to exercise](points-polygons.md))" msgstr "" -#: src/exercises/day-2/solutions-morning.md:22 +#: src/exercises/day-2/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" "#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" "// ANCHOR: Point\n" "pub struct Point {\n" " // ANCHOR_END: Point\n" " x: i32,\n" " y: i32,\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:30 -msgid "" +"}\n" +"\n" "// ANCHOR: Point-impl\n" "impl Point {\n" " // ANCHOR_END: Point-impl\n" " pub fn new(x: i32, y: i32) -> Point {\n" " Point { x, y }\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:37 -msgid "" +" }\n" +"\n" " pub fn magnitude(self) -> f64 {\n" " f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:41 -msgid "" +" }\n" +"\n" " pub fn dist(self, other: Point) -> f64 {\n" " (self - other).magnitude()\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:49 -msgid "" +"}\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" " fn add(self, other: Self) -> Self::Output {\n" " Self {\n" " x: self.x + other.x,\n" " y: self.y + other.y,\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:57 -msgid "" +"}\n" +"\n" "impl std::ops::Sub for Point {\n" -" type Output = Self;" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:60 -msgid "" +" type Output = Self;\n" +"\n" " fn sub(self, other: Self) -> Self::Output {\n" " Self {\n" " x: self.x - other.x,\n" " y: self.y - other.y,\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:68 -msgid "" +"}\n" +"\n" "// ANCHOR: Polygon\n" "pub struct Polygon {\n" " // ANCHOR_END: Polygon\n" " points: Vec,\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:74 -msgid "" +"}\n" +"\n" "// ANCHOR: Polygon-impl\n" "impl Polygon {\n" " // ANCHOR_END: Polygon-impl\n" " pub fn new() -> Polygon {\n" " Polygon { points: Vec::new() }\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:81 -msgid "" +" }\n" +"\n" " pub fn add_point(&mut self, point: Point) {\n" " self.points.push(point);\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:85 -msgid "" +" }\n" +"\n" " pub fn left_most_point(&self) -> Option {\n" " self.points.iter().min_by_key(|p| p.x).copied()\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:89 -msgid "" +" }\n" +"\n" " pub fn iter(&self) -> impl Iterator {\n" " self.points.iter()\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:93 -msgid "" +" }\n" +"\n" " pub fn length(&self) -> f64 {\n" " if self.points.is_empty() {\n" " return 0.0;\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:98 -msgid "" +" }\n" +"\n" " let mut result = 0.0;\n" " let mut last_point = self.points[0];\n" " for point in &self.points[1..] {\n" @@ -11308,96 +17276,114 @@ msgid "" " result += last_point.dist(self.points[0]);\n" " result\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:109 -msgid "" +"}\n" +"\n" "// ANCHOR: Circle\n" "pub struct Circle {\n" " // ANCHOR_END: Circle\n" " center: Point,\n" " radius: i32,\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:116 -msgid "" +"}\n" +"\n" "// ANCHOR: Circle-impl\n" "impl Circle {\n" " // ANCHOR_END: Circle-impl\n" " pub fn new(center: Point, radius: i32) -> Circle {\n" " Circle { center, radius }\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:123 -msgid "" +" }\n" +"\n" " pub fn circumference(&self) -> f64 {\n" " 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:127 -msgid "" +" }\n" +"\n" " pub fn dist(&self, other: &Self) -> f64 {\n" " self.center.dist(other.center)\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:132 -msgid "" +"}\n" +"\n" "// ANCHOR: Shape\n" "pub enum Shape {\n" " Polygon(Polygon),\n" " Circle(Circle),\n" "}\n" -"// ANCHOR_END: Shape" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:139 -msgid "" +"// ANCHOR_END: Shape\n" +"\n" "impl From for Shape {\n" " fn from(poly: Polygon) -> Self {\n" " Shape::Polygon(poly)\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:145 -msgid "" +"}\n" +"\n" "impl From for Shape {\n" " fn from(circle: Circle) -> Self {\n" " Shape::Circle(circle)\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:151 -msgid "" +"}\n" +"\n" "impl Shape {\n" -" pub fn circumference(&self) -> f64 {\n" +" pub fn perimeter(&self) -> f64 {\n" " match self {\n" " Shape::Polygon(poly) => poly.length(),\n" " Shape::Circle(circle) => circle.circumference(),\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:160 -msgid "" -"// ANCHOR: unit-tests\n" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:213 -msgid "" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" " #[test]\n" -" fn test_shape_circumferences() {\n" +" fn test_shape_perimeters() {\n" " let mut poly = Polygon::new();\n" " poly.add_point(Point::new(12, 13));\n" " poly.add_point(Point::new(17, 11));\n" @@ -11406,15 +17392,18 @@ msgid "" " Shape::from(poly),\n" " Shape::from(Circle::new(Point::new(10, 20), 5)),\n" " ];\n" -" let circumferences = shapes\n" +" let perimeters = shapes\n" " .iter()\n" -" .map(Shape::circumference)\n" +" .map(Shape::perimeter)\n" " .map(round_two_digits)\n" " .collect::>();\n" -" assert_eq!(circumferences, vec![15.48, 31.42]);\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" " }\n" "}\n" -"// ANCHOR_END: unit-tests" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" msgstr "" #: src/exercises/day-2/solutions-afternoon.md:1 @@ -11429,8 +17418,23 @@ msgstr "" msgid "([back to exercise](luhn.md))" msgstr "" -#: src/exercises/day-2/solutions-afternoon.md:22 +#: src/exercises/day-2/solutions-afternoon.md:7 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: luhn\n" "pub fn luhn(cc_number: &str) -> bool {\n" " // ANCHOR_END: luhn\n" @@ -11450,45 +17454,54 @@ msgid "" " }\n" " None => return false,\n" " }\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:42 -msgid "" +" }\n" +"\n" " if digits_seen < 2 {\n" " return false;\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:46 -msgid "" +" }\n" +"\n" " sum % 10 == 0\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:49 -msgid "" +"}\n" +"\n" "fn main() {\n" " let cc_number = \"1234 5678 1234 5670\";\n" " println!(\n" -" \"Is {} a valid credit card number? {}\",\n" -" cc_number,\n" +" \"Is {cc_number} a valid credit card number? {}\",\n" " if luhn(cc_number) { \"yes\" } else { \"no\" }\n" " );\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:58 -msgid "" +"}\n" +"\n" "// ANCHOR: unit-tests\n" "#[test]\n" "fn test_non_digit_cc_number() {\n" " assert!(!luhn(\"foo\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:89 -msgid "" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" "#[test]\n" "fn test_invalid_cc_number() {\n" " assert!(!luhn(\"4223 9826 4026 9299\"));\n" @@ -11499,16 +17512,31 @@ msgid "" "```" msgstr "" -#: src/exercises/day-2/solutions-afternoon.md:98 +#: src/exercises/day-2/solutions-afternoon.md:97 msgid "## Strings and Iterators" msgstr "" -#: src/exercises/day-2/solutions-afternoon.md:100 +#: src/exercises/day-2/solutions-afternoon.md:99 msgid "([back to exercise](strings-iterators.md))" msgstr "" -#: src/exercises/day-2/solutions-afternoon.md:117 +#: src/exercises/day-2/solutions-afternoon.md:101 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: prefix_matches\n" "pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" " // ANCHOR_END: prefix_matches\n" @@ -11516,11 +17544,8 @@ msgid "" " let request_paths = request_path\n" " .split('/')\n" " .map(|p| Some(p))\n" -" .chain(std::iter::once(None));" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:126 -msgid "" +" .chain(std::iter::once(None));\n" +"\n" " for (prefix, request_path) in prefixes.zip(request_paths) {\n" " match request_path {\n" " Some(request_path) => {\n" @@ -11532,11 +17557,8 @@ msgid "" " }\n" " }\n" " true\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:139 -msgid "" +"}\n" +"\n" "// ANCHOR: unit-tests\n" "#[test]\n" "fn test_matches_without_wildcard() {\n" @@ -11544,11 +17566,29 @@ msgid "" " assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/" "abc-123\"));\n" " assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/" -"books\"));" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:166 -msgid "" +"books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/" +"publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" " assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/" "publishers\"));\n" " assert!(!prefix_matches(\n" @@ -11557,6 +17597,8 @@ msgid "" " ));\n" "}\n" "// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" "```" msgstr "" @@ -11572,95 +17614,145 @@ msgstr "" msgid "([back to exercise](simple-gui.md))" msgstr "" -#: src/exercises/day-3/solutions-morning.md:22 +#: src/exercises/day-3/solutions-morning.md:7 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: setup\n" "pub trait Widget {\n" " /// Natural width of `self`.\n" -" fn width(&self) -> usize;" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:82 -msgid "// ANCHOR_END: setup" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:84 -msgid "" -"// ANCHOR: Window-width\n" -"impl Widget for Window {\n" -" fn width(&self) -> usize {\n" -" // ANCHOR_END: Window-width\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"\n" +" fn inner_width(&self) -> usize {\n" " std::cmp::max(\n" " self.title.chars().count(),\n" " self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" " )\n" -" }" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:94 -msgid "" +" }\n" +"}\n" +"\n" +"// ANCHOR_END: setup\n" +"\n" +"// ANCHOR: Window-width\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" // ANCHOR_END: Window-width\n" +" // Add 4 paddings for borders\n" +" self.inner_width() + 4\n" +" }\n" +"\n" " // ANCHOR: Window-draw_into\n" " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" " // ANCHOR_END: Window-draw_into\n" " let mut inner = String::new();\n" " for widget in &self.widgets {\n" " widget.draw_into(&mut inner);\n" -" }" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:102 -msgid " let window_width = self.width();" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:104 -msgid "" +" }\n" +"\n" +" let inner_width = self.inner_width();\n" +"\n" " // TODO: after learning about error handling, you can change\n" " // draw_into to return Result<(), std::fmt::Error>. Then use\n" " // the ?-operator here instead of .unwrap().\n" -" writeln!(buffer, \"+-{:- usize {\n" " // ANCHOR_END: Button-width\n" " self.label.width() + 8 // add a bit of padding\n" -" }" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:124 -msgid "" +" }\n" +"\n" " // ANCHOR: Button-draw_into\n" " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" " // ANCHOR_END: Button-draw_into\n" " let width = self.width();\n" " let mut label = String::new();\n" -" self.label.draw_into(&mut label);" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:131 -msgid "" +" self.label.draw_into(&mut label);\n" +"\n" " writeln!(buffer, \"+{:- usize {\n" @@ -11670,21 +17762,15 @@ msgid "" " .map(|line| line.chars().count())\n" " .max()\n" " .unwrap_or(0)\n" -" }" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:150 -msgid "" +" }\n" +"\n" " // ANCHOR: Label-draw_into\n" " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" " // ANCHOR_END: Label-draw_into\n" " writeln!(buffer, \"{}\", &self.label).unwrap();\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:157 -msgid "" +"}\n" +"\n" "// ANCHOR: main\n" "fn main() {\n" " let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" @@ -11712,25 +17798,78 @@ msgstr "" msgid "([back to exercise](safe-ffi-wrapper.md))" msgstr "" -#: src/exercises/day-3/solutions-afternoon.md:22 +#: src/exercises/day-3/solutions-afternoon.md:7 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: ffi\n" "mod ffi {\n" -" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:53 -msgid "" +" use std::os::raw::{c_char, c_int};\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" use std::os::raw::{c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::" +"PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-" +"gnu.\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" // Layout as per man entry for dirent\n" +" #[cfg(target_os = \"macos\")]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: u64,\n" +" pub d_seekoff: u64,\n" +" pub d_reclen: u16,\n" +" pub d_namlen: u16,\n" +" pub d_type: u8,\n" +" pub d_name: [c_char; 1024],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" "#[derive(Debug)]\n" "struct DirectoryIterator {\n" " path: CString,\n" " dir: *mut ffi::DIR,\n" "}\n" -"// ANCHOR_END: ffi" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:60 -msgid "" +"// ANCHOR_END: ffi\n" +"\n" "// ANCHOR: DirectoryIterator\n" "impl DirectoryIterator {\n" " fn new(path: &str) -> Result {\n" @@ -11747,11 +17886,8 @@ msgid "" " Ok(DirectoryIterator { path, dir })\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:77 -msgid "" +"}\n" +"\n" "// ANCHOR: Iterator\n" "impl Iterator for DirectoryIterator {\n" " type Item = OsString;\n" @@ -11770,11 +17906,8 @@ msgid "" " let os_str = OsStr::from_bytes(d_name.to_bytes());\n" " Some(os_str.to_owned())\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:97 -msgid "" +"}\n" +"\n" "// ANCHOR: Drop\n" "impl Drop for DirectoryIterator {\n" " fn drop(&mut self) {\n" @@ -11787,11 +17920,8 @@ msgid "" " }\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:111 -msgid "" +"}\n" +"\n" "// ANCHOR: main\n" "fn main() -> Result<(), String> {\n" " let iter = DirectoryIterator::new(\".\")?;\n" @@ -11799,43 +17929,575 @@ msgid "" " Ok(())\n" "}\n" "// ANCHOR_END: main\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +" use std::error::Error;\n" +"\n" +" #[test]\n" +" fn test_nonexisting_directory() {\n" +" let iter = DirectoryIterator::new(\"no-such-directory\");\n" +" assert!(iter.is_err());\n" +" }\n" +"\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" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-morning.md:1 +msgid "# Bare Metal Rust Morning Exercise" +msgstr "" + +#: src/exercises/bare-metal/solutions-morning.md:3 +#, fuzzy +msgid "## Compass" +msgstr "Sammenligning" + +#: src/exercises/bare-metal/solutions-morning.md:5 +msgid "([back to exercise](compass.md))" +msgstr "" + +#: src/exercises/bare-metal/solutions-morning.md:7 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"// ANCHOR_END: top\n" +"use core::cmp::{max, min};\n" +"use lsm303agr::{AccelOutputDataRate, Lsm303agr, MagOutputDataRate};\n" +"use microbit::display::blocking::Display;\n" +"use microbit::hal::prelude::*;\n" +"use microbit::hal::twim::Twim;\n" +"use microbit::hal::uarte::{Baudrate, Parity, Uarte};\n" +"use microbit::hal::Timer;\n" +"use microbit::pac::twim0::frequency::FREQUENCY_A;\n" +"use microbit::Board;\n" +"\n" +"const COMPASS_SCALE: i32 = 30000;\n" +"const ACCELEROMETER_SCALE: i32 = 700;\n" +"\n" +"// ANCHOR: main\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // ANCHOR_END: main\n" +" writeln!(serial, \"Setting up IMU...\").unwrap();\n" +" let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::" +"K100);\n" +" let mut imu = Lsm303agr::new_with_i2c(i2c);\n" +" imu.init().unwrap();\n" +" imu.set_mag_odr(MagOutputDataRate::Hz50).unwrap();\n" +" imu.set_accel_odr(AccelOutputDataRate::Hz50).unwrap();\n" +" let mut imu = imu.into_mag_continuous().ok().unwrap();\n" +"\n" +" // Set up display and timer.\n" +" let mut timer = Timer::new(board.TIMER0);\n" +" let mut display = Display::new(board.display_pins);\n" +"\n" +" let mut mode = Mode::Compass;\n" +" let mut button_pressed = false;\n" +"\n" +" // ANCHOR: loop\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // ANCHOR_END: loop\n" +" while !(imu.mag_status().unwrap().xyz_new_data\n" +" && imu.accel_status().unwrap().xyz_new_data)\n" +" {}\n" +" let compass_reading = imu.mag_data().unwrap();\n" +" let accelerometer_reading = imu.accel_data().unwrap();\n" +" writeln!(\n" +" serial,\n" +" \"{},{},{}\\t{},{},{}\",\n" +" compass_reading.x,\n" +" compass_reading.y,\n" +" compass_reading.z,\n" +" accelerometer_reading.x,\n" +" accelerometer_reading.y,\n" +" accelerometer_reading.z,\n" +" )\n" +" .unwrap();\n" +"\n" +" let mut image = [[0; 5]; 5];\n" +" let (x, y) = match mode {\n" +" Mode::Compass => (\n" +" scale(-compass_reading.x, -COMPASS_SCALE, COMPASS_SCALE, 0, " +"4) as usize,\n" +" scale(compass_reading.y, -COMPASS_SCALE, COMPASS_SCALE, 0, " +"4) as usize,\n" +" ),\n" +" Mode::Accelerometer => (\n" +" scale(\n" +" accelerometer_reading.x,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" scale(\n" +" -accelerometer_reading.y,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" ),\n" +" };\n" +" image[y][x] = 255;\n" +" display.show(&mut timer, image, 100);\n" +"\n" +" // If button A is pressed, switch to the next mode and briefly blink " +"all LEDs on.\n" +" if board.buttons.button_a.is_low().unwrap() {\n" +" if !button_pressed {\n" +" mode = mode.next();\n" +" display.show(&mut timer, [[255; 5]; 5], 200);\n" +" }\n" +" button_pressed = true;\n" +" } else {\n" +" button_pressed = false;\n" +" }\n" +" }\n" +"}\n" +"\n" +"#[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +"enum Mode {\n" +" Compass,\n" +" Accelerometer,\n" +"}\n" +"\n" +"impl Mode {\n" +" fn next(self) -> Self {\n" +" match self {\n" +" Self::Compass => Self::Accelerometer,\n" +" Self::Accelerometer => Self::Compass,\n" +" }\n" +" }\n" +"}\n" +"\n" +"fn scale(value: i32, min_in: i32, max_in: i32, min_out: i32, max_out: i32) -" +"> i32 {\n" +" let range_in = max_in - min_in;\n" +" let range_out = max_out - min_out;\n" +" cap(\n" +" min_out + range_out * (value - min_in) / range_in,\n" +" min_out,\n" +" max_out,\n" +" )\n" +"}\n" +"\n" +"fn cap(value: i32, min_value: i32, max_value: i32) -> i32 {\n" +" max(min_value, min(value, max_value))\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:1 +msgid "# Bare Metal Rust Afternoon" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:3 +msgid "## RTC driver" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:5 +msgid "([back to exercise](rtc.md))" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:7 +msgid "`main.rs`:" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:9 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"// ANCHOR_END: top\n" +"mod pl031;\n" +"\n" +"use crate::pl031::Rtc;\n" +"use arm_gic::gicv3::{IntId, Trigger};\n" +"use arm_gic::{irq_enable, wfi};\n" +"use chrono::{TimeZone, Utc};\n" +"use core::hint::spin_loop;\n" +"// ANCHOR: imports\n" +"use crate::pl011::Uart;\n" +"use arm_gic::gicv3::GicV3;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, trace, LevelFilter};\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" +"const GICR_BASE_ADDRESS: *mut u64 = 0x80A_0000 as _;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"// ANCHOR_END: imports\n" +"\n" +"/// Base address of the PL031 RTC.\n" +"const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;\n" +"/// The IRQ used by the PL031 RTC.\n" +"const PL031_IRQ: IntId = IntId::spi(2);\n" +"\n" +"// ANCHOR: main\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +"\n" +" // Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the " +"base\n" +" // addresses of a GICv3 distributor and redistributor respectively, and\n" +" // nothing else accesses those address ranges.\n" +" let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, " +"GICR_BASE_ADDRESS) };\n" +" gic.setup();\n" +" // ANCHOR_END: main\n" +"\n" +" // Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let mut rtc = unsafe { Rtc::new(PL031_BASE_ADDRESS) };\n" +" let timestamp = rtc.read();\n" +" let time = Utc.timestamp_opt(timestamp.into(), 0).unwrap();\n" +" info!(\"RTC: {time}\");\n" +"\n" +" GicV3::set_priority_mask(0xff);\n" +" gic.set_interrupt_priority(PL031_IRQ, 0x80);\n" +" gic.set_trigger(PL031_IRQ, Trigger::Level);\n" +" irq_enable();\n" +" gic.enable_interrupt(PL031_IRQ, true);\n" +"\n" +" // Wait for 3 seconds, without interrupts.\n" +" let target = timestamp + 3;\n" +" rtc.set_match(target);\n" +" info!(\n" +" \"Waiting for {}\",\n" +" Utc.timestamp_opt(target.into(), 0).unwrap()\n" +" );\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" while !rtc.matched() {\n" +" spin_loop();\n" +" }\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" info!(\"Finished waiting\");\n" +"\n" +" // Wait another 3 seconds for an interrupt.\n" +" let target = timestamp + 6;\n" +" info!(\n" +" \"Waiting for {}\",\n" +" Utc.timestamp_opt(target.into(), 0).unwrap()\n" +" );\n" +" rtc.set_match(target);\n" +" rtc.clear_interrupt();\n" +" rtc.enable_interrupt(true);\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" while !rtc.interrupt_pending() {\n" +" wfi();\n" +" }\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" info!(\"Finished waiting\");\n" +"\n" +" // ANCHOR: main_end\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off::().unwrap();\n" +" loop {}\n" +"}\n" +"// ANCHOR_END: main_end\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:149 +msgid "`pl031.rs`:" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:151 +msgid "" +"```rust\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"use core::ptr::{addr_of, addr_of_mut};\n" +"\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" /// Data register\n" +" dr: u32,\n" +" /// Match register\n" +" mr: u32,\n" +" /// Load register\n" +" lr: u32,\n" +" /// Control register\n" +" cr: u8,\n" +" _reserved0: [u8; 3],\n" +" /// Interrupt Mask Set or Clear register\n" +" imsc: u8,\n" +" _reserved1: [u8; 3],\n" +" /// Raw Interrupt Status\n" +" ris: u8,\n" +" _reserved2: [u8; 3],\n" +" /// Masked Interrupt Status\n" +" mis: u8,\n" +" _reserved3: [u8; 3],\n" +" /// Interrupt Clear Register\n" +" icr: u8,\n" +" _reserved4: [u8; 3],\n" +"}\n" +"\n" +"/// Driver for a PL031 real-time clock.\n" +"#[derive(Debug)]\n" +"pub struct Rtc {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Rtc {\n" +" /// Constructs a new instance of the RTC driver for a PL031 device at " +"the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of " +"a\n" +" /// PL031 device, which must be mapped into the address space of the " +"process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Reads the current RTC value.\n" +" pub fn read(&self) -> u32 {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).dr).read_volatile() }\n" +" }\n" +"\n" +" /// Writes a match value. When the RTC value matches this then an " +"interrupt\n" +" /// will be generated (if it is enabled).\n" +" pub fn set_match(&mut self, value: u32) {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of_mut!((*self.registers).mr).write_volatile(value) }\n" +" }\n" +"\n" +" /// Returns whether the match register matches the RTC value, whether or " +"not\n" +" /// the interrupt is enabled.\n" +" pub fn matched(&self) -> bool {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" let ris = unsafe { addr_of!((*self.registers).ris)." +"read_volatile() };\n" +" (ris & 0x01) != 0\n" +" }\n" +"\n" +" /// Returns whether there is currently an interrupt pending.\n" +" ///\n" +" /// This should be true iff `matched` returns true and the interrupt is\n" +" /// masked.\n" +" pub fn interrupt_pending(&self) -> bool {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" let ris = unsafe { addr_of!((*self.registers).mis)." +"read_volatile() };\n" +" (ris & 0x01) != 0\n" +" }\n" +"\n" +" /// Sets or clears the interrupt mask.\n" +" ///\n" +" /// When the mask is true the interrupt is enabled; when it is false " +"the\n" +" /// interrupt is disabled.\n" +" pub fn enable_interrupt(&mut self, mask: bool) {\n" +" let imsc = if mask { 0x01 } else { 0x00 };\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of_mut!((*self.registers).imsc)." +"write_volatile(imsc) }\n" +" }\n" +"\n" +" /// Clears a pending interrupt, if any.\n" +" pub fn clear_interrupt(&mut self) {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of_mut!((*self.registers).icr).write_volatile(0x01) }\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Rtc {}\n" "```" msgstr "" -#: src/exercises/day-4/solutions-morning.md:1 -msgid "# Day 4 Morning Exercise" +#: src/exercises/concurrency/solutions-morning.md:1 +msgid "# Concurrency Morning Exercise" msgstr "" -#: src/exercises/day-4/solutions-morning.md:3 +#: src/exercises/concurrency/solutions-morning.md:3 msgid "## Dining Philosophers" msgstr "" -#: src/exercises/day-4/solutions-morning.md:5 +#: src/exercises/concurrency/solutions-morning.md:5 msgid "([back to exercise](dining-philosophers.md))" msgstr "" -#: src/exercises/day-4/solutions-morning.md:22 +#: 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;\n" -"use std::sync::{Arc, Mutex};\n" +"use std::sync::{mpsc, Arc, Mutex};\n" "use std::thread;\n" -"use std::time::Duration;" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:30 -msgid "" +"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" -"}" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:38 -msgid "" +"}\n" +"\n" "// ANCHOR: Philosopher-think\n" "impl Philosopher {\n" " fn think(&self) {\n" @@ -11843,87 +18505,212 @@ msgid "" " .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" " .unwrap();\n" " }\n" -" // ANCHOR_END: Philosopher-think" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:47 -msgid "" +" // 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();" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:54 -msgid "" +" 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" -"}" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:63 -msgid "" +"}\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);" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:67 -msgid "" +" let (tx, rx) = mpsc::sync_channel(10);\n" +"\n" " let forks = (0..PHILOSOPHERS.len())\n" " .map(|_| Arc::new(Mutex::new(Fork)))\n" -" .collect::>();" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:71 -msgid "" +" .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();" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:76 -msgid "" +" 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" -" }" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:83 -msgid "" +" }\n" +"\n" " let philosopher = Philosopher {\n" " name: PHILOSOPHERS[i].to_string(),\n" " thoughts: tx,\n" " left_fork,\n" " right_fork,\n" -" };" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:90 -msgid "" +" };\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 +msgid "# Concurrency Afternoon Exercise" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:3 +msgid "## Dining Philosophers - Async" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:5 +msgid "([back to exercise](dining-philosophers-async.md))" msgstr "" -#: src/exercises/day-4/solutions-morning.md:98 +#: src/exercises/concurrency/solutions-afternoon.md:7 msgid "" -" drop(tx);\n" -" for thought in rx {\n" -" println!(\"{}\", thought);\n" +"```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 "" + +#~ msgid "On Day 4, we will cover Android-specific things such as:" +#~ msgstr "På dag 4 vil vi dække Android-specifikke ting såsom:" + +#~ msgid "" +#~ "* Building Android components in Rust.\n" +#~ "* AIDL servers and clients.\n" +#~ "* Interoperability with C, C++, and Java." +#~ msgstr "" +#~ "* Bygning af Android-komponenter i Rust\n" +#~ "* AIDL servere og klienter.\n" +#~ "* Interoperabilitet med C, C++ og 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 "" +#~ "Det er vigtigt at bemærke, at dette kursus ikke dækker\n" +#~ "Android-applikationsudvikling i Rust, og at de Android-specifikke dele\n" +#~ "specifikt handler om at skrive kode til selve Android styresystemet." diff --git a/po/de.po b/po/de.po index ec40753..a3c42e5 100644 --- a/po/de.po +++ b/po/de.po @@ -25,761 +25,1019 @@ 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:7 +#: src/SUMMARY.md:8 +msgid "Translations" +msgstr "Übersetzungen" + +#: src/SUMMARY.md:9 msgid "Using Cargo" msgstr "Cargo verwenden" -#: src/SUMMARY.md:8 +#: src/SUMMARY.md:10 msgid "Rust Ecosystem" msgstr "Rust Ökosystem" -#: src/SUMMARY.md:9 +#: src/SUMMARY.md:11 msgid "Code Samples" msgstr "Codebeispiele" -#: src/SUMMARY.md:10 +#: src/SUMMARY.md:12 msgid "Running Cargo Locally" msgstr "Cargo lokal ausführen" -#: src/SUMMARY.md:13 +#: src/SUMMARY.md:15 msgid "Day 1: Morning" msgstr "Tag 1: Morgens" -#: src/SUMMARY.md:17 src/SUMMARY.md:73 src/SUMMARY.md:126 src/SUMMARY.md:180 +#: src/SUMMARY.md:19 src/SUMMARY.md:76 src/SUMMARY.md:129 src/SUMMARY.md:185 src/SUMMARY.md:259 msgid "Welcome" msgstr "Willkommen" -#: src/SUMMARY.md:18 +#: src/SUMMARY.md:20 msgid "What is Rust?" msgstr "Was ist Rust?" -#: src/SUMMARY.md:19 +#: src/SUMMARY.md:21 msgid "Hello World!" msgstr "Hallo Welt!" -#: src/SUMMARY.md:20 +#: src/SUMMARY.md:22 msgid "Small Example" msgstr "Ein kleines Beispiel" -#: src/SUMMARY.md:21 +#: src/SUMMARY.md:23 msgid "Why Rust?" msgstr "Warum Rust?" -#: src/SUMMARY.md:22 +#: src/SUMMARY.md:24 msgid "Compile Time Guarantees" msgstr "Kompilierzeitgarantien" -#: src/SUMMARY.md:23 +#: src/SUMMARY.md:25 msgid "Runtime Guarantees" msgstr "Laufzeitgarantien" -#: src/SUMMARY.md:24 +#: src/SUMMARY.md:26 msgid "Modern Features" msgstr "Moderne Merkmale" -#: src/SUMMARY.md:25 +#: src/SUMMARY.md:27 msgid "Basic Syntax" msgstr "Grundlegende Syntax" -#: src/SUMMARY.md:26 +#: src/SUMMARY.md:28 msgid "Scalar Types" msgstr "Skalare Typen" -#: src/SUMMARY.md:27 +#: src/SUMMARY.md:29 msgid "Compound Types" msgstr "Verbundtypen" -#: src/SUMMARY.md:28 +#: src/SUMMARY.md:30 msgid "References" msgstr "Referenzen" -#: src/SUMMARY.md:29 +#: src/SUMMARY.md:31 msgid "Dangling References" msgstr "Hängende Referenzen" -#: src/SUMMARY.md:30 +#: src/SUMMARY.md:32 msgid "Slices" msgstr "Anteilstypen" -#: src/SUMMARY.md:31 +#: src/SUMMARY.md:33 msgid "String vs str" msgstr "String vs. str" -#: src/SUMMARY.md:32 +#: src/SUMMARY.md:34 msgid "Functions" msgstr "Funktionen" -#: src/SUMMARY.md:33 src/SUMMARY.md:80 +#: src/SUMMARY.md:35 +msgid "Rustdoc" +msgstr "" + +#: src/SUMMARY.md:36 src/SUMMARY.md:83 msgid "Methods" msgstr "Methoden" -#: src/SUMMARY.md:34 +#: src/SUMMARY.md:37 msgid "Overloading" msgstr "Überladen" -#: src/SUMMARY.md:35 src/SUMMARY.md:64 src/SUMMARY.md:88 src/SUMMARY.md:117 src/SUMMARY.md:145 -#: src/SUMMARY.md:172 src/SUMMARY.md:195 src/SUMMARY.md:222 +#: 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 msgid "Exercises" msgstr "Übungen" -#: src/SUMMARY.md:36 +#: src/SUMMARY.md:39 msgid "Implicit Conversions" msgstr "Implizite Konvertierungen" -#: src/SUMMARY.md:37 +#: src/SUMMARY.md:40 msgid "Arrays and for Loops" msgstr "Arrays und for-Schleifen" -#: src/SUMMARY.md:39 +#: src/SUMMARY.md:42 msgid "Day 1: Afternoon" msgstr "Tag 1: Nachmittags" -#: src/SUMMARY.md:41 +#: src/SUMMARY.md:44 msgid "Variables" msgstr "Variablen" -#: src/SUMMARY.md:42 +#: src/SUMMARY.md:45 msgid "Type Inference" msgstr "Typinferenz" -#: src/SUMMARY.md:43 +#: src/SUMMARY.md:46 msgid "static & const" msgstr "static & const" -#: src/SUMMARY.md:44 +#: src/SUMMARY.md:47 msgid "Scopes and Shadowing" -msgstr "Gültigkeitsbereiche und Beschatten" +msgstr "Gültigkeitsbereiche und Verschattungen" -#: src/SUMMARY.md:45 +#: src/SUMMARY.md:48 msgid "Memory Management" msgstr "Speicherverwaltung" -#: src/SUMMARY.md:46 +#: src/SUMMARY.md:49 msgid "Stack vs Heap" msgstr "Stapelspeicher vs. Haldenspeicher" -#: src/SUMMARY.md:47 +#: src/SUMMARY.md:50 msgid "Stack Memory" msgstr "Stapelspeicher" -#: src/SUMMARY.md:48 +#: src/SUMMARY.md:51 msgid "Manual Memory Management" msgstr "Manuelle Speicherverwaltung" -#: src/SUMMARY.md:49 +#: src/SUMMARY.md:52 msgid "Scope-Based Memory Management" msgstr "Gültigkeitsbereichbasierte Speicherverwaltung" -#: src/SUMMARY.md:50 +#: src/SUMMARY.md:53 msgid "Garbage Collection" msgstr "Automatische Speicherbereinigung" -#: src/SUMMARY.md:51 +#: src/SUMMARY.md:54 msgid "Rust Memory Management" msgstr "Rust Speicherverwaltung" -#: src/SUMMARY.md:52 +#: src/SUMMARY.md:55 msgid "Comparison" msgstr "Vergleich" -#: src/SUMMARY.md:53 +#: src/SUMMARY.md:56 msgid "Ownership" msgstr "Eigentümerschaft" -#: src/SUMMARY.md:54 +#: src/SUMMARY.md:57 msgid "Move Semantics" msgstr "Semantik des Verschiebens" -#: src/SUMMARY.md:55 +#: src/SUMMARY.md:58 msgid "Moved Strings in Rust" msgstr "Verschieben von String in Rust" -#: src/SUMMARY.md:56 +#: src/SUMMARY.md:59 msgid "Double Frees in Modern C++" msgstr "Doppel-Freigabe-Fehler in modernem C++" -#: src/SUMMARY.md:57 +#: src/SUMMARY.md:60 msgid "Moves in Function Calls" msgstr "Verschieben in Funktionsaufrufen" -#: src/SUMMARY.md:58 +#: src/SUMMARY.md:61 msgid "Copying and Cloning" msgstr "Kopieren und Klonen" -#: src/SUMMARY.md:59 +#: src/SUMMARY.md:62 msgid "Borrowing" msgstr "Ausleihen" -#: src/SUMMARY.md:60 +#: src/SUMMARY.md:63 msgid "Shared and Unique Borrows" msgstr "Geteiltes und einmaliges Ausleihen" -#: src/SUMMARY.md:61 +#: src/SUMMARY.md:64 msgid "Lifetimes" msgstr "Lebensdauern" -#: src/SUMMARY.md:62 +#: src/SUMMARY.md:65 msgid "Lifetimes in Function Calls" msgstr "Lebensdauern in Funktionsaufrufen" -#: src/SUMMARY.md:63 +#: src/SUMMARY.md:66 msgid "Lifetimes in Data Structures" msgstr "Lebensdauern in Datenstrukturen" -#: src/SUMMARY.md:65 +#: src/SUMMARY.md:68 msgid "Designing a Library" msgstr "Entwerfen einer Bibliothek" -#: src/SUMMARY.md:66 +#: src/SUMMARY.md:69 msgid "Iterators and Ownership" msgstr "Iteratoren und Eigentümerschaft" -#: src/SUMMARY.md:69 +#: src/SUMMARY.md:72 msgid "Day 2: Morning" msgstr "Tag 2: Morgens" -#: src/SUMMARY.md:74 +#: src/SUMMARY.md:77 msgid "Structs" msgstr "Strukturen" -#: src/SUMMARY.md:75 +#: src/SUMMARY.md:78 msgid "Tuple Structs" msgstr "Tupelstrukturen" -#: src/SUMMARY.md:76 +#: src/SUMMARY.md:79 msgid "Field Shorthand Syntax" msgstr "Feld Abkürzungs Syntax" -#: src/SUMMARY.md:77 +#: src/SUMMARY.md:80 msgid "Enums" msgstr "Aufzählungstypen" -#: src/SUMMARY.md:78 +#: src/SUMMARY.md:81 msgid "Variant Payloads" msgstr "Varianteninhalte" -#: src/SUMMARY.md:79 +#: src/SUMMARY.md:82 msgid "Enum Sizes" msgstr "Größen von Aufzählungstypen" -#: src/SUMMARY.md:81 +#: src/SUMMARY.md:84 msgid "Method Receiver" msgstr "Methodenempfänger" -#: src/SUMMARY.md:82 src/SUMMARY.md:190 +#: src/SUMMARY.md:85 src/SUMMARY.md:160 src/SUMMARY.md:195 msgid "Example" msgstr "Beispiel" -#: src/SUMMARY.md:83 +#: src/SUMMARY.md:86 msgid "Pattern Matching" msgstr "Musterabgleich" -#: src/SUMMARY.md:84 +#: src/SUMMARY.md:87 msgid "Destructuring Enums" msgstr "Aufzählungstypen destrukturieren" -#: src/SUMMARY.md:85 +#: src/SUMMARY.md:88 msgid "Destructuring Structs" msgstr "Strukturen destrukturieren" -#: src/SUMMARY.md:86 +#: src/SUMMARY.md:89 msgid "Destructuring Arrays" msgstr "Arrays destrukturieren" -#: src/SUMMARY.md:87 +#: src/SUMMARY.md:90 msgid "Match Guards" msgstr "Abgleichsbedingungen" -#: src/SUMMARY.md:89 +#: src/SUMMARY.md:92 msgid "Health Statistics" msgstr "Gesundheitsstatistiken" -#: src/SUMMARY.md:90 +#: src/SUMMARY.md:93 msgid "Points and Polygons" msgstr "Punkte und Polygone" -#: src/SUMMARY.md:92 +#: src/SUMMARY.md:95 msgid "Day 2: Afternoon" msgstr "Tag 2: Nachmittags" -#: src/SUMMARY.md:94 +#: src/SUMMARY.md:97 src/SUMMARY.md:240 msgid "Control Flow" msgstr "Kontrollfluss" -#: src/SUMMARY.md:95 +#: src/SUMMARY.md:98 msgid "Blocks" msgstr "Blöcke" -#: src/SUMMARY.md:96 +#: src/SUMMARY.md:99 msgid "if expressions" msgstr "if-Ausdrücke" -#: src/SUMMARY.md:97 +#: src/SUMMARY.md:100 msgid "if let expressions" msgstr "if let-Ausdrücke" -#: src/SUMMARY.md:98 +#: src/SUMMARY.md:101 msgid "while expressions" msgstr "while-Ausdrücke" -#: src/SUMMARY.md:99 +#: src/SUMMARY.md:102 msgid "while let expressions" msgstr "while let-Ausdrücke" -#: src/SUMMARY.md:100 +#: src/SUMMARY.md:103 msgid "for expressions" msgstr "for-Ausdrücke" -#: src/SUMMARY.md:101 +#: src/SUMMARY.md:104 msgid "loop expressions" msgstr "loop-Ausdrücke" -#: src/SUMMARY.md:102 +#: src/SUMMARY.md:105 msgid "match expressions" msgstr "match-Ausdrücke" -#: src/SUMMARY.md:103 +#: src/SUMMARY.md:106 msgid "break & continue" msgstr "break & continue" -#: src/SUMMARY.md:104 +#: src/SUMMARY.md:107 msgid "Standard Library" msgstr "Standardbibliothek" -#: src/SUMMARY.md:105 +#: src/SUMMARY.md:108 msgid "Option and Result" msgstr "Option und Result" -#: src/SUMMARY.md:106 +#: src/SUMMARY.md:109 msgid "String" msgstr "String" -#: src/SUMMARY.md:107 +#: src/SUMMARY.md:110 msgid "Vec" msgstr "Vec" -#: src/SUMMARY.md:108 +#: src/SUMMARY.md:111 msgid "HashMap" msgstr "HashMap" -#: src/SUMMARY.md:109 +#: src/SUMMARY.md:112 msgid "Box" msgstr "Box" -#: src/SUMMARY.md:110 +#: src/SUMMARY.md:113 msgid "Recursive Data Types" msgstr "Rekursive Datentypen" -#: src/SUMMARY.md:111 -#, fuzzy +#: src/SUMMARY.md:114 msgid "Niche Optimization" msgstr "Nischenoptimierung" -#: src/SUMMARY.md:112 +#: src/SUMMARY.md:115 msgid "Rc" msgstr "Rc" -#: src/SUMMARY.md:113 +#: src/SUMMARY.md:116 msgid "Modules" msgstr "Module" -#: src/SUMMARY.md:114 +#: src/SUMMARY.md:117 msgid "Visibility" msgstr "Sichtbarkeit" -#: src/SUMMARY.md:115 +#: src/SUMMARY.md:118 msgid "Paths" msgstr "Pfade" -#: src/SUMMARY.md:116 +#: src/SUMMARY.md:119 msgid "Filesystem Hierarchy" msgstr "Dateisystemhierarchie" -#: src/SUMMARY.md:118 +#: src/SUMMARY.md:121 msgid "Luhn Algorithm" msgstr "Luhn-Algorithmus" -#: src/SUMMARY.md:119 +#: src/SUMMARY.md:122 msgid "Strings and Iterators" msgstr "Strings und Iteratoren" -#: src/SUMMARY.md:122 +#: src/SUMMARY.md:125 msgid "Day 3: Morning" msgstr "Tag 3: Morgens" -#: src/SUMMARY.md:127 +#: src/SUMMARY.md:130 +msgid "Generics" +msgstr "Generische Datentypen und Methoden" + +#: src/SUMMARY.md:131 +msgid "Generic Data Types" +msgstr "Generische Datentypen" + +#: src/SUMMARY.md:132 +msgid "Generic Methods" +msgstr "Generische Methoden" + +#: src/SUMMARY.md:133 +msgid "Monomorphization" +msgstr "Monomorphisierung" + +#: src/SUMMARY.md:134 msgid "Traits" msgstr "Merkmale" -#: src/SUMMARY.md:128 +#: src/SUMMARY.md:135 +msgid "Trait Objects" +msgstr "Merkmalsobjekte" + +#: src/SUMMARY.md:136 msgid "Deriving Traits" msgstr "Ableitung von Merkmalen" -#: src/SUMMARY.md:129 +#: src/SUMMARY.md:137 msgid "Default Methods" msgstr "Standardmethoden" -#: src/SUMMARY.md:130 +#: src/SUMMARY.md:138 +msgid "Trait Bounds" +msgstr "Merkmalsgrenzen" + +#: src/SUMMARY.md:139 +msgid "impl Trait" +msgstr "impl Merkmal" + +#: src/SUMMARY.md:140 msgid "Important Traits" msgstr "Wichtige Merkmale" -#: src/SUMMARY.md:131 +#: src/SUMMARY.md:141 msgid "Iterator" msgstr "Iterator" -#: src/SUMMARY.md:132 +#: src/SUMMARY.md:142 msgid "FromIterator" msgstr "FromIterator" -#: src/SUMMARY.md:133 +#: src/SUMMARY.md:143 msgid "From and Into" msgstr "From und Into" -#: src/SUMMARY.md:134 +#: src/SUMMARY.md:144 msgid "Read and Write" msgstr "Read und Write" -#: src/SUMMARY.md:135 -msgid "Add, Mul, ..." -msgstr "Add, Mul, ..." - -#: src/SUMMARY.md:136 +#: src/SUMMARY.md:145 msgid "Drop" msgstr "Drop" -#: src/SUMMARY.md:137 -msgid "Generics" -msgstr "Generische Datentypen und Methoden" - -#: src/SUMMARY.md:138 -msgid "Generic Data Types" -msgstr "Generische Datentypen" - -#: src/SUMMARY.md:139 -msgid "Generic Methods" -msgstr "Generische Methoden" - -#: src/SUMMARY.md:140 -msgid "Trait Bounds" -msgstr "Merkmalsgrenzen" +#: src/SUMMARY.md:146 +msgid "Default" +msgstr "Default Merkmal" -#: src/SUMMARY.md:141 -msgid "impl Trait" -msgstr "impl Merkmal" +#: src/SUMMARY.md:147 +msgid "Operators: Add, Mul, ..." +msgstr "Operatoren: Add, Mul, ..." -#: src/SUMMARY.md:142 +#: src/SUMMARY.md:148 msgid "Closures" msgstr "Funktionsabschlüsse" -#: src/SUMMARY.md:143 -msgid "Monomorphization" -msgstr "Monomorphisierung" - -#: src/SUMMARY.md:144 -msgid "Trait Objects" -msgstr "Merkmalsobjekte" - -#: src/SUMMARY.md:146 +#: src/SUMMARY.md:150 msgid "A Simple GUI Library" msgstr "Eine einfache GUI-Bibliothek" -#: src/SUMMARY.md:148 +#: src/SUMMARY.md:152 msgid "Day 3: Afternoon" msgstr "Tag 3: Nachmittags" -#: src/SUMMARY.md:150 +#: src/SUMMARY.md:154 msgid "Error Handling" msgstr "Fehlerbehandlung" -#: src/SUMMARY.md:151 +#: src/SUMMARY.md:155 msgid "Panics" msgstr "Laufzeitabbrüche" -#: src/SUMMARY.md:152 +#: src/SUMMARY.md:156 msgid "Catching Stack Unwinding" -msgstr "Abfangen des Auflösen des Stapelspeichers" +msgstr "Abfangen der Auflösung des Stapelspeichers" -#: src/SUMMARY.md:153 +#: src/SUMMARY.md:157 msgid "Structured Error Handling" msgstr "Strukturierte Fehlerbehandlung" -#: src/SUMMARY.md:154 +#: src/SUMMARY.md:158 msgid "Propagating Errors with ?" msgstr "Weitergabe von Fehlern mit ?" -#: src/SUMMARY.md:155 +#: src/SUMMARY.md:159 msgid "Converting Error Types" msgstr "Fehlertypen konvertieren" -#: src/SUMMARY.md:156 +#: src/SUMMARY.md:161 msgid "Deriving Error Enums" msgstr "Ableiten von Fehleraufzählungen" -#: src/SUMMARY.md:157 +#: src/SUMMARY.md:162 msgid "Dynamic Error Types" msgstr "Dynamische Fehlertypen" -#: src/SUMMARY.md:158 +#: src/SUMMARY.md:163 msgid "Adding Context to Errors" msgstr "Kontext zu Fehlern hinzufügen" -#: src/SUMMARY.md:159 +#: src/SUMMARY.md:164 msgid "Testing" msgstr "Testen" -#: src/SUMMARY.md:160 +#: src/SUMMARY.md:165 msgid "Unit Tests" msgstr "Unit-Tests" -#: src/SUMMARY.md:161 +#: src/SUMMARY.md:166 msgid "Test Modules" msgstr "Testmodule" -#: src/SUMMARY.md:162 +#: src/SUMMARY.md:167 msgid "Documentation Tests" msgstr "Dokumentationstests" -#: src/SUMMARY.md:163 +#: src/SUMMARY.md:168 msgid "Integration Tests" msgstr "Integrationstests" -#: src/SUMMARY.md:164 +#: src/SUMMARY.md:169 msgid "Unsafe Rust" msgstr "Unsicheres Rust" -#: src/SUMMARY.md:165 +#: src/SUMMARY.md:170 msgid "Dereferencing Raw Pointers" msgstr "Roh-zeiger dereferenzieren" -#: src/SUMMARY.md:166 +#: src/SUMMARY.md:171 msgid "Mutable Static Variables" msgstr "Veränderbare statische Variablen" -#: src/SUMMARY.md:167 +#: src/SUMMARY.md:172 msgid "Unions" msgstr "Vereinigungen" -#: src/SUMMARY.md:168 +#: src/SUMMARY.md:173 msgid "Calling Unsafe Functions" msgstr "Unsichere Funktionen aufrufen" -#: src/SUMMARY.md:169 +#: src/SUMMARY.md:174 msgid "Writing Unsafe Functions" msgstr "Unsichere Funktionen schreiben" -#: src/SUMMARY.md:170 +#: src/SUMMARY.md:175 msgid "Extern Functions" msgstr "Externe Funktionen" -#: src/SUMMARY.md:171 +#: src/SUMMARY.md:176 msgid "Implementing Unsafe Traits" msgstr "Unsichere Merkmale implementieren" -#: src/SUMMARY.md:173 +#: src/SUMMARY.md:178 msgid "Safe FFI Wrapper" msgstr "Sicherer FFI-Wrapper" -#: src/SUMMARY.md:176 +#: src/SUMMARY.md:181 msgid "Day 4: Morning" msgstr "Tag 4: Morgens" -#: src/SUMMARY.md:181 +#: src/SUMMARY.md:186 msgid "Concurrency" msgstr "Nebenläufigkeit" -#: src/SUMMARY.md:182 +#: src/SUMMARY.md:187 msgid "Threads" msgstr "Ausführungsstrang" -#: src/SUMMARY.md:183 +#: src/SUMMARY.md:188 msgid "Scoped Threads" msgstr "Ausführungsstrang mit Sichtbarkeitsbereich" -#: src/SUMMARY.md:184 +#: src/SUMMARY.md:189 msgid "Channels" msgstr "Kanäle" -#: src/SUMMARY.md:185 +#: src/SUMMARY.md:190 msgid "Unbounded Channels" msgstr "Unbegrenzte Kanäle" -#: src/SUMMARY.md:186 +#: src/SUMMARY.md:191 msgid "Bounded Channels" msgstr "Unbeschränkte Kanäle" -#: src/SUMMARY.md:187 +#: src/SUMMARY.md:192 msgid "Shared State" msgstr "Geteilter Zustand" -#: src/SUMMARY.md:188 +#: src/SUMMARY.md:193 msgid "Arc" msgstr "Arc" -#: src/SUMMARY.md:189 +#: src/SUMMARY.md:194 msgid "Mutex" msgstr "Mutex" -#: src/SUMMARY.md:191 +#: src/SUMMARY.md:196 msgid "Send and Sync" msgstr "Send und Sync" -#: src/SUMMARY.md:191 +#: src/SUMMARY.md:196 msgid "Send" msgstr "Send" -#: src/SUMMARY.md:191 +#: src/SUMMARY.md:196 msgid "Sync" msgstr "Sync" -#: src/SUMMARY.md:194 +#: src/SUMMARY.md:199 msgid "Examples" msgstr "Beispiele" -#: src/SUMMARY.md:196 +#: src/SUMMARY.md:201 msgid "Dining Philosophers" msgstr "Philosophenproblem" -#: src/SUMMARY.md:197 +#: src/SUMMARY.md:202 msgid "Multi-threaded Link Checker" msgstr "Link Überprüfung mit mehreren Ausführungssträngen" -#: src/SUMMARY.md:199 -msgid "Day 4: Afternoon" -msgstr "Tag 4: Nachmittags" +#: src/SUMMARY.md:204 +msgid "Day 4: Afternoon (Android)" +msgstr "Tag 4: Nachmittags (Android)" -#: src/SUMMARY.md:203 +#: src/SUMMARY.md:204 src/SUMMARY.md:297 msgid "Android" msgstr "Android" -#: src/SUMMARY.md:204 +#: src/SUMMARY.md:209 msgid "Setup" msgstr "Einrichtung" -#: src/SUMMARY.md:205 +#: src/SUMMARY.md:210 msgid "Build Rules" msgstr "Regeln beim Bauen" -#: src/SUMMARY.md:206 +#: src/SUMMARY.md:211 msgid "Binary" msgstr "Binärdatei" -#: src/SUMMARY.md:207 +#: src/SUMMARY.md:212 msgid "Library" msgstr "Bibliothek" -#: src/SUMMARY.md:208 +#: src/SUMMARY.md:213 msgid "AIDL" msgstr "AIDL" -#: src/SUMMARY.md:209 +#: src/SUMMARY.md:214 msgid "Interface" msgstr "Schnittstelle" -#: src/SUMMARY.md:210 +#: src/SUMMARY.md:215 msgid "Implementation" msgstr "Implementierung" -#: src/SUMMARY.md:211 +#: src/SUMMARY.md:216 msgid "Server" msgstr "Server" -#: src/SUMMARY.md:212 +#: src/SUMMARY.md:217 msgid "Deploy" msgstr "Einsetzen" -#: src/SUMMARY.md:213 +#: src/SUMMARY.md:218 msgid "Client" msgstr "Klient" -#: src/SUMMARY.md:214 +#: src/SUMMARY.md:219 msgid "Changing API" msgstr "API verändern" -#: src/SUMMARY.md:215 +#: src/SUMMARY.md:220 src/SUMMARY.md:288 msgid "Logging" msgstr "Protokollierung" -#: src/SUMMARY.md:216 +#: src/SUMMARY.md:221 msgid "Interoperability" msgstr "Interoperabilität" -#: src/SUMMARY.md:217 +#: src/SUMMARY.md:222 msgid "With C" msgstr "Mit C" -#: src/SUMMARY.md:218 +#: src/SUMMARY.md:223 msgid "Calling C with Bindgen" msgstr "Aufruf von C-Funktionen mit Bindgen" -#: src/SUMMARY.md:219 +#: src/SUMMARY.md:224 msgid "Calling Rust from C" msgstr "Aufruf von Rust aus C" -#: src/SUMMARY.md:220 +#: src/SUMMARY.md:225 msgid "With C++" msgstr "Mit C++" -#: src/SUMMARY.md:221 +#: src/SUMMARY.md:226 msgid "With Java" msgstr "Mit Java" -#: src/SUMMARY.md:224 +#: 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:226 +#: src/SUMMARY.md:251 msgid "Thanks!" msgstr "Danke!" -#: src/SUMMARY.md:227 +#: src/SUMMARY.md:252 msgid "Other Resources" msgstr "Andere Ressourcen" -#: src/SUMMARY.md:228 +#: src/SUMMARY.md:253 msgid "Credits" msgstr "Würdigungen" -#: src/SUMMARY.md:232 +#: src/SUMMARY.md:257 +msgid "Bare Metal Rust: Morning" +msgstr "Hardwarenahes Rust: Morgens" + +#: src/SUMMARY.md:260 +msgid "no_std" +msgstr "" + +#: src/SUMMARY.md:261 +msgid "A Minimal Example" +msgstr "Kleines Beispiel" + +#: src/SUMMARY.md:262 +msgid "alloc" +msgstr "" + +#: src/SUMMARY.md:263 +msgid "Microcontrollers" +msgstr "Mikrokontroller" + +#: src/SUMMARY.md:264 +msgid "Raw MMIO" +msgstr "MMIO" + +#: src/SUMMARY.md:265 +msgid "PACs" +msgstr "" + +#: src/SUMMARY.md:266 +msgid "HAL Crates" +msgstr "HAL Kisten" + +#: src/SUMMARY.md:267 +msgid "Board Support Crates" +msgstr "Helfer Kisten" + +#: src/SUMMARY.md:268 +msgid "The Type State Pattern" +msgstr "Das Typzustandsmuster" + +#: src/SUMMARY.md:269 +msgid "embedded-hal" +msgstr "" + +#: src/SUMMARY.md:270 +msgid "probe-rs, cargo-embed" +msgstr "" + +#: src/SUMMARY.md:271 +msgid "Debugging" +msgstr "Debugging" + +#: src/SUMMARY.md:272 src/SUMMARY.md:290 +msgid "Other Projects" +msgstr "Andere Ressourcen" + +#: src/SUMMARY.md:274 +msgid "Compass" +msgstr "Kompass" + +#: src/SUMMARY.md:276 +msgid "Bare Metal Rust: Afternoon" +msgstr "Hardwarenahes Rust: Nachmittags" + +#: src/SUMMARY.md:278 +msgid "Application Processors" +msgstr "Applikationsprozessoren" + +#: src/SUMMARY.md:279 +msgid "Inline Assembly" +msgstr "" + +#: src/SUMMARY.md:280 +msgid "MMIO" +msgstr "" + +#: src/SUMMARY.md:281 +msgid "Let's Write a UART Driver" +msgstr "Schreiben eines UART Treibers" + +#: src/SUMMARY.md:282 +msgid "More Traits" +msgstr "Noch mehr Merkmale" + +#: src/SUMMARY.md:283 +msgid "A Better UART Driver" +msgstr "Ein besserer UART Treiber" + +#: src/SUMMARY.md:284 +msgid "Bitflags" +msgstr "" + +#: src/SUMMARY.md:285 +msgid "Multiple Registers" +msgstr "Mehrere Register" + +#: src/SUMMARY.md:286 +msgid "Driver" +msgstr "Treiber" + +#: src/SUMMARY.md:287 src/SUMMARY.md:289 +msgid "Using It" +msgstr "Benutzung" + +#: src/SUMMARY.md:291 +msgid "Useful Crates" +msgstr "Nützliche Kisten" + +#: src/SUMMARY.md:292 +msgid "zerocopy" +msgstr "" + +#: src/SUMMARY.md:293 +msgid "aarch64-paging" +msgstr "" + +#: src/SUMMARY.md:294 +msgid "buddy_system_allocator" +msgstr "" + +#: src/SUMMARY.md:295 +msgid "tinyvec" +msgstr "" + +#: src/SUMMARY.md:296 +msgid "spin" +msgstr "" + +#: src/SUMMARY.md:298 +msgid "vmbase" +msgstr "" + +#: src/SUMMARY.md:300 +msgid "RTC Driver" +msgstr "RTC Treiber" + +#: src/SUMMARY.md:304 msgid "Solutions" msgstr "Lösungen" -#: src/SUMMARY.md:237 +#: src/SUMMARY.md:309 msgid "Day 1 Morning" msgstr "Tag 1 Morgens" -#: src/SUMMARY.md:238 +#: src/SUMMARY.md:310 msgid "Day 1 Afternoon" msgstr "Tag 1 Nachmittags" -#: src/SUMMARY.md:239 +#: src/SUMMARY.md:311 msgid "Day 2 Morning" msgstr "Tag 2 Morgens" -#: src/SUMMARY.md:240 +#: src/SUMMARY.md:312 msgid "Day 2 Afternoon" msgstr "Tag 2 Nachmittags" -#: src/SUMMARY.md:241 +#: src/SUMMARY.md:313 msgid "Day 3 Morning" msgstr "Tag 3 Morgens" -#: src/SUMMARY.md:242 +#: src/SUMMARY.md:314 msgid "Day 3 Afternoon" msgstr "Tag 3 Nachmittags" -#: src/SUMMARY.md:243 +#: src/SUMMARY.md:315 msgid "Day 4 Morning" msgstr "Tag 4 Morgens" +#: src/SUMMARY.md:316 +msgid "Bare Metal Rust Morning" +msgstr "Hardwarenahes Rust: Morgens" + +#: src/SUMMARY.md:317 +msgid "Bare Metal Rust Afternoon" +msgstr "Hadwarenahes Rust: Nachmittags" + #: src/welcome.md:1 msgid "# Welcome to Comprehensive Rust 🦀" msgstr "# Willkommen bei Comprehensive Rust 🦀" #: src/welcome.md:3 msgid "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/" +"build.yml?style=flat-square)](https://github.com/google/comprehensive-rust/actions/workflows/build." +"yml)" +msgstr "" + +#: src/welcome.md:3 +msgid "Build workflow" +msgstr "" + +#: src/welcome.md:3 +msgid "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/" +"build.yml?style=flat-square)](https://github.com/google/comprehensive-rust/actions/workflows/build." +"yml)\n" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?" +"style=flat-square)](https://github.com/google/comprehensive-rust/graphs/contributors)" +msgstr "" + +#: src/welcome.md:4 +msgid "GitHub contributors" +msgstr "Github Beiträger" + +#: src/welcome.md:4 +msgid "" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?" +"style=flat-square)](https://github.com/google/comprehensive-rust/graphs/contributors)\n" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)]" +"(https://github.com/google/comprehensive-rust/stargazers)" +msgstr "" + +#: src/welcome.md:5 +msgid "GitHub stars" +msgstr "Github Sterne" + +#: src/welcome.md:5 +msgid "" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)]" +"(https://github.com/google/comprehensive-rust/stargazers)" +msgstr "" + +#: src/welcome.md:7 +msgid "" "This is a four 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." @@ -789,7 +1047,7 @@ msgstr "" "generischen Methoden und Datentypen\n" "sowie Fehlerbehandlung. Am letzten Tag werden auch Android-spezifische Inhalte behandelt." -#: src/welcome.md:7 +#: src/welcome.md:11 msgid "" "The goal of the course is to teach you Rust. We assume you don't know anything\n" "about Rust and hope to:" @@ -797,7 +1055,7 @@ msgstr "" "Das Ziel des Kurses ist es, Dir Rust beizubringen. Wie setzen keine Vorkenntnisse über Rust " "voraus, und hoffen das Folgende zu erreichen:" -#: src/welcome.md:10 +#: src/welcome.md:14 msgid "" "* Give you a comprehensive understanding of the Rust syntax and language.\n" "* Enable you to modify existing programs and write new programs in Rust.\n" @@ -808,11 +1066,11 @@ msgstr "" "schreiben.\n" "* Dir gängige Rust-Idiome zu zeigen." -#: src/welcome.md:14 +#: 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:16 +#: src/welcome.md:20 msgid "" "* Building Android components in Rust.\n" "* AIDL servers and clients.\n" @@ -822,7 +1080,7 @@ msgstr "" "* AIDL-Server und -Klienten.\n" "* Interoperabilität mit C, C++ und Java." -#: src/welcome.md:20 +#: src/welcome.md:24 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" @@ -832,11 +1090,11 @@ msgstr "" "und dass es bei den Android-spezifischen Teilen um das \n" "Schreiben von Code für das Betriebssystem Android geht. " -#: src/welcome.md:24 +#: src/welcome.md:28 msgid "## Non-Goals" msgstr "## Nicht-Ziele" -#: src/welcome.md:26 +#: src/welcome.md:30 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:" @@ -845,7 +1103,7 @@ msgstr "" "können.\n" "Einige Nicht-Ziele dieses Kurses sind:" -#: src/welcome.md:29 +#: src/welcome.md:33 msgid "" "* Learn how to use async Rust --- we'll only mention async Rust when\n" " covering traditional concurrency primitives. Please see [Asynchronous\n" @@ -863,67 +1121,97 @@ msgstr "" " 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)." -#: src/welcome.md:37 +#: src/welcome.md:41 msgid "## Assumptions" msgstr "## Annahmen" -#: src/welcome.md:39 +#: src/welcome.md:43 msgid "" "The course assumes that you already know how to program. Rust is a statically\n" "typed language and we will sometimes make comparisons with C and C++ to better\n" "explain or contrast the Rust approach." msgstr "" -"Der Kurs setzt voraus, dass Du bereits Programmierkenntnisse besitzt. Rust ist eine statisch\n" +"Der Kurs setzt voraus, dass du bereits Programmierkenntnisse besitzt. Rust ist eine statisch\n" "typisierte Sprache und wir werden manchmal Vergleiche mit C und C++ machen, um besser den Rust-" "Ansatz zu erklären oder gegenüberzustellen." -#: src/welcome.md:43 +#: src/welcome.md:47 msgid "" "If you know how to program in a dynamically typed language such as Python or\n" "JavaScript, then you will be able to follow along just fine too." msgstr "" -"Aber auch wenn Du Vorwissen in einer dynamisch typisierten Sprache wie Python oder\n" -"JavaScript hast, wirst Du problemlos folgen können." +"Aber auch wenn du Vorwissen in einer dynamisch typisierten Sprache wie Python oder\n" +"JavaScript hast, wirst du problemlos folgen können." -#: src/welcome.md:46 src/cargo/rust-ecosystem.md:19 src/cargo/code-samples.md:22 +#: src/welcome.md:50 src/cargo/rust-ecosystem.md:19 src/cargo/code-samples.md:22 #: 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/string-slices.md:25 src/basic-syntax/functions.md:33 -#: 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/structs/tuple-structs.md:35 -#: src/structs/field-shorthand.md:25 src/enums/variant-payloads.md:33 src/methods.md:28 -#: src/pattern-matching/destructuring-enums.md:33 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/std/option-result.md:16 src/std/string.md:28 src/std/box.md:32 src/std/rc.md:26 -#: src/exercises/day-2/afternoon.md:5 src/traits.md:39 src/traits/iterator.md:30 -#: src/traits/from-iterator.md:12 src/traits/operators.md:24 src/traits/drop.md:32 -#: src/generics/methods.md:23 src/generics/trait-bounds.md:20 src/generics/impl-trait.md:22 -#: src/generics/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.md:66 +#: 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/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/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/concurrency/threads.md:28 -#: src/concurrency/channels.md:25 src/concurrency/shared_state/arc.md:27 +#: 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/afternoon.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/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 +#: src/bare-metal/microcontrollers/type-state.md:30 +#: src/bare-metal/microcontrollers/embedded-hal.md:17 src/bare-metal/microcontrollers/probe-rs.md:14 +#: src/bare-metal/microcontrollers/debugging.md:25 +#: src/bare-metal/microcontrollers/other-projects.md:16 src/exercises/bare-metal/morning.md:5 +#: src/bare-metal/aps.md:7 src/bare-metal/aps/inline-assembly.md:41 src/bare-metal/aps/mmio.md:7 +#: 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/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 msgid "
" msgstr "
" -#: src/welcome.md:48 +#: src/welcome.md:52 msgid "" "This is an example of a _speaker note_. We will use these to add additional\n" "information to the slides. This could be key points which the instructor should\n" @@ -934,36 +1222,71 @@ msgstr "" "beinhalten, die vom Kursleiter erwähnt werden sollten, oder auch Antworten auf \n" "Fragen, die typischerweise im Kurs vorkommen." -#: src/welcome.md:52 src/cargo/rust-ecosystem.md:67 src/cargo/code-samples.md:35 +#: src/welcome.md:56 src/cargo/rust-ecosystem.md:67 src/cargo/code-samples.md:35 #: 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:36 src/hello-world/small-example.md:44 src/why-rust.md:24 +#: 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/functions.md:54 src/exercises/day-1/morning.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/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:32 +#: src/basic-syntax/scopes-shadowing.md:39 src/memory-management/stack.md:49 #: src/memory-management/rust.md:18 src/ownership/move-semantics.md:26 -#: src/ownership/moves-function-calls.md:26 src/ownership/borrowing.md:51 -#: src/ownership/shared-unique-borrows.md:29 src/ownership/lifetimes-function-calls.md:60 -#: src/exercises/day-1/afternoon.md:15 src/exercises/day-1/book-library.md:103 src/structs.md:40 -#: src/enums/variant-payloads.md:39 src/enums/sizes.md:49 src/methods/example.md:53 -#: src/pattern-matching/destructuring-enums.md:39 src/exercises/day-2/morning.md:15 -#: src/exercises/day-2/points-polygons.md:125 src/control-flow/if-let-expressions.md:26 src/std.md:31 -#: src/std/option-result.md:25 src/std/string.md:34 src/std/vec.md:38 src/std/box.md:37 -#: src/std/rc.md:32 src/exercises/day-2/afternoon.md:11 src/traits.md:54 -#: src/traits/from-iterator.md:23 src/traits/operators.md:38 src/traits/drop.md:42 -#: src/generics/methods.md:31 src/generics/closures.md:38 src/exercises/day-3/morning.md:11 -#: src/error-handling/try-operator.md:55 src/error-handling/converting-error-types.md:78 +#: 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/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/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/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/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/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/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/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/concurrency/threads.md:45 -#: src/concurrency/channels.md:32 src/concurrency/shared_state/arc.md:38 -#: src/concurrency/shared_state/example.md:60 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/afternoon.md:15 +#: 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/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 +#: src/bare-metal/microcontrollers/other-projects.md:26 src/exercises/bare-metal/morning.md:11 +#: 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/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 msgid "
" msgstr "
" @@ -972,6 +1295,7 @@ 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." @@ -984,102 +1308,74 @@ msgstr "" "durchführen." #: src/running-the-course.md:8 -msgid "To run the course, you need to:" -msgstr "Um den Kurs durchzuführen:" +msgid "Before you run the course, you will want to:" +msgstr "Bevor du den Kurs vorstellst solltest du:" #: src/running-the-course.md:10 msgid "" "1. Make yourself familiar with the course material. We've included speaker notes\n" -" on some of the pages to help highlight the key points (please help us by\n" -" contributing more speaker notes!). You should make sure to open the speaker\n" -" notes in a popup (click the link with a little arrow next to \"Speaker\n" -" Notes\"). This way you have a clean screen to present to the class." -msgstr "" -"1. Mach dich mit dem Kursmaterial vertraut. Wir haben Sprechernotizen an einigen \n" -" Stellen hinzugefügt, um die wichtigsten Punkte hervorzuheben (du hilfts uns sehr, \n" -" wenn du weitere Sprechernotizen beisteuerst!). Du solltest die Sprechernotizeb in \n" -" einem Popup öffnen (klicke dazu auf dem Link mit einem kleinen Pfeil neben \n" -" \"Sprechernotizen\"). Auf diese Weise präsentierst Du den Kursteilnehmern nur \n" -" das Kursmaterial." - -#: src/running-the-course.md:16 -msgid "" -"2. Decide on the dates. Since the course is large, we recommend that you\n" +" to help highlight the key points (please help us by contributing more speaker\n" +" notes!). When presenting, you should make sure to open the speaker notes in a\n" +" 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" " they find it helpful to have a gap in the course since it helps them process\n" -" all the information we give them." -msgstr "" -"2. Lege die Termine fest. Da der Kurs recht lang ist, empfehlen wir die 4 Tage \n" -" verteilt über 2 Wochen zu legen. Bisherige Kursteilnehmer fanden es hilfreich, \n" -" eine Lücke zwischen Kurstage zu haben, um das Material zu verinnerlichern." - -#: src/running-the-course.md:21 -msgid "" -"3. Find a room large enough for your in-person participants. We recommend a\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" " asking questions --- it's also small enough that one instructor will have\n" -" time to answer the questions." -msgstr "" -"3. Finde einen Raum, der groß genug für alle in Person anwesenden Teilnehmer ist. \n" -" Wir empfehlen eine Kursgröße von 15-20 Personen. Das ist klein genug, dass sich \n" -" die Leute wohlfühlen Fragen stellen --- und es ist auch klein genug, dass der \n" -" Lehrende Zeit hat alle Fragen zu beantworten." - -#: src/running-the-course.md:26 -msgid "" -"4. On the day of your course, show up to the room a little early to set things\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" +" In particular, you will be doing a lot of live-coding as an instructor, so a lectern won't\n" +" be very helpful for you.\n" +"\n" +"1. On the day of your course, show up to the room a little early to set things\n" " up. We recommend presenting directly using `mdbook serve` running on your\n" -" laptop. This ensures optimal performance with no lag as you change pages.\n" +" laptop (see the [installation instructions][3]). This ensures optimal performance with no lag " +"as you change pages.\n" " Using your laptop will also allow you to fix typos as you or the course\n" -" participants spot them." -msgstr "" -"4. Erscheine am Tag des Kurses etwas früher in dem Raum, um alles vorzubereiten. \n" -" Wir empfehlen, direkt `mdbook serve` auf deinem Laptop laufen zu lassen, und so \n" -" den Kurz zu präsentieren. Das minimiert Verzögerungen beim Seitenwechsel und \n" -" ermöglicht es, Tippfehler, die von Teilnehmern entdeckt werden, gleich währende\n" -" des Kurses zu korrigieren." - -#: src/running-the-course.md:32 -msgid "" -"5. Let people solve the exercises by themselves or in small groups. Make sure to\n" +" participants spot them.\n" +"\n" +"1. Let people solve the exercises by themselves or in small groups. 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." -msgstr "" -"5. Lass die Teilnehmer die Übungen alleine oder in kleinen Gruppen lösen. Frage ab und zu nach,\n" -" ob jemand nicht weiterkommt und ob es etwas gibt, wo Du helfen kannst. Wenn Du merkst,\n" -" dass mehrere Personen die gleichen Probleme haben, solltest Du dies im Kurs ansprechen\n" -" und Hinweise geben, wo relevante Informationen (wie z.B. Teile der Standardbibliothek) zu \n" -" finden sind." - -#: src/running-the-course.md:38 -msgid "" -"6. If you don't skip the Android specific parts on Day 4, you will need an [AOSP\n" -" checkout][1]. Make a checkout of the [course repository][2] on the same\n" -" machine and move the `src/android/` directory into the root of your AOSP\n" -" checkout. This will ensure that the Android build system sees the\n" -" `Android.bp` files in `src/android/`." -msgstr "" -"6. 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" -" auf deinem Laptop und verschiebe das Verzeichnis `src/android/` in \n" -" das Stammverzeichnis Deiner AOSP Arbeitskopie . Dadurch wird \n" -" sichergestellt, dass das Android-Buildsystem die \n" -" `Android.bp`-Dateien in `src/android/` sehen kann." - -#: src/running-the-course.md:44 -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." -msgstr "" -" Stelle sicher, dass \"adb sync\" auf Ihrem 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.md:48 +" information in the standard library.\n" +"\n" +"1. Prepare anything you need to have available for the afternoon of day 4." +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!). " +"Beim Vorstellen kannst du die Sprechernotizen in einem Seitenfenster öffnen (klick dazu auf den " +"kleinen Pfeil neben \"Speaker Notes\"). Dadurch hast du eine übersichtliche Oberfläche wenn du den " +"Kurs vorstellst.\n" +"1. Am Nachmittag des vierten Tages kannst du ein Thema frei wählen. Du kannst entweder ein Thema " +"nach Schwierigkeitsgrad wählen, oder aber ein Thema was zu deiner Zuhörerschaft passt.\n" +"1. Lege im Vorhinein die Kurszeiten fest. Der Kurs ist umfangreich, daher empfehlen wir vier Tage " +"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" +"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 " +"Rechtschreibfehler finden können diese sofort behoben werden.\n" +"1. Gib den Kursteilnehmern Zeit die Aufgaben selbst oder in kleinen Gruppen zu lösen. Vergiss " +"nicht ab und an zu fragen ob jemand Hilfe benötigt. Wenn mehrere Teilnehmer das gleiche Problem " +"haben, spreche es vor allen Teilnehmern an und zeige einen möglichen Lösungsweg auf. Z. B. " +"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 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!" @@ -1087,243 +1383,283 @@ 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:51 +#: src/running-the-course.md:49 msgid "" -"Please [provide feedback][3] afterwards so that we can keep improving the\n" +"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" -"better. Your students are also very welcome to [send us feedback][4]!" -msgstr "" -"Bitte [gib anschließend Rückmeldung][3], damit wir den Kurs weiter verbessern können. \n" -"Wir sind daran interessiert, was gut funktioniert hat und was verbessert werden kann\n" -"Auch deine Teilnehmer sind herzlich eingeladen, [uns Rückmeldung zu senden][4]!" - -#: src/running-the-course.md:55 -#, fuzzy -msgid "" -"[1]: https://source.android.com/docs/setup/download/downloading\n" -"[2]: https://github.com/google/comprehensive-rust\n" -"[3]: https://github.com/google/comprehensive-rust/discussions/86\n" -"[4]: https://github.com/google/comprehensive-rust/discussions/100" +"better. Your students are also very welcome to [send us feedback][2]!" msgstr "" -"[1]: https://source.android.com/docs/setup/download/downloading\n" -"[2]: https://github.com/google/comprehensive-rust\n" -"[3]: https://github.com/google/comprehensive-rust/discussions/86\n" -"[4]: https://github.com/google/comprehensive-rust/discussions/100" +"Bitte [gib anschließend Rückmeldung][1], damit wir den Kurs weiter verbessern können. \n" +"Was uns besonders interessieren würde ist was gut funktioniert hat aber auch was wir verbessern " +"könnten.\n" +"Deine Teilnehmer sind natürlich auch herzlich eingeladen, [uns Rückmeldung zu geben][2]!" #: src/running-the-course/course-structure.md:1 -#, fuzzy msgid "# Course Structure" msgstr "# Kursstruktur" #: src/running-the-course/course-structure.md:5 -#, fuzzy msgid "The course is fast paced and covers a lot of ground:" -msgstr "Der Kurs ist schnelllebig und deckt viel Boden ab:" +msgstr "Der Kurs geht in schnellem Tempo voran und deckt viele Themen ab:" #: src/running-the-course/course-structure.md:7 -#, fuzzy 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 interoperability with other languages" +"* Day 4: Concurrency in Rust and seeing Rust in action." msgstr "" -"* Tag 1: Basic Rust, Eigentum und der Leihenprüfer.\n" -"* Tag 2: Zusammengesetzte Datentypen, Mustervergleich, die Standardbibliothek.\n" -"* Tag 3: Traits und Generika, Fehlerbehandlung, Testen, unsicheres Rust.\n" -"* Tag 4: Parallelität in Rust und Interoperabilität mit anderen Sprachen" +"* 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." #: src/running-the-course/course-structure.md:12 -#, fuzzy -msgid "" -"> **Exercise for Day 4:** Do you interface with some C/C++ code in your project\n" -"> which we could attempt to move to Rust? The fewer dependencies the better.\n" -"> Parsing code would be ideal." -msgstr "" -"> **Übung für Tag 4:** Arbeiten Sie in Ihrem Projekt mit C/C++-Code zusammen?\n" -"> die wir versuchen könnten, nach Rust zu verlegen? Je weniger Abhängigkeiten, desto besser.\n" -"> Parsing-Code wäre ideal." - -#: src/running-the-course/course-structure.md:16 -#, fuzzy msgid "## Format" msgstr "## Format" -#: src/running-the-course/course-structure.md:18 -#, fuzzy +#: src/running-the-course/course-structure.md:14 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 sein und wir empfehlen, die\n" -"Fragen treiben die Erkundung von Rust voran!" +"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 -#, fuzzy -msgid "# Keyboard Shortcuts" -msgstr "# Tastatürkürzel" +#: src/running-the-course/day-4.md:1 +msgid "# Day 4" +msgstr "# Tag 4" -#: src/running-the-course/keyboard-shortcuts.md:3 -#, fuzzy -msgid "There are several useful keyboard shortcuts in mdBook:" -msgstr "Es gibt mehrere nützliche Tastaturkürzel in mdBook:" +#: src/running-the-course/day-4.md:5 +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." -#: src/running-the-course/keyboard-shortcuts.md:5 -#, fuzzy +#: src/running-the-course/day-4.md:9 msgid "" -"* Arrow-Left: Navigate to the previous page.\n" -"* Arrow-Right: Navigate to the next page.\n" -"* Ctrl + Enter: Execute the code sample that has focus.\n" -"* s: Activate the search bar." +"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 "" -"* Pfeil-links: Zur vorherigen Seite navigieren.\n" -"* Pfeil-rechts: Zur nächsten Seite navigieren.\n" -"* Strg + Eingabe: Führt das Codebeispiel aus, das den Fokus hat.\n" -"* s: Suchleiste aktivieren." +"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/cargo.md:1 -#, fuzzy -msgid "# Using Cargo" -msgstr "# Verwenden von Fracht" +#: src/running-the-course/day-4.md:13 +msgid "Some topics need additional preparation:" +msgstr "Manche Themen benötigen eine besondere Vorbereitung:" -#: src/cargo.md:3 -#, fuzzy +#: src/running-the-course/day-4.md:15 +msgid "## Android" +msgstr "## Android" + +#: src/running-the-course/day-4.md:17 msgid "" -"When you start reading about Rust, you will soon meet [Cargo](https://doc.rust-lang.org/cargo/), " -"the standard tool\n" -"used in the Rust ecosystem to build and run Rust applications. Here we want to\n" -"give a brief overview of what Cargo is and how it fits into the wider ecosystem\n" -"and how it fits into this training." +"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/`." msgstr "" -"Wenn Sie anfangen, über Rust zu lesen, werden Sie bald [Cargo](https://doc.rust-lang.org/cargo/), " -"das Standardwerkzeug, kennenlernen\n" -"Wird im Rust-Ökosystem verwendet, um Rust-Anwendungen zu erstellen und auszuführen. Hier wollen " -"wir\n" -"geben einen kurzen Überblick darüber, was Cargo ist und wie es in das breitere Ökosystem passt\n" -"und wie es in dieses Training passt." +"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" +" auf deinem Laptop und verschiebe das Verzeichnis `src/android/` in \n" +" das Stammverzeichnis Deiner AOSP Arbeitskopie . Dadurch wird \n" +" sichergestellt, dass das Android-Buildsystem die \n" +" `Android.bp`-Dateien in `src/android/` sehen kann." + +#: src/running-the-course/day-4.md:22 +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." +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." + +#: src/running-the-course/day-4.md:26 +msgid "## Async" +msgstr "## Async" + +#: src/running-the-course/day-4.md:28 +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." +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." + +#: src/running-the-course/day-4.md:32 +msgid "" +"```shell\n" +"cargo init day4\n" +"cd day4\n" +"cargo add tokio --features full\n" +"cargo run\n" +"```" +msgstr "" + +#: src/running-the-course/keyboard-shortcuts.md:1 +msgid "# Keyboard Shortcuts" +msgstr "# Tastaturkürzel" + +#: src/running-the-course/keyboard-shortcuts.md:3 +msgid "There are several useful keyboard shortcuts in mdBook:" +msgstr "Es gibt mehrere nützliche Tastaturkürzel in mdBook:" + +#: src/running-the-course/keyboard-shortcuts.md:5 +msgid "" +"* Arrow-Left: Navigate to the previous page.\n" +"* Arrow-Right: Navigate to the next page.\n" +"* Ctrl + Enter: Execute the code sample that has focus.\n" +"* s: Activate the search bar." +msgstr "" +"* Pfeil-links: Zur vorherigen Seite navigieren.\n" +"* Pfeil-rechts: Zur nächsten Seite navigieren.\n" +"* Strg + Eingabe: Führe das Codebeispiel aus, das aktuell den Fokus hat.\n" +"* s: Suchleiste aktivieren." + +#: src/running-the-course/translations.md:1 +msgid "# Translations" +msgstr "# Übersetzungen" + +#: src/running-the-course/translations.md:3 +msgid "" +"The course has been translated into other languages by a set of wonderful\n" +"volunteers:" +msgstr "Der Kurs wurde auch in andere Sprachen übersetzt:" + +#: src/running-the-course/translations.md:6 +msgid "" +"* [Brazilian Portuguese][pt-BR] by [@rastringer] and [@hugojacob].\n" +"* [Korean][ko] by [@keispace], [@jiyongp] and [@jooyunghan]." +msgstr "" +"* [Brasilianisches Portugiesisch][pt-BR] von [@rastringer] und [@hugojacob].\n" +"* [Koreanisch][ko] von [@keispace], [@jiyongp] und [@jooyunghan]." + +#: src/running-the-course/translations.md:9 +msgid "Use the language picker in the top-right corner to switch between languages." +msgstr "Benutze die Sprachenauswahl oben rechts, um die Sprache zu wechseln." + +#: src/running-the-course/translations.md:11 +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]." +msgstr "" +"Wenn du uns hierbei unterstützen möchtest, lies dir bitte [unsere Anweisungen][our instructions] " +"durch.\n" +"Übersetzungen werden mit dem [Issue-Tracker][issue tracker] koordiniert." + +#: src/cargo.md:1 +msgid "# Using Cargo" +msgstr "# Cargo verwenden" + +#: src/cargo.md:3 +msgid "" +"When you start reading about Rust, you will soon meet [Cargo](https://doc.rust-lang.org/cargo/), " +"the standard tool\n" +"used in the Rust ecosystem to build and run Rust applications. Here we want to\n" +"give a brief overview of what Cargo is and how it fits into the wider ecosystem\n" +"and how it fits into this training." +msgstr "" +"Wenn du anfängst über Rust zu lesen, wirst du sehr bald [Cargo](https://doc.rust-lang.org/" +"cargo/), \n" +"ein Standardwerkzeug, welches im Rust-Ökosystem verwendet wird, um Rust-Anwendungen zu erstellen \n" +"und auszuführen, kennenlernen. Hier wollen wir einen kurzen Überblick geben, was Cargo ist und wie " +"es\n" +"in das breitere Ökosystem und in dieses Training passt." #: src/cargo.md:8 -#, fuzzy msgid "## Installation" msgstr "## Installation" #: src/cargo.md:10 -#, fuzzy msgid "### Rustup (Recommended)" msgstr "### Rustup (empfohlen)" #: src/cargo.md:12 -#, fuzzy msgid "" "You can follow the instructions to install cargo and rust compiler, among other standard ecosystem " "tools with the [rustup][3] tool, which is maintained by the Rust Foundation." msgstr "" -"Sie können den Anweisungen zur Installation des Cargo- und Rust-Compilers sowie anderer Standard-" +"Du kannst den Anweisungen zur Installation von Cargo und des Rust-Compilers sowie anderer Standard-" "Ökosystem-Tools mit dem Tool [rustup][3] folgen, das von der Rust Foundation verwaltet wird." #: src/cargo.md:14 -#, fuzzy msgid "" "Along with cargo and rustc, Rustup will install itself as a command line utility that you can use " "to install/switch toolchains, setup cross compilation, etc." msgstr "" -"Zusammen mit Cargo und Rustc installiert sich Rustup selbst als Befehlszeilendienstprogramm, mit " -"dem Sie Toolchains installieren/wechseln, Cross-Compilation einrichten usw. können." +"Neben cargo und rustc installiert sich rustup selbst als Befehlszeilenprogramm, mit welchem du " +"Toolchains installieren/wechseln, oder cross-Kompilierung einrichten kannst." #: src/cargo.md:16 -#, fuzzy msgid "### Package Managers" msgstr "### Paketmanager" #: src/cargo.md:18 -#, fuzzy msgid "#### Debian" msgstr "#### Debian" #: src/cargo.md:20 #, fuzzy -msgid "On Debian/Ubuntu, you can install Cargo and the Rust source with" -msgstr "Auf Debian/Ubuntu können Sie Cargo und die Rust-Quelle mit installieren" +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:" #: src/cargo.md:22 msgid "" "```shell\n" -"$ sudo apt install cargo rust-src\n" +"$ sudo apt install cargo rust-src rustfmt\n" "```" msgstr "" #: src/cargo.md:26 -#, fuzzy msgid "" "This will allow [rust-analyzer][1] to jump to the definitions. We suggest using\n" "[VS Code][2] to edit the code (but any LSP compatible editor works)." msgstr "" "Dadurch kann [rust-analyzer][1] zu den Definitionen springen. Wir empfehlen die Verwendung\n" -"[VS Code][2], um den Code zu bearbeiten (aber jeder LSP-kompatible Editor funktioniert)." +"von [VS Code][2], um Code zu bearbeiten (aber jeder LSP-kompatible Editor funktioniert auch)." #: src/cargo.md:29 -#, fuzzy msgid "" "Some folks also like to use the [JetBrains][4] family of IDEs, which do their own analysis but " "have their own tradeoffs. If you prefer them, you can install the [Rust Plugin][5]. Please take " "note that as of January 2023 debugging only works on the CLion version of the JetBrains IDEA suite." msgstr "" -"Einige Leute verwenden auch gerne die [JetBrains][4]-Familie von IDEs, die ihre eigene Analyse " -"durchführen, aber ihre eigenen Kompromisse haben. Wenn Sie sie bevorzugen, können Sie das [Rust-" -"Plugin] [5] installieren. Bitte beachten Sie, dass das Debuggen ab Januar 2023 nur auf der CLion-" -"Version der JetBrains IDEA-Suite funktioniert." - -#: src/cargo.md:31 -#, fuzzy -msgid "" -"[1]: https://rust-analyzer.github.io/\n" -"[2]: https://code.visualstudio.com/\n" -"[3]: https://rustup.rs/\n" -"[4]: https://www.jetbrains.com/clion/\n" -"[5]: https://www.jetbrains.com/rust/" -msgstr "" -"[1]: https://rust-analyzer.github.io/\n" -"[2]: https://code.visualstudio.com/\n" -"[3]: https://rustup.rs/\n" -"[4]: https://www.jetbrains.com/clion/\n" -"[5]: https://www.jetbrains.com/rust/" +"Einige Leute verwenden auch gerne die [JetBrains][4]-Familie von IDEs, die eigene Code-Analysen " +"durchführen, aber auch eigene Einschränkungen haben. Wenn du diese IDEs bevorzugst, kannst du das " +"[Rust-Plugin] [5] installieren. Bitte beachte, dass das Debuggen seit Januar 2023 nur auf der " +"CLion-Version funktioniert, welche Teil der JetBrains IDEA-Suite ist." #: src/cargo/rust-ecosystem.md:1 -#, fuzzy msgid "# The Rust Ecosystem" -msgstr "# Das Rost-Ökosystem" +msgstr "# Das Rust-Ökosystem" #: src/cargo/rust-ecosystem.md:3 -#, fuzzy msgid "The Rust ecosystem consists of a number of tools, of which the main ones are:" -msgstr "Das Rust-Ökosystem besteht aus einer Reihe von Tools, von denen die wichtigsten sind:" +msgstr "" +"Das Rust-Ökosystem besteht aus einer Reihe von Werkzeugen, von denen die wichtigsten die Folgenden " +"sind:" #: src/cargo/rust-ecosystem.md:5 #, fuzzy msgid "" "* `rustc`: the Rust compiler which turns `.rs` files into binaries and other\n" -" intermediate formats[^rustc]." -msgstr "" -"* „rustc“: der Rust-Compiler, der „.rs“-Dateien in Binärdateien und andere umwandelt\n" -" Zwischenformate[^rustc]." - -#: src/cargo/rust-ecosystem.md:8 -#, fuzzy -msgid "" +" intermediate formats.\n" +"\n" "* `cargo`: the Rust dependency manager and build tool. Cargo knows how to\n" " download dependencies hosted on and it will pass them to\n" " `rustc` when building your project. Cargo also comes with a built-in test\n" -" runner which is used to execute unit tests[^cargo]." -msgstr "" -"* `cargo`: der Rust-Abhängigkeitsmanager und Build-Tool. Cargo weiß, wie es geht\n" -" Laden Sie Abhängigkeiten herunter, die auf gehostet werden, und es wird sie " -"an sie weitergeben\n" -" `rustc`, wenn Sie Ihr Projekt erstellen. Cargo kommt auch mit einem eingebauten Test\n" -" Runner, der zum Ausführen von Unit-Tests[^cargo] verwendet wird." - -#: src/cargo/rust-ecosystem.md:13 -#, fuzzy -msgid "" +" runner which is used to execute unit tests.\n" +"\n" "* `rustup`: the Rust toolchain installer and updater. This tool is used to\n" " install and update `rustc` and `cargo` when new versions of Rust is released.\n" " In addition, `rustup` can also download documentation for the standard\n" @@ -1340,86 +1676,39 @@ msgstr "" #: src/cargo/rust-ecosystem.md:21 src/hello-world.md:25 src/hello-world/small-example.md:27 #: src/why-rust/runtime.md:10 src/why-rust/modern.md:21 src/basic-syntax/compound-types.md:30 -#: src/error-handling/try-operator.md:50 src/error-handling/converting-error-types.md:68 -#: src/concurrency/threads.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 msgid "Key points:" msgstr "Kernpunkte:" #: src/cargo/rust-ecosystem.md:23 -#, fuzzy msgid "" "* Rust has a rapid release schedule with a new release coming out\n" " every six weeks. New releases maintain backwards compatibility with\n" -" old releases --- plus they enable new functionality." -msgstr "" -"* Rust hat einen schnellen Veröffentlichungszeitplan mit einer neuen Veröffentlichung, die " -"herauskommt\n" -" alle sechs Wochen. Neue Releases behalten die Abwärtskompatibilität mit\n" -" alte Versionen --- und sie ermöglichen neue Funktionen." - -#: src/cargo/rust-ecosystem.md:27 -#, fuzzy -msgid "* There are three release channels: \"stable\", \"beta\", and \"nightly\"." -msgstr "* Es gibt drei Veröffentlichungskanäle: „Stable“, „Beta“ und „Nightly“." - -#: src/cargo/rust-ecosystem.md:29 -#, fuzzy -msgid "" +" old releases --- plus they enable new functionality.\n" +"\n" +"* There are three release channels: \"stable\", \"beta\", and \"nightly\".\n" +"\n" "* New features are being tested on \"nightly\", \"beta\" is what becomes\n" -" \"stable\" every six weeks." -msgstr "" -"* Neue Funktionen werden auf \"Nightly\" getestet, \"Beta\" ist das, was wird\n" -" \"stabil\" alle sechs Wochen." - -#: src/cargo/rust-ecosystem.md:32 -#, fuzzy -msgid "" +" \"stable\" every six weeks.\n" +"\n" "* Rust also has [editions]: the current edition is Rust 2021. Previous\n" -" editions were Rust 2015 and Rust 2018." -msgstr "" -"* Rust hat auch [Editionen]: Die aktuelle Edition ist Rust 2021. Zurück\n" -" Editionen waren Rust 2015 und Rust 2018." - -#: src/cargo/rust-ecosystem.md:35 -#, fuzzy -msgid "" +" editions were Rust 2015 and Rust 2018.\n" +"\n" " * The editions are allowed to make backwards incompatible changes to\n" -" the language." -msgstr "" -" * Die Editionen dürfen rückwärtsinkompatible Änderungen vornehmen\n" -" die Sprache." - -#: src/cargo/rust-ecosystem.md:38 -#, fuzzy -msgid "" +" the language.\n" +"\n" " * To prevent breaking code, editions are opt-in: you select the\n" -" edition for your crate via the `Cargo.toml` file." -msgstr "" -" * Um das Brechen von Code zu verhindern, sind Editionen Opt-in: Sie wählen die aus\n" -" Edition für Ihre Kiste über die Datei `Cargo.toml`." - -#: src/cargo/rust-ecosystem.md:41 -#, fuzzy -msgid "" +" edition for your crate via the `Cargo.toml` file.\n" +"\n" " * To avoid splitting the ecosystem, Rust compilers can mix code\n" -" written for different editions." -msgstr "" -" * Um eine Aufspaltung des Ökosystems zu vermeiden, können Rust-Compiler Code mischen\n" -" für verschiedene Editionen geschrieben." - -#: src/cargo/rust-ecosystem.md:44 -#, fuzzy -msgid "" +" written for different editions.\n" +"\n" " * Mention that it is quite rare to ever use the compiler directly not through `cargo` (most " -"users never do)." -msgstr "" -" * Erwähnen Sie, dass es ziemlich selten vorkommt, den Compiler jemals direkt zu verwenden, nicht " -"über `cargo` (die meisten Benutzer tun dies nie)." - -#: src/cargo/rust-ecosystem.md:46 -#, fuzzy -msgid "" +"users never do).\n" +"\n" " * It might be worth alluding that Cargo itself is an extremely powerful and comprehensive tool. " "It is capable of many advanced features including but not limited to: \n" " * Project/package structure\n" @@ -1430,46 +1719,6 @@ msgid "" " * It is also extensible with sub command plugins as well (such as [cargo clippy]).\n" " * Read more from the [official Cargo Book]" msgstr "" -" * Es könnte erwähnenswert sein, dass Cargo selbst ein äußerst leistungsfähiges und umfassendes " -"Werkzeug 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" -" * [Skript erstellen]\n" -" * [globale Installation]\n" -" * Es ist auch mit Unterbefehls-Plugins erweiterbar (wie [cargo clippy]).\n" -" * Lesen Sie mehr aus dem [offiziellen Frachtbuch]" - -#: src/cargo/rust-ecosystem.md:55 -#, fuzzy -msgid "[editions]: https://doc.rust-lang.org/edition-guide/" -msgstr "[Ausgaben]: https://doc.rust-lang.org/edition-guide/" - -#: src/cargo/rust-ecosystem.md:57 -#, fuzzy -msgid "[workspaces]: https://doc.rust-lang.org/cargo/reference/workspaces.html" -msgstr "[Arbeitsbereiche]: https://doc.rust-lang.org/cargo/reference/workspaces.html" - -#: src/cargo/rust-ecosystem.md:59 -#, fuzzy -msgid "[build scripting]: https://doc.rust-lang.org/cargo/reference/build-scripts.html" -msgstr "[Build-Scripting]: https://doc.rust-lang.org/cargo/reference/build-scripts.html" - -#: src/cargo/rust-ecosystem.md:61 -#, fuzzy -msgid "[global installation]: https://doc.rust-lang.org/cargo/commands/cargo-install.html" -msgstr "[globale Installation]: https://doc.rust-lang.org/cargo/commands/cargo-install.html" - -#: src/cargo/rust-ecosystem.md:63 -#, fuzzy -msgid "[cargo clippy]: https://github.com/rust-lang/rust-clippy" -msgstr "[cargo clippy]: https://github.com/rust-lang/rust-clippy" - -#: src/cargo/rust-ecosystem.md:65 -#, fuzzy -msgid "[official Cargo Book]: https://doc.rust-lang.org/cargo/" -msgstr "[offizielles Frachtbuch]: https://doc.rust-lang.org/cargo/" #: src/cargo/code-samples.md:1 #, fuzzy @@ -1535,14 +1784,8 @@ msgstr "" #, 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." -msgstr "" -"* Die eingebetteten Playgrounds können keine Unit-Tests ausführen. Kopieren Sie die\n" -" code und öffnen Sie ihn im realen Playground, um Unit-Tests zu demonstrieren." - -#: src/cargo/code-samples.md:30 -#, fuzzy -msgid "" +" code and open it in the real Playground to demonstrate unit tests.\n" +"\n" "* The embedded playgrounds lose their state the moment you navigate\n" " away from the page! This is the reason that the students should\n" " solve the exercises using a local Rust installation or via the\n" @@ -1592,36 +1835,18 @@ msgstr "" "der Beispiele in diesem Training:" #: src/cargo/running-locally.md:18 -#, fuzzy -msgid "1. Click the \"Copy to clipboard\" button on the example you want to copy." -msgstr "" -"1. Klicken Sie bei dem Beispiel, das Sie kopieren möchten, auf die Schaltfläche \"In die " -"Zwischenablage kopieren\"." - -#: src/cargo/running-locally.md:20 -#, fuzzy -msgid "2. Use `cargo new exercise` to create a new `exercise/` directory for your code:" -msgstr "" -"2. Verwenden Sie `cargo new Exercise`, um ein neues `exercise/`-Verzeichnis für Ihren Code zu " -"erstellen:" - -#: src/cargo/running-locally.md:22 msgid "" +"1. Click the \"Copy to clipboard\" button on the example you want to copy.\n" +"\n" +"2. Use `cargo new exercise` to create a new `exercise/` directory for your code:\n" +"\n" " ```shell\n" " $ cargo new exercise\n" " Created binary (application) `exercise` package\n" -" ```" -msgstr "" - -#: src/cargo/running-locally.md:27 -#, fuzzy -msgid "3. Navigate into `exercise/` and use `cargo run` to build and run your binary:" -msgstr "" -"3. Navigieren Sie zu „exercise/“ und verwenden Sie „cargo run“, um Ihre Binärdatei zu erstellen " -"und auszuführen:" - -#: src/cargo/running-locally.md:29 -msgid "" +" ```\n" +"\n" +"3. Navigate into `exercise/` and use `cargo run` to build and run your binary:\n" +"\n" " ```shell\n" " $ cd exercise\n" " $ cargo run\n" @@ -1629,74 +1854,36 @@ msgid "" " Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" " Running `target/debug/exercise`\n" " Hello, world!\n" -" ```" -msgstr "" - -#: src/cargo/running-locally.md:38 -#, fuzzy -msgid "" +" ```\n" +"\n" "4. Replace the boiler-plate code in `src/main.rs` with your own code. For\n" -" example, using the example on the previous page, make `src/main.rs` look like" -msgstr "" -"4. Ersetzen Sie den Standardcode in `src/main.rs` durch Ihren eigenen Code. Für\n" -" Verwenden Sie beispielsweise das Beispiel auf der vorherigen Seite und lassen Sie `src/main.rs` " -"so aussehen" - -#: src/cargo/running-locally.md:41 -msgid "" +" example, using the example on the previous page, make `src/main.rs` look like\n" +"\n" " ```rust\n" " fn main() {\n" " println!(\"Edit me!\");\n" " }\n" -" ```" -msgstr "" - -#: src/cargo/running-locally.md:47 -#, fuzzy -msgid "5. Use `cargo run` to build and run your updated binary:" -msgstr "5. Verwenden Sie „cargo run“, um Ihre aktualisierte Binärdatei zu erstellen und auszuführen:" - -#: src/cargo/running-locally.md:49 -msgid "" +" ```\n" +"\n" +"5. Use `cargo run` to build and run your updated binary:\n" +"\n" " ```shell\n" " $ cargo run\n" " Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" " Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" " Running `target/debug/exercise`\n" " Edit me!\n" -" ```" -msgstr "" - -#: src/cargo/running-locally.md:57 -#, fuzzy -msgid "" +" ```\n" +"\n" "6. Use `cargo check` to quickly check your project for errors, use `cargo build`\n" " to compile it without running it. You will find the output in `target/debug/`\n" " for a normal debug build. Use `cargo build --release` to produce an optimized\n" -" release build in `target/release/`." -msgstr "" -"6. Verwenden Sie „Cargo Check“, um Ihr Projekt schnell auf Fehler zu überprüfen, verwenden Sie " -"„Cargo Build“.\n" -" um es zu kompilieren, ohne es auszuführen. Die Ausgabe finden Sie in `target/debug/`\n" -" für einen normalen Debug-Build. Verwenden Sie `cargo build --release`, um eine optimierte\n" -" Release-Build in `target/release/`." - -#: src/cargo/running-locally.md:62 -#, fuzzy -msgid "" +" release build in `target/release/`.\n" +"\n" "7. You can add dependencies for your project by editing `Cargo.toml`. When you\n" " run `cargo` commands, it will automatically download and compile missing\n" " dependencies for you." msgstr "" -"7. Sie können Abhängigkeiten für Ihr Projekt hinzufügen, indem Sie `Cargo.toml` bearbeiten. Wenn " -"du\n" -" Führen Sie \"Cargo\"-Befehle aus, es wird automatisch heruntergeladen und kompiliert\n" -" Abhängigkeiten für Sie." - -#: src/cargo/running-locally.md:66 -#, fuzzy -msgid "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" -msgstr "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" #: src/cargo/running-locally.md:70 #, fuzzy @@ -1724,28 +1911,15 @@ msgstr "" "Heute:" #: src/welcome-day-1.md:6 -#, fuzzy msgid "" "* Basic Rust syntax: variables, scalar and compound types, enums, structs,\n" -" references, functions, and methods." -msgstr "" -"* Grundlegende Rust-Syntax: Variablen, skalare und zusammengesetzte Typen, Aufzählungen, " -"Strukturen,\n" -" Referenzen, Funktionen und Methoden." - -#: src/welcome-day-1.md:9 -#, fuzzy -msgid "" +" references, functions, and methods.\n" +"\n" "* Memory management: stack vs heap, manual memory management, scope-based memory\n" -" management, and garbage collection." +" management, and garbage collection.\n" +"\n" +"* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." msgstr "" -"* Speicherverwaltung: Stack vs. Heap, manuelle Speicherverwaltung, bereichsbasierter Speicher\n" -" Verwaltung und Garbage Collection." - -#: src/welcome-day-1.md:12 -#, fuzzy -msgid "* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." -msgstr "* Eigentum: Verschieben von Semantik, Kopieren und Klonen, Ausleihen und Lebensdauern." #: src/welcome-day-1.md:16 #, fuzzy @@ -1761,8 +1935,8 @@ msgid "" " 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" -"* The questions will likely mean that we about things ahead of the slides.\n" -" * This is perfectly okay! Repetition is an important part of leaning. Remember\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 "" @@ -1825,7 +1999,7 @@ msgstr "# Was ist Rost?" #: 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:" +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 @@ -1930,30 +2104,20 @@ msgstr "" "eine Tonne davon in den nächsten vier Tagen, also fangen wir klein mit etwas Vertrautem an." #: src/hello-world.md:27 -#, fuzzy msgid "" "* Rust is very much like other languages in the C/C++/Java tradition. It is\n" " imperative (not functional) and it doesn't try to reinvent things unless\n" -" absolutely necessary." -msgstr "" -"* Rust ist anderen Sprachen in der C/C++/Java-Tradition sehr ähnlich. Es ist\n" -" Imperativ (nicht funktional) und es versucht nicht, Dinge neu zu erfinden, es sei denn\n" -" absolut notwendig." - -#: src/hello-world.md:31 -#, fuzzy -msgid "* Rust is modern with full support for things like Unicode." -msgstr "* Rust ist modern mit voller Unterstützung für Dinge wie Unicode." - -#: src/hello-world.md:33 -#, fuzzy -msgid "" +" absolutely necessary.\n" +"\n" +"* Rust is modern with full support for things like Unicode.\n" +"\n" "* Rust uses macros for situations where you want to have a variable number of\n" -" arguments (no function [overloading](basic-syntax/functions-interlude.md))." +" arguments (no function [overloading](basic-syntax/functions-interlude.md)).\n" +"\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)." msgstr "" -"* Rust verwendet Makros für Situationen, in denen Sie eine variable Anzahl von Makros haben " -"möchten\n" -" Argumente (keine Funktion [Überladen] (Grundsyntax/Funktionen-Zwischenspiel.md))." #: src/hello-world/small-example.md:1 #, fuzzy @@ -1997,50 +2161,22 @@ msgstr "" "Eingänge." #: src/hello-world/small-example.md:29 -#, fuzzy msgid "" "* Explain that all variables are statically typed. Try removing `i32` to trigger\n" -" type inference. Try with `i8` instead and trigger a runtime integer overflow." -msgstr "" -"* Erklären Sie, dass alle Variablen statisch typisiert sind. Versuchen Sie, „i32“ zu entfernen, um " -"auszulösen\n" -" Typ Inferenz. Versuchen Sie es stattdessen mit \"i8\" und lösen Sie einen Integer-Überlauf zur " -"Laufzeit aus." - -#: src/hello-world/small-example.md:32 -#, fuzzy -msgid "* Change `let mut x` to `let x`, discuss the compiler error." -msgstr "* Ändere `let mut x` in `let x`, diskutiere den Compiler-Fehler." - -#: src/hello-world/small-example.md:34 -#, fuzzy -msgid "" +" type inference. Try with `i8` instead and trigger a runtime integer overflow.\n" +"\n" +"* Change `let mut x` to `let x`, discuss the compiler error.\n" +"\n" "* Show how `print!` gives a compilation error if the arguments don't match the\n" -" format string." -msgstr "" -"* Zeigen Sie, wie `print!` einen Kompilierungsfehler ausgibt, wenn die Argumente nicht " -"übereinstimmen\n" -" Zeichenfolge formatieren." - -#: src/hello-world/small-example.md:37 -#, fuzzy -msgid "" +" format string.\n" +"\n" "* Show how you need to use `{}` as a placeholder if you want to print an\n" -" expression which is more complex than just a single variable." -msgstr "" -"* Zeigen Sie, wie Sie `{}` als Platzhalter verwenden müssen, wenn Sie eine drucken möchten\n" -" Ausdruck, der komplexer ist als nur eine einzelne Variable." - -#: src/hello-world/small-example.md:40 -#, fuzzy -msgid "" +" expression which is more complex than just a single variable.\n" +"\n" "* Show the students the standard library, show them how to search for `std::fmt`\n" " 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 "" -"* Zeigen Sie den Schülern die Standardbibliothek, zeigen Sie ihnen, wie man nach `std::fmt` sucht\n" -" die die Regeln der Formatierungsminisprache hat. Wichtig ist, dass die\n" -" Die Schüler lernen die Suche in der Standardbibliothek kennen." #: src/why-rust.md:1 #, fuzzy @@ -2078,16 +2214,8 @@ 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" " have the memory unsafety issues. In addition, you get a modern language with\n" -" constructs like pattern matching and built-in dependency management." -msgstr "" -"* Erfahrung mit C oder C++: Rust eliminiert eine ganze Klasse von _Laufzeitfehlern_\n" -" über den Ausleihprüfer. Sie erhalten eine Leistung wie in C und C++, aber Sie tun es nicht\n" -" habe die Speicherunsicherheitsprobleme. Außerdem bekommt man eine moderne Sprache mit\n" -" Konstrukte wie Musterabgleich und integriertes Abhängigkeitsmanagement." - -#: src/why-rust.md:19 -#, fuzzy -msgid "" +" constructs like pattern matching and built-in dependency management.\n" +"\n" "* Experience with Java, Go, Python, JavaScript...: You get the same memory safety\n" " as in those languages, plus a similar high-level language feeling. In addition\n" " you get fast and predictable performance like C and C++ (no garbage collector)\n" @@ -2168,17 +2296,6 @@ msgstr "" "Für die Zwecke dieses Kurses sollte \"Keine Speicherlecks\" verstanden werden\n" "als \"so gut wie keine *versehentlichen* Speicherlecks\"." -#: src/why-rust/compile-time.md:31 -#, fuzzy -msgid "" -"[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak\n" -"[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" -"[reference cycle]: https://doc.rust-lang.org/book/ch15-06-reference-cycles.html" -msgstr "" -"[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak\n" -"[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" -"[Referenzzyklus]: https://doc.rust-lang.org/book/ch15-06-reference-cycles.html" - #: src/why-rust/runtime.md:1 #, fuzzy msgid "# Runtime Guarantees" @@ -2204,25 +2321,17 @@ 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" " semantics. By default, you get panics in debug mode (`cargo build`)\n" -" and wrap-around in release mode (`cargo build --release`)." -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`)." - -#: src/why-rust/runtime.md:17 -#, fuzzy -msgid "" +" and wrap-around in release mode (`cargo build --release`).\n" +"\n" "* Bounds checking cannot be disabled with a compiler flag. It can also\n" " not be disabled directly with the `unsafe` keyword. However,\n" " `unsafe` allows you to call functions such as `slice::get_unchecked`\n" " which does not do bounds checking." msgstr "" -"* Die Begrenzungsprüfung kann nicht mit einem Compiler-Flag deaktiviert werden. Es kann auch\n" -" nicht direkt mit dem Schlüsselwort „unsafe“ deaktiviert werden. Jedoch,\n" -" `unsafe` erlaubt Ihnen, Funktionen wie `slice::get_unchecked` aufzurufen\n" -" die keine Begrenzungsprüfung durchführt." +"* 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`)." #: src/why-rust/modern.md:1 #, fuzzy @@ -2271,92 +2380,38 @@ msgstr "" "* Hervorragende Unterstützung des Language Server Protocol." #: src/why-rust/modern.md:23 -#, fuzzy msgid "" "* Zero-cost abstractions, similar to C++, means that you don't have to 'pay'\n" " for higher-level programming constructs with memory or CPU. For example,\n" " writing a loop using `for` should result in roughly the same low level\n" -" instructions as using the `.iter().fold()` construct." -msgstr "" -"* Zero-Cost-Abstraktionen, ähnlich wie C++, bedeutet, dass Sie nicht „bezahlen“ müssen\n" -" für übergeordnete Programmierkonstrukte mit Speicher oder CPU. Zum Beispiel,\n" -" Das Schreiben einer Schleife mit `for` sollte ungefähr den gleichen niedrigen Pegel ergeben\n" -" Anweisungen wie die Verwendung des `.iter().fold()`-Konstrukts." - -#: src/why-rust/modern.md:28 -#, fuzzy -msgid "" +" instructions as using the `.iter().fold()` construct.\n" +"\n" "* It may be worth mentioning that Rust enums are 'Algebraic Data Types', also\n" " known as 'sum types', which allow the type system to express things like\n" -" `Option` and `Result`." -msgstr "" -"* Es sollte erwähnt werden, dass Rust-Enumerationen auch 'algebraische Datentypen' sind\n" -" bekannt als \"Summentypen\", die es dem Typsystem ermöglichen, Dinge wie auszudrücken\n" -" `Option` und `Ergebnis`." - -#: src/why-rust/modern.md:32 -#, fuzzy -msgid "" +" `Option` and `Result`.\n" +"\n" "* Remind people to read the errors --- many developers have gotten used to\n" " ignore lengthy compiler output. The Rust compiler is significantly more\n" " talkative than other compilers. It will often provide you with _actionable_\n" -" feedback, ready to copy-paste into your code." -msgstr "" -"* Erinnere die Leute daran, die Fehler zu lesen --- viele Entwickler haben sich daran gewöhnt\n" -" Ignoriere lange Compiler-Ausgaben. Der Rust-Compiler ist deutlich mehr\n" -" gesprächiger als andere Compiler. Es wird Ihnen oft _umsetzbare_\n" -" Feedback, bereit zum Kopieren und Einfügen in Ihren Code." - -#: src/why-rust/modern.md:37 -#, fuzzy -msgid "" +" feedback, ready to copy-paste into your code.\n" +"\n" "* The Rust standard library is small compared to languages like Java, Python,\n" " and Go. Rust does not come with several things you might consider standard and\n" -" essential:" -msgstr "" -"* Die Rust-Standardbibliothek ist klein im Vergleich zu Sprachen wie Java, Python,\n" -" Los geht. Rust kommt nicht mit einigen Dingen, die Sie als Standard betrachten könnten und\n" -" essentiell:" - -#: src/why-rust/modern.md:41 -#, fuzzy -msgid "" +" essential:\n" +"\n" " * a random number generator, but see [rand].\n" " * support for SSL or TLS, but see [rusttls].\n" -" * support for JSON, but see [serde_json]." -msgstr "" -" * ein Zufallszahlengenerator, aber siehe [rand].\n" -" * Unterstützung für SSL oder TLS, aber siehe [rusttls].\n" -" * Unterstützung für JSON, aber siehe [serde_json]." - -#: src/why-rust/modern.md:45 -#, fuzzy -msgid "" +" * support for JSON, but see [serde_json].\n" +"\n" " The reasoning behind this is that functionality in the standard library cannot\n" " go away, so it has to be very stable. For the examples above, the Rust\n" " community is still working on finding the best solution --- and perhaps there\n" -" isn't a single \"best solution\" for some of these things." -msgstr "" -" Der Grund dafür ist, dass die Funktionalität in der Standardbibliothek dies nicht kann\n" -" weggehen, also muss es sehr stabil sein. Für die obigen Beispiele ist die Rust\n" -" Die Community arbeitet immer noch daran, die beste Lösung zu finden --- und vielleicht gibt es " -"sie\n" -" ist für einige dieser Dinge keine einzige \"beste Lösung\"." - -#: src/why-rust/modern.md:50 -#, fuzzy -msgid "" +" isn't a single \"best solution\" for some of these things.\n" +"\n" " Rust comes with a built-in package manager in the form of Cargo and this makes\n" " it trivial to download and compile third-party crates. A consequence of this\n" -" is that the standard library can be smaller." -msgstr "" -" Rust kommt mit einem eingebauten Paketmanager in Form von Cargo und macht das\n" -" Es ist trivial, Crates von Drittanbietern herunterzuladen und zu kompilieren. Eine Folge davon\n" -" ist, dass die Standardbibliothek kleiner sein kann." - -#: src/why-rust/modern.md:54 -#, fuzzy -msgid "" +" is that the standard library can be smaller.\n" +"\n" " Discovering good third-party crates can be a problem. Sites like\n" " help with this by letting you compare health metrics for\n" " crates to find a good and trusted one.\n" @@ -2364,26 +2419,6 @@ msgid "" "* [rust-analyzer] is a well supported LSP implementation used in major\n" " IDEs and text editors." msgstr "" -" Das Entdecken guter Kisten von Drittanbietern kann ein Problem sein. Seiten wie\n" -" hilft dabei, indem es Ihnen ermöglicht, Gesundheitsmetriken für zu " -"vergleichen\n" -" Kisten, um eine gute und vertrauenswürdige zu finden.\n" -" \n" -"* [rust-analyzer] ist eine gut unterstützte LSP-Implementierung, die in Major verwendet wird\n" -" IDEs und Texteditoren." - -#: src/why-rust/modern.md:61 -#, fuzzy -msgid "" -"[rand]: https://docs.rs/rand/\n" -"[rusttls]: https://docs.rs/rustls/\n" -"[serde_json]: https://docs.rs/serde_json/\n" -"[rust-analyzer]: https://rust-analyzer.github.io/" -msgstr "" -"[rand]: https://docs.rs/rand/\n" -"[rusttls]: https://docs.rs/rustls/\n" -"[serde_json]: https://docs.rs/serde_json/\n" -"[Rostanalyzer]: https://rust-analyzer.github.io/" #: src/basic-syntax.md:1 #, fuzzy @@ -2392,7 +2427,7 @@ msgstr "# Grundlegende Syntax" #: src/basic-syntax.md:3 #, fuzzy -msgid "Much of the Rust syntax will be familiar to you from C or C++:" +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:" #: src/basic-syntax.md:5 @@ -2520,34 +2555,17 @@ msgstr "Arrays:" msgid "" "* Arrays have elements of the same type, `T`, and length, `N`, which is a compile-time constant.\n" " Note that the length of the array is *part of its type*, which means that `[u8; 3]` and\n" -" `[u8; 4]` are considered two different types." -msgstr "" - -#: src/basic-syntax/compound-types.md:38 -#, fuzzy -msgid "* We can use literals to assign values to arrays." -msgstr "* Wir können Literale verwenden, um Arrays Werte zuzuweisen." - -#: src/basic-syntax/compound-types.md:40 -#, fuzzy -msgid "" +" `[u8; 4]` are considered two different types.\n" +"\n" +"* We can use literals to assign values to arrays.\n" +"\n" "* In the main function, the print statement asks for the debug implementation with the `?` format\n" " parameter: `{}` gives the default output, `{:?}` gives the debug output. We\n" " could also have used `{a}` and `{a:?}` without specifying the value after the\n" -" format string." +" format string.\n" +"\n" +"* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read." msgstr "" -"* In der main-Funktion fragt die print-Anweisung nach der Debug-Implementierung mit dem `?`-" -"Format\n" -" Parameter: `{}` gibt die Standardausgabe, `{:?}` gibt die Debug-Ausgabe. Wir\n" -" hätte auch `{a}` und `{a:?}` verwenden können, ohne den Wert nach dem anzugeben\n" -" Zeichenfolge formatieren." - -#: src/basic-syntax/compound-types.md:45 -#, fuzzy -msgid "* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read." -msgstr "" -"* Das Hinzufügen von `#`, z. B. `{a:#?}`, ruft ein \"hübsches Druckformat\" auf, das einfacher zu " -"lesen sein kann." #: src/basic-syntax/compound-types.md:47 #, fuzzy @@ -2556,25 +2574,13 @@ msgstr "Tupel:" #: src/basic-syntax/compound-types.md:49 #, fuzzy -msgid "* Like arrays, tuples have a fixed length." -msgstr "* Tupel haben wie Arrays eine feste Länge." - -#: src/basic-syntax/compound-types.md:51 -#, fuzzy -msgid "* Tuples group together values of different types into a compound type." -msgstr "* Tupel fassen Werte verschiedener Typen zu einem zusammengesetzten Typ zusammen." - -#: src/basic-syntax/compound-types.md:53 -#, fuzzy -msgid "" -"* Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`." -msgstr "" -"* Auf Felder eines Tupels kann über den Punkt und den Index des Werts zugegriffen werden, z. " -"„t.0“, „t.1“." - -#: src/basic-syntax/compound-types.md:55 -#, fuzzy msgid "" +"* Like arrays, tuples have a fixed length.\n" +"\n" +"* Tuples group together values of different types into a compound type.\n" +"\n" +"* Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`.\n" +"\n" "* The empty tuple `()` is also known as the \"unit type\". It is both a type, and\n" " the only valid value of that type - that is to say both the type and its value\n" " are expressed as `()`. It is used to indicate, for example, that a function or\n" @@ -2636,9 +2642,7 @@ msgstr "" msgid "" "
\n" "Key points:" -msgstr "" -"
\n" -"Kernpunkte:" +msgstr "Kernpunkte:" #: src/basic-syntax/references.md:24 #, fuzzy @@ -2703,11 +2707,8 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" -" println!(\"a: {a:?}\");" -msgstr "" - -#: src/basic-syntax/slices.md:10 -msgid "" +" println!(\"a: {a:?}\");\n" +"\n" " let s: &[i32] = &a[2..4];\n" " println!(\"s: {s:?}\");\n" "}\n" @@ -2726,33 +2727,15 @@ msgstr "" #: src/basic-syntax/slices.md:20 #, fuzzy msgid "" -"* We create a slice by borrowing `a` and specifying the starting and ending indexes in brackets." -msgstr "" -"* Wir erstellen einen Slice, indem wir `a` ausleihen und den Anfangs- und Endindex in Klammern " -"angeben." - -#: src/basic-syntax/slices.md:22 -#, fuzzy -msgid "" +"* We create a slice by borrowing `a` and specifying the starting and ending indexes in brackets.\n" +"\n" "* If the slice starts at index 0, Rust’s range syntax allows us to drop the starting index, " "meaning that `&a[0..a.len()]` and `&a[..a.len()]` are identical.\n" " \n" -"* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are identical." -msgstr "" -"* Wenn der Slice 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" -"* Dasselbe gilt für den letzten Index, also sind `&a[2..a.len()]` und `&a[2..]` identisch." - -#: src/basic-syntax/slices.md:26 -#, fuzzy -msgid "* To easily create a slice of the full array, we can therefore use `&a[..]`." -msgstr "" -"* Um einfach einen Teil des gesamten Arrays zu erstellen, können wir daher `&a[..]` verwenden." - -#: src/basic-syntax/slices.md:28 -#, fuzzy -msgid "" +"* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are identical.\n" +"\n" +"* To easily create a slice of the full array, we can therefore use `&a[..]`.\n" +"\n" "* `s` is a reference to a slice of `i32`s. Notice that the type of `s` (`&[i32]`) no longer " "mentions the array length. This allows us to perform computation on slices of different sizes.\n" " \n" @@ -2793,11 +2776,8 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let s1: &str = \"World\";\n" -" println!(\"s1: {s1}\");" -msgstr "" - -#: src/basic-syntax/string-slices.md:10 -msgid "" +" println!(\"s1: {s1}\");\n" +"\n" " let mut s2: String = String::from(\"Hello \");\n" " println!(\"s2: {s2}\");\n" " s2.push_str(s1);\n" @@ -2827,26 +2807,15 @@ msgstr "" #, fuzzy msgid "" "* `&str` introduces a string slice, which is an immutable reference to UTF-8 encoded string data \n" -" stored in a block of memory. String literals (`”Hello”`), are stored in the program’s binary." -msgstr "" -"* `&str` führt ein String-Slice ein, das eine unveränderliche Referenz auf UTF-8-codierte String-" -"Daten ist\n" -" in einem Speicherblock gespeichert. String-Literale (`”Hallo”`) werden in der Binärdatei des " -"Programms gespeichert." - -#: src/basic-syntax/string-slices.md:30 -msgid "" +" stored in a block of memory. String literals (`”Hello”`), are stored in the program’s binary.\n" +"\n" "* Rust’s `String` type is a wrapper around a vector of bytes. As with a `Vec`, it is owned.\n" " \n" "* As with many other types `String::from()` creates a string from a string literal; `String::" "new()` \n" " creates a new empty string, to which string data can be added using the `push()` and " -"`push_str()` methods." -msgstr "" - -#: src/basic-syntax/string-slices.md:35 -#, fuzzy -msgid "" +"`push_str()` methods.\n" +"\n" "* The `format!()` macro is a convenient way to generate an owned string from dynamic values. It \n" " accepts the same format specification as `println!()`.\n" " \n" @@ -2856,8 +2825,7 @@ msgid "" " to a valid string in memory. Rust `String` is a rough equivalent of `std::string` from C++ \n" " (main difference: it can only contain UTF-8 encoded bytes and will never use a small-string " "optimization).\n" -" \n" -"
" +" " msgstr "" "* Das `format!()`-Makro ist eine bequeme Möglichkeit, einen eigenen String aus dynamischen Werten " "zu generieren. Es\n" @@ -2888,26 +2856,20 @@ 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" -"}" -msgstr "" - -#: src/basic-syntax/functions.md:10 -msgid "" +"}\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" -"}" -msgstr "" - -#: src/basic-syntax/functions.md:17 -#, fuzzy -msgid "" +"}\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" @@ -2915,7 +2877,14 @@ msgid "" " (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" @@ -2926,16 +2895,6 @@ msgstr "" " }\n" "}" -#: src/basic-syntax/functions.md:26 -msgid "" -"fn fizzbuzz_to(n: u32) { // `-> ()` is normally omitted\n" -" for i in 1..=n {\n" -" fizzbuzz(i);\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/basic-syntax/functions.md:35 msgid "" "* We refer in `main` to a function written below. Neither forward declarations nor headers are " @@ -2949,28 +2908,63 @@ msgid "" "* 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." -msgstr "" - -#: src/basic-syntax/functions.md:42 -#, fuzzy -msgid " (Type annotations added for clarity, but they can be elided.)" -msgstr "" -" (Typ-Anmerkungen wurden der Übersichtlichkeit halber hinzugefügt, können aber entfernt werden.)" - -#: src/basic-syntax/functions.md:44 -msgid "" +"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" +" " +msgstr "" + +#: src/basic-syntax/rustdoc.md:1 +#, fuzzy +msgid "# Rustdoc" +msgstr "# Warum Rost?" + +#: src/basic-syntax/rustdoc.md:3 +msgid "All language items in Rust can be documented using special `///` syntax." +msgstr "" + +#: src/basic-syntax/rustdoc.md:5 +msgid "" +"```rust,editable\n" +"/// Determine whether the first argument is divisible by the second argument.\n" +"///\n" +"/// If the second argument is zero, the result is false.\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" +"```" +msgstr "" + +#: src/basic-syntax/rustdoc.md:17 +msgid "" +"The contents are treated as Markdown. All published Rust library crates are\n" +"automatically documented at [`docs.rs`](https://docs.rs) using the\n" +"[rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It is\n" +"idiomatic to document all public items in an API using this pattern." msgstr "" -#: src/basic-syntax/functions.md:52 -msgid " " +#: src/basic-syntax/rustdoc.md:24 +msgid "" +"* Show students the generated docs for the `rand` crate at\n" +" [`docs.rs/rand`](https://docs.rs/rand).\n" +"\n" +"* This course does not include rustdoc on slides, just to save space, but in\n" +" real code they should be present.\n" +"\n" +"* Inner doc comments are discussed later (in the page on modules) and need not\n" +" be addressed here." msgstr "" #: src/basic-syntax/methods.md:1 src/methods.md:1 @@ -2993,32 +2987,18 @@ msgid "" "struct Rectangle {\n" " width: u32,\n" " height: u32,\n" -"}" -msgstr "" - -#: src/basic-syntax/methods.md:12 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Rectangle {\n" " fn area(&self) -> u32 {\n" " self.width * self.height\n" -" }" -msgstr "" -"impl Rechteck {\n" -" fn-Bereich(&self) -> u32 {\n" -" selbst.Breite * selbst.Höhe\n" -" }" - -#: src/basic-syntax/methods.md:17 -msgid "" +" }\n" +"\n" " fn inc_width(&mut self, delta: u32) {\n" " self.width += delta;\n" " }\n" -"}" -msgstr "" - -#: src/basic-syntax/methods.md:22 -msgid "" +"}\n" +"\n" "fn main() {\n" " let mut rect = Rectangle { width: 10, height: 5 };\n" " println!(\"old area: {}\", rect.area());\n" @@ -3071,11 +3051,8 @@ msgid "" "```rust,editable\n" "fn pick_one(a: T, b: T) -> T {\n" " if std::process::id() % 2 == 0 { a } else { b }\n" -"}" -msgstr "" - -#: src/basic-syntax/functions-interlude.md:19 -msgid "" +"}\n" +"\n" "fn main() {\n" " println!(\"coin toss: {}\", pick_one(\"heads\", \"tails\"));\n" " println!(\"cash prize: {}\", pick_one(500, 1000));\n" @@ -3110,14 +3087,12 @@ msgstr "In diesen Übungen werden wir zwei Teile von Rust erkunden:" #: src/exercises/day-1/morning.md:5 #, fuzzy -msgid "* Implicit conversions between types." +msgid "" +"* Implicit conversions between types.\n" +"\n" +"* Arrays and `for` loops." msgstr "* Implizite Konvertierungen zwischen Typen." -#: src/exercises/day-1/morning.md:7 -#, fuzzy -msgid "* Arrays and `for` loops." -msgstr "* Arrays und „for“-Schleifen." - #: src/exercises/day-1/morning.md:11 #, fuzzy msgid "A few things to consider while solving the exercises:" @@ -3128,7 +3103,9 @@ msgstr "Ein paar Dinge, die Sie beim Lösen der Aufgaben beachten sollten:" msgid "" "* Use a local Rust installation, if possible. This way you can get\n" " auto-completion in your editor. See the page about [Using Cargo] for details\n" -" on installing Rust." +" on installing Rust.\n" +"\n" +"* Alternatively, use the Rust Playground." msgstr "" "* Verwenden Sie nach Möglichkeit eine lokale Rust-Installation. Auf diese Weise können Sie " "erhalten\n" @@ -3136,11 +3113,6 @@ msgstr "" "[Fracht verwenden].\n" " bei der Installation von Rust." -#: src/exercises/day-1/morning.md:17 -#, fuzzy -msgid "* Alternatively, use the Rust Playground." -msgstr "* Benutze alternativ den Rust Playground." - #: src/exercises/day-1/morning.md:19 #, fuzzy msgid "" @@ -3153,23 +3125,13 @@ 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 #, fuzzy msgid "After looking at the exercises, you can look at the [solutions] provided." msgstr "" "Nachdem Sie sich die Übungen angesehen haben, können Sie sich die bereitgestellten [Lösungen] " "ansehen." -#: src/exercises/day-1/morning.md:24 src/exercises/day-2/morning.md:13 -#: src/exercises/day-3/morning.md:9 src/exercises/day-4/morning.md:14 -#, fuzzy -msgid "[solutions]: solutions-morning.md" -msgstr "[Lösungen]: Lösungen-Morgen.md" - -#: src/exercises/day-1/morning.md:26 -#, fuzzy -msgid "[Using Cargo]: ../../cargo.md" -msgstr "[Fracht verwenden]: ../../cargo.md" - #: src/exercises/day-1/implicit-conversions.md:1 #, fuzzy msgid "# Implicit Conversions" @@ -3189,18 +3151,12 @@ msgid "" "```rust,editable,compile_fail\n" "fn multiply(x: i16, y: i16) -> i16 {\n" " x * y\n" -"}" -msgstr "" - -#: src/exercises/day-1/implicit-conversions.md:11 -msgid "" +"}\n" +"\n" "fn main() {\n" " let x: i8 = 15;\n" -" let y: i16 = 1000;" -msgstr "" - -#: src/exercises/day-1/implicit-conversions.md:15 -msgid "" +" let y: i16 = 1000;\n" +"\n" " println!(\"{x} * {y} = {}\", multiply(x, y));\n" "}\n" "```" @@ -3247,18 +3203,11 @@ msgstr "" #: src/exercises/day-1/implicit-conversions.md:33 #, fuzzy -msgid "1. Execute the above program and look at the compiler error." -msgstr "1. Führen Sie das obige Programm aus und sehen Sie sich den Compiler-Fehler an." - -#: src/exercises/day-1/implicit-conversions.md:35 -#, fuzzy -msgid "2. Update the code above to use `into()` to do the conversion." -msgstr "" -"2. Aktualisieren Sie den obigen Code, um `into()` zu verwenden, um die Konvertierung durchzuführen." - -#: src/exercises/day-1/implicit-conversions.md:37 -#, fuzzy msgid "" +"1. Execute the above program and look at the compiler error.\n" +"\n" +"2. Update the code above to use `into()` to do the conversion.\n" +"\n" "3. Change the types of `x` and `y` to other things (such as `f32`, `bool`,\n" " `i128`) to see which types you can convert to which other types. Try\n" " converting small types to big types and the other way around. Check the\n" @@ -3271,17 +3220,6 @@ msgstr "" " [Dokumentation der Standardbibliothek][1], um zu sehen, ob \"From\" für implementiert ist\n" " die Paare, die Sie überprüfen." -#: src/exercises/day-1/implicit-conversions.md:43 -#, fuzzy -msgid "" -"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" -"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" -"[3]: https://en.cppreference.com/w/cpp/language/implicit_conversion" -msgstr "" -"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" -"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" -"[3]: https://en.cppreference.com/w/cpp/language/implicit_conversion" - #: src/exercises/day-1/for-loops.md:1 #, fuzzy msgid "# Arrays and `for` Loops" @@ -3333,11 +3271,8 @@ msgid "" " for n in array {\n" " print!(\" {n}\");\n" " }\n" -" println!();" -msgstr "" - -#: src/exercises/day-1/for-loops.md:30 -msgid "" +" println!();\n" +"\n" " print!(\"Iterating over range:\");\n" " for i in 0..3 {\n" " print!(\" {}\", array[i]);\n" @@ -3380,46 +3315,30 @@ msgstr "" "Kopieren Sie den folgenden Code nach und implementieren Sie die\n" "Funktionen:" -#: src/exercises/day-1/for-loops.md:52 src/exercises/day-1/book-library.md:20 -#: src/exercises/day-2/health-statistics.md:13 +#: src/exercises/day-1/for-loops.md:52 msgid "" "```rust,should_panic\n" "// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]" -msgstr "" - -#: src/exercises/day-1/for-loops.md:56 -msgid "" +"#![allow(unused_variables, dead_code)]\n" +"\n" "fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" " unimplemented!()\n" -"}" -msgstr "" - -#: src/exercises/day-1/for-loops.md:60 -msgid "" +"}\n" +"\n" "fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" " unimplemented!()\n" -"}" -msgstr "" - -#: src/exercises/day-1/for-loops.md:64 -msgid "" +"}\n" +"\n" "fn main() {\n" " let matrix = [\n" " [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" " [201, 202, 203],\n" " [301, 302, 303],\n" -" ];" -msgstr "" - -#: src/exercises/day-1/for-loops.md:71 src/exercises/day-1/solutions-morning.md:70 -msgid "" +" ];\n" +"\n" " println!(\"matrix:\");\n" -" pretty_print(&matrix);" -msgstr "" - -#: src/exercises/day-1/for-loops.md:74 -msgid "" +" pretty_print(&matrix);\n" +"\n" " let transposed = transpose(matrix);\n" " println!(\"transposed:\");\n" " pretty_print(&transposed);\n" @@ -3492,7 +3411,7 @@ msgstr "" #, fuzzy msgid "" "* Due to type inference the `i32` is optional. We will gradually show the types less and less as " -"the type progresses.\n" +"the course progresses.\n" "* Note that since `println!` is a macro, `x` is not moved, even using the function like syntax of " "`println!(\"x: {}\", x)`" msgstr "" @@ -3516,25 +3435,16 @@ msgid "" "```rust,editable\n" "fn takes_u32(x: u32) {\n" " println!(\"u32: {x}\");\n" -"}" -msgstr "" - -#: src/basic-syntax/type-inference.md:10 -msgid "" +"}\n" +"\n" "fn takes_i8(y: i8) {\n" " println!(\"i8: {y}\");\n" -"}" -msgstr "" - -#: src/basic-syntax/type-inference.md:14 -msgid "" +"}\n" +"\n" "fn main() {\n" " let x = 10;\n" -" let y = 20;" -msgstr "" - -#: src/basic-syntax/type-inference.md:18 -msgid "" +" let y = 20;\n" +"\n" " takes_u32(x);\n" " takes_i8(y);\n" " // takes_u32(y);\n" @@ -3546,17 +3456,20 @@ msgstr "" #, fuzzy msgid "" "This slide demonstrates how the Rust compiler infers types based on constraints given by variable " -"declarations and usages.\n" -" \n" +"declarations and usages." +msgstr "" +"Diese Folie zeigt, wie der Rust-Compiler Typen basierend auf Einschränkungen ableitet, die durch " +"Variablendeklarationen und Verwendungen gegeben sind.\n" + +#: src/basic-syntax/type-inference.md:28 +#, fuzzy +msgid "" "It is very important to emphasize that variables declared like this are not of some sort of " "dynamic \"any type\" that can\n" "hold any data. The machine code generated by such declaration is identical to the explicit " "declaration of a type.\n" -"The compiler does the job for us and helps us to write a more concise code." +"The compiler does the job for us and helps us write more concise code." msgstr "" -"Diese Folie zeigt, wie der Rust-Compiler Typen basierend auf Einschränkungen ableitet, die durch " -"Variablendeklarationen und Verwendungen gegeben sind.\n" -" \n" "Es ist sehr wichtig zu betonen, dass auf diese Weise deklarierte Variablen nicht von einer Art " "dynamischem \"beliebigen Typ\" sind, der dies kann\n" "irgendwelche Daten halten. Der durch eine solche Deklaration erzeugte Maschinencode ist identisch " @@ -3580,11 +3493,8 @@ msgid "" " let mut v = Vec::new();\n" " v.push((10, false));\n" " v.push((20, true));\n" -" println!(\"v: {v:?}\");" -msgstr "" - -#: src/basic-syntax/type-inference.md:41 -msgid "" +" println!(\"v: {v:?}\");\n" +"\n" " let vv = v.iter().collect::>();\n" " println!(\"vv: {vv:?}\");\n" "}\n" @@ -3626,22 +3536,16 @@ msgstr "Sie können Kompilierzeitkonstanten deklarieren:" msgid "" "```rust,editable\n" "const DIGEST_SIZE: usize = 3;\n" -"const ZERO: Option = Some(42);" -msgstr "" - -#: src/basic-syntax/static-and-const.md:13 -msgid "" +"const ZERO: Option = Some(42);\n" +"\n" "fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {\n" " let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];\n" " for (idx, &b) in text.as_bytes().iter().enumerate() {\n" " digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE].wrapping_add(b);\n" " }\n" " digest\n" -"}" -msgstr "" - -#: src/basic-syntax/static-and-const.md:21 -msgid "" +"}\n" +"\n" "fn main() {\n" " let digest = compute_digest(\"Hello\");\n" " println!(\"Digest: {digest:?}\");\n" @@ -3667,11 +3571,8 @@ msgstr "Sie können auch statische Variablen deklarieren:" #: src/basic-syntax/static-and-const.md:33 msgid "" "```rust,editable\n" -"static BANNER: &str = \"Welcome to RustOS 3.14\";" -msgstr "" - -#: src/basic-syntax/static-and-const.md:36 -msgid "" +"static BANNER: &str = \"Welcome to RustOS 3.14\";\n" +"\n" "fn main() {\n" " println!(\"{BANNER}\");\n" "}\n" @@ -3711,11 +3612,6 @@ msgstr "" "* Es kommt nicht sehr häufig vor, dass man eine zur Laufzeit ausgewertete Konstante benötigt, aber " "es ist hilfreich und sicherer als die Verwendung einer statischen." -#: src/basic-syntax/static-and-const.md:54 -#, fuzzy -msgid "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" -msgstr "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" - #: src/basic-syntax/scopes-shadowing.md:1 #, fuzzy msgid "# Scopes and Shadowing" @@ -3736,25 +3632,16 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let a = 10;\n" -" println!(\"before: {a}\");" -msgstr "" - -#: src/basic-syntax/scopes-shadowing.md:11 -msgid "" +" println!(\"before: {a}\");\n" +"\n" " {\n" " let a = \"hello\";\n" -" println!(\"inner scope: {a}\");" -msgstr "" - -#: src/basic-syntax/scopes-shadowing.md:15 -msgid "" +" println!(\"inner scope: {a}\");\n" +"\n" " let a = true;\n" " println!(\"shadowed in inner scope: {a}\");\n" -" }" -msgstr "" - -#: src/basic-syntax/scopes-shadowing.md:19 -msgid "" +" }\n" +"\n" " println!(\"after: {a}\");\n" "}\n" "```" @@ -3849,7 +3736,12 @@ msgid "" " * Values have fixed sizes known at compile time.\n" " * Extremely fast: just move a stack pointer.\n" " * Easy to manage: follows function calls.\n" -" * Great memory locality." +" * Great memory locality.\n" +"\n" +"* Heap: Storage of values outside of function calls.\n" +" * Values have dynamic sizes determined at runtime.\n" +" * Slightly slower than the stack: some book-keeping needed.\n" +" * No guarantee of memory locality." msgstr "" "* Stack: Kontinuierlicher Speicherbereich für lokale Variablen.\n" " * Werte haben feste Größen, die zur Kompilierzeit bekannt sind.\n" @@ -3857,19 +3749,6 @@ msgstr "" " * Einfach zu verwalten: folgt Funktionsaufrufen.\n" " * Große Gedächtnislokalität." -#: src/memory-management/stack-vs-heap.md:9 -#, fuzzy -msgid "" -"* Heap: Storage of values outside of function calls.\n" -" * Values have dynamic sizes determined at runtime.\n" -" * Slightly slower than the stack: some book-keeping needed.\n" -" * No guarantee of memory locality." -msgstr "" -"* Heap: Speicherung von Werten außerhalb von Funktionsaufrufen.\n" -" * Werte haben dynamische Größen, die zur Laufzeit bestimmt werden.\n" -" * Etwas langsamer als der Stapel: Etwas Buchhaltung erforderlich.\n" -" * Keine Garantie auf Speicherort." - #: src/memory-management/stack.md:1 #, fuzzy msgid "# Stack Memory" @@ -3912,32 +3791,31 @@ msgid "" msgstr "" #: src/memory-management/stack.md:28 -#, fuzzy msgid "" "* Mention that a `String` is backed by a `Vec`, so it has a capacity and length and can grow if " -"mutable via reallocation on the heap." -msgstr "" -"* Erwähnen Sie, dass ein `String` von einem `Vec` unterstützt wird, sodass er eine Kapazität und " -"Länge hat und wachsen kann, wenn er durch Neuzuweisung auf dem Haufen veränderbar ist." - -#: src/memory-management/stack.md:30 -#, fuzzy -msgid "" +"mutable via reallocation on the heap.\n" +"\n" "* If students ask about it, you can mention that the underlying memory is heap allocated using the " -"[System Allocator] and custom allocators can be implemented using the [Allocator API]" -msgstr "" -"* Wenn die Schüler danach fragen, können Sie erwähnen, dass der zugrunde liegende Speicher mit dem " -"[System Allocator] Heap zugewiesen wird und benutzerdefinierte Allokatoren mit der [Allocator API] " -"implementiert werden können." - -#: src/memory-management/stack.md:34 -#, fuzzy -msgid "" -"[System Allocator]: https://doc.rust-lang.org/std/alloc/struct.System.html\n" -"[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html" +"[System Allocator] and custom allocators can be implemented using the [Allocator API]\n" +"\n" +"* We can inspect the memory layout with `unsafe` code. However, you should point out that this is " +"rightfully unsafe!\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could lead to\n" +" // undefined behavior.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +" }\n" +" }\n" +" ```" msgstr "" -"[Systemzuordner]: https://doc.rust-lang.org/std/alloc/struct.System.html\n" -"[Allocator-API]: https://doc.rust-lang.org/std/alloc/index.html" #: src/memory-management/manual.md:1 #, fuzzy @@ -4144,35 +4022,15 @@ msgstr "Dies wird erreicht, indem _Eigentum_ explizit modelliert wird." msgid "" "* If asked how at this point, you can mention that in Rust this is usually handled by RAII wrapper " "types such as [Box], [Vec], [Rc], or [Arc]. These encapsulate ownership and memory allocation via " -"various means, and prevent the potential errors in C." +"various means, and prevent the potential errors in C.\n" +"\n" +"* You may be asked about destructors here, the [Drop] trait is the Rust equivalent." msgstr "" "* Wenn Sie an dieser Stelle fragen, wie das geht, können Sie erwähnen, dass dies in Rust " "normalerweise von RAII-Wrapper-Typen wie [Box], [Vec], [Rc] oder [Arc] gehandhabt wird. Diese " "kapseln den Besitz und die Speicherzuweisung auf verschiedene Weise und verhindern die " "potenziellen Fehler in C." -#: src/memory-management/rust.md:16 -#, fuzzy -msgid "* You may be asked about destructors here, the [Drop] trait is the Rust equivalent." -msgstr "" -"* Möglicherweise werden Sie hier nach Destruktoren gefragt, die Eigenschaft [Drop] ist das Rust-" -"Äquivalent." - -#: src/memory-management/rust.md:20 -#, fuzzy -msgid "" -"[Box]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" -"[Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" -"[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" -"[Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" -"[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html" -msgstr "" -"[Box]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" -"[Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" -"[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" -"[Bogen]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" -"[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html" - #: src/memory-management/comparison.md:1 #, fuzzy msgid "# Comparison" @@ -4270,11 +4128,8 @@ msgstr "" #: src/ownership.md:6 msgid "" "```rust,editable,compile_fail\n" -"struct Point(i32, i32);" -msgstr "" - -#: src/ownership.md:9 -msgid "" +"struct Point(i32, i32);\n" +"\n" "fn main() {\n" " {\n" " let p = Point(3, 4);\n" @@ -4337,16 +4192,13 @@ msgstr "" #, fuzzy msgid "" "* Mention that this is the opposite of the defaults in C++, which copies by value unless you use " -"`std::move` (and the move constructor is defined!)." +"`std::move` (and the move constructor is defined!).\n" +"\n" +"* In Rust, clones are explicit (by using `clone`)." msgstr "" "* Erwähnen Sie, dass dies das Gegenteil der Standardeinstellungen in C++ ist, die nach Wert " "kopieren, es sei denn, Sie verwenden `std::move` (und der Move-Konstruktor ist definiert!)." -#: src/ownership/move-semantics.md:24 -#, fuzzy -msgid "* In Rust, you clones are explicit (by using `clone`)." -msgstr "* In Rust sind Klone explizit (durch Verwendung von `clone`)." - #: src/ownership/moved-strings-rust.md:1 #, fuzzy msgid "# Moved Strings in Rust" @@ -4520,11 +4372,8 @@ msgid "" "```rust,editable\n" "fn say_hello(name: String) {\n" " println!(\"Hello {name}\")\n" -"}" -msgstr "" - -#: src/ownership/moves-function-calls.md:11 -msgid "" +"}\n" +"\n" "fn main() {\n" " let name = String::from(\"Alice\");\n" " say_hello(name);\n" @@ -4591,11 +4440,8 @@ msgstr "Sie können Ihre eigenen Typen für die Verwendung von Kopiersemantik ak msgid "" "```rust,editable\n" "#[derive(Copy, Clone, Debug)]\n" -"struct Point(i32, i32);" -msgstr "" - -#: src/ownership/copy-clone.md:22 -msgid "" +"struct Point(i32, i32);\n" +"\n" "fn main() {\n" " let p1 = Point(3, 4);\n" " let p2 = p1;\n" @@ -4662,9 +4508,7 @@ msgid "" "If students ask about `derive`, it is sufficient to say that this is a way to generate code in " "Rust\n" "at compile time. In this case the default implementations of `Copy` and `Clone` traits are " -"generated.\n" -" \n" -"
" +"generated." msgstr "" "Wenn Schüler nach „derive“ fragen, reicht es zu sagen, dass dies eine Möglichkeit ist, Code in " "Rust zu generieren\n" @@ -4687,26 +4531,16 @@ msgstr "" "Anstatt den Besitz beim Aufruf einer Funktion zu übertragen, können Sie a\n" "function _borrow_ den Wert:" -#: src/ownership/borrowing.md:6 src/ownership/lifetimes-function-calls.md:5 +#: src/ownership/borrowing.md:6 msgid "" "```rust,editable\n" "#[derive(Debug)]\n" -"struct Point(i32, i32);" -msgstr "" - -#: src/ownership/borrowing.md:10 -#, fuzzy -msgid "" +"struct Point(i32, i32);\n" +"\n" "fn add(p1: &Point, p2: &Point) -> Point {\n" " Point(p1.0 + p2.0, p1.1 + p2.1)\n" -"}" -msgstr "" -"fn add(p1: &Punkt, p2: &Punkt) -> Punkt {\n" -" Punkt(p1.0 + p2.0, p1.1 + p2.1)\n" -"}" - -#: src/ownership/borrowing.md:14 -msgid "" +"}\n" +"\n" "fn main() {\n" " let p1 = Point(3, 4);\n" " let p2 = Point(10, 20);\n" @@ -4727,37 +4561,26 @@ msgstr "" #: src/ownership/borrowing.md:27 #, fuzzy +msgid "Notes on stack returns:" +msgstr "Hinweise zur Stapelrückgabe:\n" + +#: src/ownership/borrowing.md:28 msgid "" -"Notes on stack returns:\n" "* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy " "operation. Change the above code to print stack addresses and run it on the [Playground]. In the " -"\"DEBUG\" optimization level, the addresses should change, while the stay the same when changing " -"to the \"RELEASE\" setting:" -msgstr "" -"Hinweise zur Stapelrückgabe:\n" -"* Zeigen Sie, dass die Rückgabe von `add` billig ist, weil der Compiler den Kopiervorgang " -"eliminieren kann. Ändern Sie den obigen Code, um Stapeladressen zu drucken, und führen Sie ihn auf " -"dem [Playground] aus. In der Optimierungsstufe „DEBUG“ sollen sich die Adressen ändern, während " -"sie beim Wechsel in die Einstellung „RELEASE“ gleich bleiben:" - -#: src/ownership/borrowing.md:30 -msgid "" +"\"DEBUG\" optimization level, the addresses should change, while they stay the same when changing " +"to the \"RELEASE\" setting:\n" +"\n" " ```rust,editable\n" " #[derive(Debug)]\n" -" struct Point(i32, i32);" -msgstr "" - -#: src/ownership/borrowing.md:34 -msgid "" +" struct Point(i32, i32);\n" +"\n" " fn add(p1: &Point, p2: &Point) -> Point {\n" " let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" " println!(\"&p.0: {:p}\", &p.0);\n" " p\n" -" }" -msgstr "" - -#: src/ownership/borrowing.md:40 -msgid "" +" }\n" +"\n" " fn main() {\n" " let p1 = Point(3, 4);\n" " let p2 = Point(10, 20);\n" @@ -4772,11 +4595,6 @@ msgid "" "performs a simple and efficient `memcpy` copy." msgstr "" -#: src/ownership/borrowing.md:53 -#, fuzzy -msgid "[Playground]: https://play.rust-lang.org/" -msgstr "[Spielplatz]: https://play.rust-lang.org/" - #: src/ownership/shared-unique-borrows.md:1 #, fuzzy msgid "# Shared and Unique Borrows" @@ -4801,19 +4619,13 @@ msgid "" "```rust,editable,compile_fail\n" "fn main() {\n" " let mut a: i32 = 10;\n" -" let b: &i32 = &a;" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:13 -msgid "" +" let b: &i32 = &a;\n" +"\n" " {\n" " let c: &mut i32 = &mut a;\n" " *c = 20;\n" -" }" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:18 src/std/rc.md:13 -msgid "" +" }\n" +"\n" " println!(\"a: {a}\");\n" " println!(\"b: {b}\");\n" "}\n" @@ -4872,19 +4684,16 @@ msgid "In addition to borrowing its arguments, a function can return a borrowed msgstr "" "Zusätzlich zum Ausleihen ihrer Argumente kann eine Funktion einen geliehenen Wert zurückgeben:" -#: src/ownership/lifetimes-function-calls.md:9 -#, fuzzy +#: src/ownership/lifetimes-function-calls.md:5 msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" "fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" " if p1.0 < p2.0 { p1 } else { p2 }\n" -"}" -msgstr "" -"fn left_most<'a>(p1: &'a Punkt, p2: &'a Punkt) -> &'a Punkt {\n" -" wenn p1.0 < p2.0 { p1 } sonst { p2 }\n" -"}" - -#: src/ownership/lifetimes-function-calls.md:13 -msgid "" +"}\n" +"\n" "fn main() {\n" " let p1: Point = Point(10, 10);\n" " let p2: Point = Point(20, 20);\n" @@ -4911,27 +4720,18 @@ msgstr "" "befinden." #: 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 " "code:\n" " ```rust,ignore\n" " #[derive(Debug)]\n" -" struct Point(i32, i32);" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:36 -#, fuzzy -msgid "" +" struct Point(i32, i32);\n" +"\n" " fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" " if p1.0 < p2.0 { p1 } else { p2 }\n" -" }" -msgstr "" -" fn left_most<'a>(p1: &'a Punkt, p2: &'a Punkt) -> &'a Punkt {\n" -" wenn p1.0 < p2.0 { p1 } sonst { p2 }\n" -" }" - -#: src/ownership/lifetimes-function-calls.md:40 -msgid "" +" }\n" +"\n" " fn main() {\n" " let p1: Point = Point(10, 10);\n" " let p3: &Point;\n" @@ -4942,12 +4742,8 @@ msgid "" " println!(\"left-most point: {:?}\", p3);\n" " }\n" " ```\n" -" Note how this does not compile since `p3` outlives `p2`." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:52 -#, fuzzy -msgid "" +" Note how this does not compile since `p3` outlives `p2`.\n" +"\n" "* Reset the workspace and change the function signature to `fn left_most<'a, 'b>(p1: &'a Point, " "p2: &'a Point) -> &'b Point`. This will not compile because the relationship between the lifetimes " "`'a` and `'b` is unclear.\n" @@ -4985,18 +4781,12 @@ msgstr "Wenn ein Datentyp geliehene Daten speichert, muss er mit einer Lebensdau msgid "" "```rust,editable\n" "#[derive(Debug)]\n" -"struct Highlight<'doc>(&'doc str);" -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:9 -msgid "" +"struct Highlight<'doc>(&'doc str);\n" +"\n" "fn erase(text: String) {\n" " println!(\"Bye {text}!\");\n" -"}" -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:13 -msgid "" +"}\n" +"\n" "fn main() {\n" " let text = String::from(\"The quick brown fox jumps over the lazy dog.\");\n" " let fox = Highlight(&text[4..19]);\n" @@ -5020,8 +4810,7 @@ msgid "" "* When possible, make data structures own their data directly.\n" "* Some structs with multiple references inside can have more than one lifetime annotation. This " "can be necessary if there is a need to describe lifetime relationships between the references " -"themselves, in addition to the lifetime of the struct itself. Those are very advanced use cases.\n" -"
" +"themselves, in addition to the lifetime of the struct itself. Those are very advanced use cases." msgstr "" "* Im obigen Beispiel erzwingt die Anmerkung zu `Highlight`, dass die Daten, die dem enthaltenen " "`&str` zugrunde liegen, mindestens so lange leben wie jede Instanz von `Highlight`, die diese " @@ -5050,19 +4839,12 @@ msgstr "Wir werden uns zwei Dinge ansehen:" #: src/exercises/day-1/afternoon.md:5 #, fuzzy -msgid "* A small book library," -msgstr "* Eine kleine Buchbibliothek," - -#: src/exercises/day-1/afternoon.md:7 -#, fuzzy -msgid "* Iterators and ownership (hard)." +msgid "" +"* A small book library,\n" +"\n" +"* Iterators and ownership (hard)." msgstr "* Iteratoren und Besitz (schwer)." -#: src/exercises/day-1/afternoon.md:13 src/exercises/day-2/afternoon.md:9 -#, fuzzy -msgid "[solutions]: solutions-afternoon.md" -msgstr "[Lösungen]: Lösungen-Nachmittag.md" - #: src/exercises/day-1/book-library.md:1 #, fuzzy msgid "# Designing a Library" @@ -5101,33 +4883,19 @@ msgstr "" "nach\n" " und aktualisieren Sie die Typen, damit es kompiliert wird:" -#: src/exercises/day-1/book-library.md:24 -#, fuzzy +#: src/exercises/day-1/book-library.md:20 msgid "" +"```rust,should_panic\n" +"\n" "struct Library {\n" " books: Vec,\n" -"}" -msgstr "" -"Struktur Bibliothek {\n" -" Bücher: Vec,\n" -"}" - -#: src/exercises/day-1/book-library.md:28 src/exercises/day-1/solutions-afternoon.md:27 -#, fuzzy -msgid "" +"}\n" +"\n" "struct Book {\n" " title: String,\n" " year: u16,\n" -"}" -msgstr "" -"struct Buch {\n" -" Titel: Zeichenkette,\n" -" Jahr: u16,\n" -"}" - -#: src/exercises/day-1/book-library.md:33 src/exercises/day-1/solutions-afternoon.md:32 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Book {\n" " // This is a constructor, used below.\n" " fn new(title: &str, year: u16) -> Book {\n" @@ -5136,120 +4904,53 @@ msgid "" " year,\n" " }\n" " }\n" -"}" -msgstr "" -"impl Buch {\n" -" // Dies ist ein Konstruktor, der unten verwendet wird.\n" -" fn neu(titel: &str, jahr: u16) -> Buch {\n" -" Buch {\n" -" Titel: Zeichenkette::von(Titel),\n" -" Jahr,\n" -" }\n" -" }\n" -"}" - -#: src/exercises/day-1/book-library.md:43 -#, fuzzy -msgid "" +"}\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" -"}" -msgstr "" -"// Dadurch ist es möglich, Buchwerte mit {} zu drucken.\n" -"impl std::fmt::Anzeige für Buch {\n" -" fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n" -" schreibe!(f, \"{} ({})\", self.title, self.year)\n" -" }\n" -"}" - -#: src/exercises/day-1/book-library.md:50 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Library {\n" " fn new() -> Library {\n" " unimplemented!()\n" -" }" -msgstr "" -"impl-Bibliothek {\n" -" fn new() -> Bibliothek {\n" -" nicht implementiert!()\n" -" }" - -#: src/exercises/day-1/book-library.md:55 -#, fuzzy -msgid "" +" }\n" +"\n" " //fn len(self) -> usize {\n" " // unimplemented!()\n" -" //}" -msgstr "" -" //fn len(self) -> verwenden {\n" -" // nicht implementiert!()\n" -" //}" - -#: src/exercises/day-1/book-library.md:59 -#, fuzzy -msgid "" +" //}\n" +"\n" " //fn is_empty(self) -> bool {\n" " // unimplemented!()\n" -" //}" -msgstr "" -" //fn is_empty(self) -> bool {\n" -" // nicht implementiert!()\n" -" //}" - -#: src/exercises/day-1/book-library.md:63 -#, fuzzy -msgid "" +" //}\n" +"\n" " //fn add_book(self, book: Book) {\n" " // unimplemented!()\n" -" //}" -msgstr "" -" //fn add_book(selbst, Buch: Buch) {\n" -" // nicht implementiert!()\n" -" //}" - -#: src/exercises/day-1/book-library.md:67 -#, fuzzy -msgid "" +" //}\n" +"\n" " //fn print_books(self) {\n" " // unimplemented!()\n" -" //}" -msgstr "" -" //fn print_books(selbst) {\n" -" // nicht implementiert!()\n" -" //}" - -#: src/exercises/day-1/book-library.md:71 -#, fuzzy -msgid "" +" //}\n" +"\n" " //fn oldest_book(self) -> Option<&Book> {\n" " // unimplemented!()\n" " //}\n" -"}" -msgstr "" -" //fn ältestes_buch(selbst) -> Option<&Buch> {\n" -" // nicht implementiert!()\n" -" //}\n" -"}" - -#: src/exercises/day-1/book-library.md:76 -msgid "" +"}\n" +"\n" "// This shows the desired behavior. Uncomment the code below and\n" "// implement the missing methods. You will need to update the\n" "// method signatures, including the \"self\" parameter! You may\n" "// also need to update the variable bindings within main.\n" "fn main() {\n" -" let library = Library::new();" -msgstr "" - -#: src/exercises/day-1/book-library.md:83 -msgid "" +" let library = Library::new();\n" +"\n" " //println!(\"Our library is empty: {}\", library.is_empty());\n" -" //\n" -" //library.add_book(Book::new(\"Lord of the Rings\", 1954));\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" " //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" " //\n" " //library.print_books();\n" @@ -5260,20 +4961,17 @@ msgid "" " //}\n" " //\n" " //println!(\"Our library has {} books\", library.len());\n" +" for book in library.books {\n" +" println!(\"{book}\");\n" +" }\n" "}\n" "```" msgstr "" -#: src/exercises/day-1/book-library.md:99 +#: src/exercises/day-1/book-library.md:104 #, fuzzy -msgid "" -"
\n" -" \n" -"[Solution](solutions-afternoon.md#designing-a-library)" -msgstr "" -"
\n" -" \n" -"[Lösung](solutions-afternoon.md#designing-a-library)" +msgid "[Solution](solutions-afternoon.md#designing-a-library)" +msgstr "[Lösung](solutions-afternoon.md#designing-a-library)" #: src/exercises/day-1/iterators-and-ownership.md:1 #, fuzzy @@ -5328,11 +5026,8 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:27 -msgid "" +" let mut iter = v.iter();\n" +"\n" " println!(\"v[0]: {:?}\", iter.next());\n" " println!(\"v[1]: {:?}\", iter.next());\n" " println!(\"v[2]: {:?}\", iter.next());\n" @@ -5351,12 +5046,8 @@ msgid "" "```rust,editable,compile_fail\n" "fn main() {\n" " let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:41 -#: src/exercises/day-1/iterators-and-ownership.md:78 -msgid "" +" let mut iter = v.iter();\n" +"\n" " let v0: Option<..> = iter.next();\n" " println!(\"v0: {v0:?}\");\n" "}\n" @@ -5387,11 +5078,8 @@ msgid "" "```rust\n" "pub trait IntoIterator {\n" " type Item;\n" -" type IntoIter: Iterator;" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:58 -msgid "" +" type IntoIter: Iterator;\n" +"\n" " fn into_iter(self) -> Self::IntoIter;\n" "}\n" "```" @@ -5434,7 +5122,12 @@ msgid "" "```rust,editable,compile_fail\n" "fn main() {\n" " let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];\n" -" let mut iter = v.into_iter();" +" let mut iter = v.into_iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" msgstr "" #: src/exercises/day-1/iterators-and-ownership.md:83 @@ -5457,18 +5150,12 @@ msgstr "" msgid "" "```rust,editable\n" "fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:93 -msgid "" +" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];\n" +"\n" " for word in &v {\n" " println!(\"word: {word}\");\n" -" }" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:97 -msgid "" +" }\n" +"\n" " for word in v {\n" " println!(\"word: {word}\");\n" " }\n" @@ -5513,37 +5200,19 @@ msgid "Now that we have seen a fair amount of Rust, we will continue with:" msgstr "Nachdem wir nun eine ganze Menge Rust gesehen haben, fahren wir fort mit:" #: src/welcome-day-2.md:5 -#, fuzzy -msgid "* Structs, enums, methods." -msgstr "* Strukturen, Aufzählungen, Methoden." - -#: src/welcome-day-2.md:7 -#, fuzzy -msgid "* Pattern matching: destructuring enums, structs, and arrays." -msgstr "* Mustervergleich: Destrukturierung von Aufzählungen, Strukturen und Arrays." - -#: src/welcome-day-2.md:9 -#, fuzzy msgid "" +"* Structs, enums, methods.\n" +"\n" +"* Pattern matching: destructuring enums, structs, and arrays.\n" +"\n" "* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and\n" -" `continue`." -msgstr "" -"* Kontrollflusskonstrukte: `if`, `if let`, `while`, `while let`, `break` und\n" -" \"weitermachen\"." - -#: src/welcome-day-2.md:12 -#, fuzzy -msgid "" +" `continue`.\n" +"\n" "* The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, `Rc`\n" -" and `Arc`." +" and `Arc`.\n" +"\n" +"* Modules: visibility, paths, and filesystem hierarchy." msgstr "" -"* Die Standardbibliothek: `String`, `Option` und `Result`, `Vec`, `HashMap`, `Rc`\n" -" und \"Bogen\"." - -#: src/welcome-day-2.md:15 -#, fuzzy -msgid "* Modules: visibility, paths, and filesystem hierarchy." -msgstr "* Module: Sichtbarkeit, Pfade und Dateisystemhierarchie." #: src/structs.md:1 #, fuzzy @@ -5561,11 +5230,8 @@ msgid "" "struct Person {\n" " name: String,\n" " age: u8,\n" -"}" -msgstr "" - -#: src/structs.md:11 -msgid "" +"}\n" +"\n" "fn main() {\n" " let mut peter = Person {\n" " name: String::from(\"Peter\"),\n" @@ -5590,9 +5256,7 @@ msgstr "" msgid "" "
\n" "Key Points: " -msgstr "" -"
\n" -"Wichtige Punkte:" +msgstr "Wichtige Punkte:" #: src/structs.md:32 msgid "" @@ -5603,7 +5267,9 @@ msgid "" "* This may be a good time to let people know there are different types of structs. \n" " * Zero-sized structs `e.g., struct Foo;` might be used when implementing a trait on some type " "but don’t have any data that you want to store in the value itself. \n" -" * The next slide will introduce Tuple structs." +" * The next slide will introduce Tuple structs, used when the field names are not important.\n" +"* The syntax `..peter` allows us to copy the majority of the fields from the old struct without " +"having to explicitly type it all out. It must always be the last element." msgstr "" #: src/structs/tuple-structs.md:1 @@ -5619,11 +5285,8 @@ msgstr "Wenn die Feldnamen unwichtig sind, können Sie eine Tupelstruktur verwen #: src/structs/tuple-structs.md:5 msgid "" "```rust,editable\n" -"struct Point(i32, i32);" -msgstr "" - -#: src/structs/tuple-structs.md:8 -msgid "" +"struct Point(i32, i32);\n" +"\n" "fn main() {\n" " let p = Point(17, 23);\n" " println!(\"({}, {})\", p.0, p.1);\n" @@ -5640,61 +5303,37 @@ msgstr "Dies wird häufig für Einzelfeld-Wrapper (genannt Newtypes) verwendet:" msgid "" "```rust,editable,compile_fail\n" "struct PoundOfForce(f64);\n" -"struct Newtons(f64);" -msgstr "" - -#: src/structs/tuple-structs.md:20 -#, fuzzy -msgid "" +"struct Newtons(f64);\n" +"\n" "fn compute_thruster_force() -> PoundOfForce {\n" " todo!(\"Ask a rocket scientist at NASA\")\n" -"}" -msgstr "" -"fn compute_thruster_force() -> PoundOfForce {\n" -" todo! (\"Fragen Sie einen Raketenwissenschaftler bei der NASA\")\n" -"}" - -#: src/structs/tuple-structs.md:24 -#, fuzzy -msgid "" +"}\n" +"\n" "fn set_thruster_force(force: Newtons) {\n" " // ...\n" -"}" -msgstr "" -"fn set_thruster_force(Kraft: Newton) {\n" -" // ...\n" -"}" - -#: src/structs/tuple-structs.md:28 -msgid "" +"}\n" +"\n" "fn main() {\n" " let force = compute_thruster_force();\n" " set_thruster_force(force);\n" -"}" -msgstr "" - -#: src/structs/tuple-structs.md:33 src/generics/trait-objects.md:86 -msgid "```" +"}\n" +"\n" +"```" msgstr "" #: src/structs/tuple-structs.md:37 -#, fuzzy msgid "" -"Newtypes are a great way to encode additional information about the value in a primitive type, for " -"example:\n" +"* Newtypes are a great way to encode additional information about the value in a primitive type, " +"for example:\n" " * The number is measured in some units: `Newtons` in the example above.\n" " * The value passed some validation when it was created, so you no longer have to validate it " "again at every use: 'PhoneNumber(String)` or `OddNumber(u32)`.\n" -" \n" -"
" +"* Demonstrate how to add a `f64` value to a `Newtons` type by accessing the single field in the " +"newtype.\n" +" * Rust generally doesn’t like inexplicit things, like automatic unwrapping or for instance " +"using booleans as integers.\n" +" * Operator overloading is discussed on Day 3 (generics). " msgstr "" -"Newtypes sind eine großartige Möglichkeit, zusätzliche Informationen über den Wert in einem " -"primitiven Typ zu codieren, zum Beispiel:\n" -" * Die Zahl wird in einigen Einheiten gemessen: „Newton“ im obigen Beispiel.\n" -" * Der Wert hat bei seiner Erstellung einige Validierungen durchlaufen, sodass Sie ihn nicht mehr " -"bei jeder Verwendung erneut validieren müssen: 'PhoneNumber(String)' oder 'OddNumber(u32)'.\n" -" \n" -"
" #: src/structs/field-shorthand.md:1 #, fuzzy @@ -5710,33 +5349,21 @@ msgstr "" "Wenn Sie bereits Variablen mit den richtigen Namen haben, können Sie die erstellen\n" "struct mit einer Abkürzung:" -#: src/structs/field-shorthand.md:6 src/methods.md:6 +#: src/structs/field-shorthand.md:6 msgid "" "```rust,editable\n" "#[derive(Debug)]\n" "struct Person {\n" " name: String,\n" " age: u8,\n" -"}" -msgstr "" - -#: src/structs/field-shorthand.md:13 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Person {\n" " fn new(name: String, age: u8) -> Person {\n" " Person { name, age }\n" " }\n" -"}" -msgstr "" -"impl Person {\n" -" fn new(name: String, age: u8) -> Person {\n" -" Person { Name, Alter }\n" -" }\n" -"}" - -#: src/structs/field-shorthand.md:19 -msgid "" +"}\n" +"\n" "fn main() {\n" " let peter = Person::new(String::from(\"Peter\"), 27);\n" " println!(\"{peter:?}\");\n" @@ -5745,25 +5372,54 @@ msgid "" msgstr "" #: src/structs/field-shorthand.md:27 -#, fuzzy msgid "" -"The `new` function could be written using `Self` as a type, as it is interchangeable with the " -"struct type name" -msgstr "" -"Die „neue“ Funktion könnte unter Verwendung von „Self“ als Typ geschrieben werden, da sie mit dem " -"Namen des Strukturtyps austauschbar ist" - -#: src/structs/field-shorthand.md:29 -msgid "" -"```rust,ignore\n" -"impl Person {\n" -" fn new(name: String, age: u8) -> Self {\n" -" Self { name, age }\n" -" }\n" -"}\n" -"```\n" -" \n" -"
" +"* The `new` function could be written using `Self` as a type, as it is interchangeable with the " +"struct type name\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Person {\n" +" fn new(name: String, age: u8) -> Self {\n" +" Self { name, age }\n" +" }\n" +" }\n" +" ``` \n" +"* Implement the `Default` trait for the struct. Define some fields and use the default values for " +"the other fields.\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Default for Person {\n" +" fn default() -> Person {\n" +" Person {\n" +" name: \"Bot\".to_string(),\n" +" age: 0,\n" +" }\n" +" }\n" +" }\n" +" fn create_default() {\n" +" let tmp = Person {\n" +" ..Default::default()\n" +" };\n" +" let tmp = Person {\n" +" name: \"Sam\".to_string(),\n" +" ..Default::default()\n" +" };\n" +" }\n" +" ```\n" +"\n" +"* Methods are defined in the `impl` block.\n" +"* Use struct update syntax to define a new structure using `peter`. Note that the variable `peter` " +"will no longer be accessible afterwards.\n" +"* Use `{:#?}` when printing structs to request the `Debug` representation." msgstr "" #: src/enums.md:1 @@ -5785,26 +5441,14 @@ msgid "" "```rust,editable\n" "fn generate_random_number() -> i32 {\n" " 4 // Chosen by fair dice roll. Guaranteed to be random.\n" -"}" -msgstr "" - -#: src/enums.md:11 -#, fuzzy -msgid "" +"}\n" +"\n" "#[derive(Debug)]\n" "enum CoinFlip {\n" " Heads,\n" " Tails,\n" -"}" -msgstr "" -"#[ableiten(Debuggen)]\n" -"enum CoinFlip {\n" -" Köpfe,\n" -" Schwänze,\n" -"}" - -#: src/enums.md:17 -msgid "" +"}\n" +"\n" "fn flip_coin() -> CoinFlip {\n" " let random_number = generate_random_number();\n" " if random_number % 2 == 0 {\n" @@ -5812,27 +5456,19 @@ msgid "" " } else {\n" " return CoinFlip::Tails;\n" " }\n" -"}" -msgstr "" - -#: src/enums.md:26 -msgid "" +"}\n" +"\n" "fn main() {\n" " println!(\"You got: {:?}\", flip_coin());\n" "}\n" "```" msgstr "" -#: src/enums.md:31 +#: 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 "" -"
\n" -" \n" -"Key Points:" -msgstr "" -"
\n" -" \n" -"Wichtige Punkte:" +msgid "Key Points:" +msgstr "Wichtige Punkte:" #: src/enums.md:35 #, fuzzy @@ -5845,8 +5481,7 @@ msgid "" "types of fields (variant payloads). \n" " * In both, associated functions are defined within an `impl` block.\n" " * You could even implement the different variants of an enum with separate structs but then they " -"wouldn’t be the same type as they would if they were all defined in an enum. \n" -"
" +"wouldn’t be the same type as they would if they were all defined in an enum. " msgstr "" "* Aufzählungen ermöglichen es Ihnen, eine Reihe von Werten unter einem Typ zu sammeln\n" "* Diese Seite bietet einen Aufzählungstyp `CoinFlip` mit zwei Varianten `Heads` und `Tail`. " @@ -5882,12 +5517,8 @@ msgid "" " PageLoad, // Variant without payload\n" " KeyPress(char), // Tuple struct variant\n" " Click { x: i64, y: i64 }, // Full struct variant\n" -"}" -msgstr "" - -#: src/enums/variant-payloads.md:13 -#, fuzzy -msgid "" +"}\n" +"\n" "#[rustfmt::skip]\n" "fn inspect(event: WebEvent) {\n" " match event {\n" @@ -5895,27 +5526,13 @@ msgid "" " WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" " WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" " }\n" -"}" -msgstr "" -"#[rustfmt::skip]\n" -"fn inspect(event: WebEvent) {\n" -" Spielereignis {\n" -" WebEvent::PageLoad => println!(\"Seite geladen\"),\n" -" WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" -" WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" -" }\n" -"}" - -#: src/enums/variant-payloads.md:22 -msgid "" +"}\n" +"\n" "fn main() {\n" " let load = WebEvent::PageLoad;\n" " let press = WebEvent::KeyPress('x');\n" -" let click = WebEvent::Click { x: 20, y: 80 };" -msgstr "" - -#: src/enums/variant-payloads.md:27 -msgid "" +" let click = WebEvent::Click { x: 20, y: 80 };\n" +"\n" " inspect(load);\n" " inspect(press);\n" " inspect(click);\n" @@ -5924,19 +5541,25 @@ msgid "" msgstr "" #: src/enums/variant-payloads.md:35 -#, fuzzy msgid "" -"* In the above example, accessing the `char` in `KeyPress`, or `x` and `y` in `Click` only works " -"within a `match` statement.\n" +"* The values in the enum variants can only be accessed after being pattern matched. The pattern " +"binds references to the fields in the \"match arm\" after the `=>`.\n" +" * The expression is matched against the patterns from top to bottom. There is no fall-through " +"like in C or C++.\n" +" * The match expression has a value. The value is the last expression in the match arm which was " +"executed.\n" +" * Starting from the top we look for what pattern matches the value then run the code following " +"the arrow. Once we find a match, we stop. \n" +"* Demonstrate what happens when the search is inexhaustive. Note the advantage the Rust compiler " +"provides by confirming when all cases are handled. \n" "* `match` inspects a hidden discriminant field in the `enum`.\n" +"* It is possible to retrieve the discriminant by calling `std::mem::discriminant()`\n" +" * This is useful, for example, if implementing `PartialEq` for structs where comparing field " +"values doesn't affect equality.\n" "* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::Click(Click)` with a top level " -"`struct Click { ... }`. The inlined version cannot implement traits, for example." +"`struct Click { ... }`. The inlined version cannot implement traits, for example. \n" +" " msgstr "" -"* Im obigen Beispiel funktioniert der Zugriff auf „char“ in „KeyPress“ oder „x“ und „y“ in „Click“ " -"nur innerhalb einer „match“-Anweisung.\n" -"* „match“ untersucht ein verstecktes Diskriminanzfeld in „enum“.\n" -"* `WebEvent::Click { ... }` ist nicht genau dasselbe wie `WebEvent::Click(Click)` mit einem Top-" -"Level-`struct Click { ... }`. Die Inline-Version kann beispielsweise keine Traits implementieren." #: src/enums/sizes.md:1 #, fuzzy @@ -5953,98 +5576,160 @@ msgstr "" #: src/enums/sizes.md:5 msgid "" "```rust,editable\n" -"use std::mem::{align_of, size_of};" -msgstr "" - -#: src/enums/sizes.md:8 -msgid "" +"use std::mem::{align_of, size_of};\n" +"\n" "macro_rules! dbg_size {\n" " ($t:ty) => {\n" " println!(\"{}: size {} bytes, align: {} bytes\",\n" " stringify!($t), size_of::<$t>(), align_of::<$t>());\n" " };\n" -"}" -msgstr "" - -#: src/enums/sizes.md:15 -#, fuzzy -msgid "" +"}\n" +"\n" "enum Foo {\n" " A,\n" " B,\n" -"}" -msgstr "" -"Aufzählung Foo {\n" -" A,\n" -" B,\n" -"}" - -#: src/enums/sizes.md:20 -#, fuzzy -msgid "" -"#[repr(u32)]\n" -"enum Bar {\n" -" A, // 0\n" -" B = 10000,\n" -" C, // 10001\n" -"}" -msgstr "" -"#[repr(u32)]\n" -"Aufzählungsbalken {\n" -" A, // 0\n" -" B = 10000,\n" -" C, // 10001\n" -"}" - -#: src/enums/sizes.md:27 -msgid "" +"}\n" +"\n" "fn main() {\n" " dbg_size!(Foo);\n" -" dbg_size!(Bar);\n" -" dbg_size!(bool);\n" -" dbg_size!(Option);\n" -" dbg_size!(&i32);\n" -" dbg_size!(Option<&i32>);\n" "}\n" "```" msgstr "" -#: src/enums/sizes.md:37 +#: src/enums/sizes.md:25 #, fuzzy msgid "* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout.html)." msgstr "* Siehe die [Rust-Referenz] (https://doc.rust-lang.org/reference/type-layout.html)." -#: src/enums/sizes.md:39 -#, fuzzy +#: src/enums/sizes.md:31 msgid "" -"
\n" -" \n" -"Key Points: \n" " * Internally Rust is using a field (discriminant) to keep track of the enum variant.\n" -" * `Bar` enum demonstrates that there is a way to control the discriminant value and type. If " -"`repr` is removed, the discriminant type takes 2 bytes, becuase 10001 fits 2 bytes.\n" -" * As a niche optimization an enum discriminant is merged with the pointer so that `Option<&Foo>` " -"is the same size as `&Foo`.\n" -" * `Option` is another example of tight packing.\n" -" * For [some types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees that " -"`size_of::()` equals `size_of::>()`.\n" -" * Zero-sized types allow for efficient implementation of `HashSet` using `HashMap` with `()` as " -"the value." -msgstr "" -"
\n" -" \n" -"Wichtige Punkte:\n" -" * Rust verwendet intern ein Feld (Discriminant), um die Enum-Variante zu verfolgen.\n" -" * `Bar` enum demonstriert, dass es eine Möglichkeit gibt, den Diskriminanzwert und -typ zu " -"steuern. Wenn \"repr\" entfernt wird, nimmt der Diskriminantentyp 2 Bytes ein, da 10001 auf 2 " -"Bytes passt.\n" -" * Als Nischenoptimierung wird eine Enum-Diskriminante mit dem Zeiger zusammengeführt, sodass " -"`Option<&Foo>` die gleiche Größe wie `&Foo` hat.\n" -" * `Option` ist ein weiteres Beispiel für Tight Packing.\n" -" * Für [einige Typen](https://doc.rust-lang.org/std/option/#representation) garantiert Rust, dass " -"„size_of::()“ gleich „size_of::“ ist >()`.\n" -" * Typen mit der Größe Null ermöglichen eine effiziente Implementierung von `HashSet` unter " -"Verwendung von `HashMap` mit `()` als Wert." +"\n" +" * You can control the discriminant if needed (e.g., for compatibility with C):\n" +" \n" +" ```rust,editable\n" +" #[repr(u32)]\n" +" enum Bar {\n" +" A, // 0\n" +" B = 10000,\n" +" C, // 10001\n" +" }\n" +" \n" +" fn main() {\n" +" println!(\"A: {}\", Bar::A as u32);\n" +" println!(\"B: {}\", Bar::B as u32);\n" +" println!(\"C: {}\", Bar::C as u32);\n" +" }\n" +" ```\n" +"\n" +" Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2\n" +" bytes.\n" +"\n" +"\n" +" * Try out other types such as\n" +" \n" +" * `dbg_size!(bool)`: size 1 bytes, align: 1 bytes,\n" +" * `dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche optimization, see below),\n" +" * `dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit machine),\n" +" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer optimization, see " +"below).\n" +"\n" +" * Niche optimization: Rust will merge use unused bit patterns for the enum\n" +" discriminant.\n" +"\n" +" * Null pointer optimization: For [some\n" +" types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees\n" +" that `size_of::()` equals `size_of::>()`.\n" +"\n" +" Example code if you want to show how the bitwise representation *may* look like in practice.\n" +" It's important to note that the compiler provides no guarantees regarding this " +"representation, therefore this is totally unsafe.\n" +"\n" +" ```rust,editable\n" +" use std::mem::transmute;\n" +"\n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" println!(\"Bitwise representation of bool\");\n" +" dbg_bits!(false, u8);\n" +" dbg_bits!(true, u8);\n" +"\n" +" println!(\"Bitwise representation of Option\");\n" +" dbg_bits!(None::, u8);\n" +" dbg_bits!(Some(false), u8);\n" +" dbg_bits!(Some(true), u8);\n" +"\n" +" println!(\"Bitwise representation of Option>\");\n" +" dbg_bits!(Some(Some(false)), u8);\n" +" dbg_bits!(Some(Some(true)), u8);\n" +" dbg_bits!(Some(None::), u8);\n" +" dbg_bits!(None::>, u8);\n" +"\n" +" println!(\"Bitwise representation of Option<&i32>\");\n" +" dbg_bits!(None::<&i32>, usize);\n" +" dbg_bits!(Some(&0i32), usize);\n" +" }\n" +" }\n" +" ```\n" +"\n" +" More complex example if you want to discuss what happens when we chain more than 256 " +"`Option`s together.\n" +"\n" +" ```rust,editable\n" +" #![recursion_limit = \"1000\"]\n" +"\n" +" use std::mem::transmute;\n" +" \n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" // Macro to wrap a value in 2^n Some() where n is the number of \"@\" signs.\n" +" // Increasing the recursion limit is required to evaluate this macro.\n" +" macro_rules! many_options {\n" +" ($value:expr) => { Some($value) };\n" +" ($value:expr, @) => {\n" +" Some(Some($value))\n" +" };\n" +" ($value:expr, @ $($more:tt)+) => {\n" +" many_options!(many_options!($value, $($more)+), $($more)+)\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" assert_eq!(many_options!(false), Some(false));\n" +" assert_eq!(many_options!(false, @), Some(Some(false)));\n" +" assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));\n" +"\n" +" println!(\"Bitwise representation of a chain of 128 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" +" dbg_bits!(many_options!(true, @@@@@@@), u8);\n" +"\n" +" println!(\"Bitwise representation of a chain of 256 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(true, @@@@@@@@), u16);\n" +"\n" +" println!(\"Bitwise representation of a chain of 257 Option's.\");\n" +" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" +" }\n" +" }\n" +" ```" +msgstr "" #: src/methods.md:3 #, fuzzy @@ -6055,17 +5740,21 @@ msgstr "" "Mit Rust können Sie Ihren neuen Typen Funktionen zuordnen. Das machst du mit einem\n" "`impl`-Block:" -#: src/methods.md:13 +#: src/methods.md:6 msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" "impl Person {\n" " fn say_hello(&self) {\n" " println!(\"Hello, my name is {}\", self.name);\n" " }\n" -"}" -msgstr "" - -#: src/methods.md:19 -msgid "" +"}\n" +"\n" "fn main() {\n" " let peter = Person {\n" " name: String::from(\"Peter\"),\n" @@ -6076,10 +5765,9 @@ msgid "" "```" msgstr "" -#: src/methods.md:30 +#: src/methods.md:31 #, fuzzy msgid "" -"Key Points:\n" "* It can be helpful to introduce methods by comparing them to functions.\n" " * Methods are called on an instance of a type (such as a struct or enum), the first parameter " "represents the instance as `self`.\n" @@ -6089,17 +5777,15 @@ msgid "" "* Point out the use of the keyword `self`, a method receiver. \n" " * Show that it is an abbreviated term for `self:&Self` and perhaps show how the struct name " "could also be used. \n" -" * Explain that Self is a type alias for the type the `impl` block is in and can be used " +" * Explain that `Self` is a type alias for the type the `impl` block is in and can be used " "elsewhere in the block.\n" -" * Note how self is used like other structs and dot notation can be used to refer to individual " +" * Note how `self` is used like other structs and dot notation can be used to refer to individual " "fields.\n" " * This might be a good time to demonstrate how the `&self` differs from `self` by modifying the " "code and trying to run say_hello twice. \n" "* We describe the distinction between method receivers next.\n" -" \n" -"
" +" " msgstr "" -"Wichtige Punkte:\n" "* Es kann hilfreich sein, Methoden einzuführen, indem man sie mit Funktionen vergleicht.\n" " * Methoden werden für eine Instanz eines Typs aufgerufen (z. B. eine Struktur oder Aufzählung), " "der erste Parameter repräsentiert die Instanz als „self“.\n" @@ -6173,20 +5859,14 @@ 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:23 +#: src/methods/receiver.md:25 #, fuzzy msgid "" -"
\n" -" \n" -"Consider emphasizing on \"shared and immutable\" and \"unique and mutable\". These constraints " -"always come\n" -"together in Rust due to borrow checker rules, and `self` is no exception. It won't be possible to\n" -"reference a struct from multiple locations and call a mutating (`&mut self`) method on it.\n" -" \n" -"
" +"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". These constraints always " +"come\n" +"together in Rust due to borrow checker rules, and `self` is no exception. It isn't possible to\n" +"reference a struct from multiple locations and call a mutating (`&mut self`) method on it." msgstr "" -"
\n" -" \n" "Erwägen Sie, die Betonung auf „gemeinsam und unveränderlich“ und „einzigartig und veränderlich“ zu " "legen. Diese Einschränkungen kommen immer\n" "zusammen in Rust aufgrund der Borrow-Checker-Regeln, und `self` ist keine Ausnahme. Es wird nicht " @@ -6208,50 +5888,30 @@ msgid "" "struct Race {\n" " name: String,\n" " laps: Vec,\n" -"}" -msgstr "" - -#: src/methods/example.md:10 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Race {\n" " fn new(name: &str) -> Race { // No receiver, a static method\n" " Race { name: String::from(name), laps: Vec::new() }\n" -" }" -msgstr "" -"impl Rennen {\n" -" fn new(name: &str) -> Race { // Kein Empfänger, eine statische Methode\n" -" Rennen { Name: String::from(Name), Runden: Vec::new() }\n" -" }" - -#: src/methods/example.md:15 -msgid "" +" }\n" +"\n" " fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write access to self\n" " self.laps.push(lap);\n" -" }" -msgstr "" - -#: src/methods/example.md:19 -msgid "" +" }\n" +"\n" " fn print_laps(&self) { // Shared and read-only borrowed access to self\n" " println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" " for (idx, lap) in self.laps.iter().enumerate() {\n" " println!(\"Lap {idx}: {lap} sec\");\n" " }\n" -" }" -msgstr "" - -#: src/methods/example.md:26 -msgid "" +" }\n" +"\n" " fn finish(self) { // Exclusive ownership of self\n" " let total = self.laps.iter().sum::();\n" " println!(\"Race {} is finished, total lap time: {}\", self.name, total);\n" " }\n" -"}" -msgstr "" - -#: src/methods/example.md:32 -msgid "" +"}\n" +"\n" "fn main() {\n" " let mut race = Race::new(\"Monaco Grand Prix\");\n" " race.add_lap(70);\n" @@ -6265,26 +5925,20 @@ msgid "" "```" msgstr "" -#: src/methods/example.md:44 +#: src/methods/example.md:47 #, fuzzy msgid "" -"
\n" -" \n" -"Key Points:\n" "* All four methods here use a different method receiver.\n" " * You can point out how that changes what the function can do with the variable values and if/" "how it can be used again in `main`.\n" " * You can showcase the error that appears when trying to call `finish` twice.\n" -"* Note, that although the method receivers are different, the non-static functions are called the " +"* Note that although the method receivers are different, the non-static functions are called the " "same way in the main body. Rust enables automatic referencing and dereferencing when calling " "methods. Rust automatically adds in the `&`, `*`, `muts` so that that object matches the method " "signature.\n" "* You might point out that `print_laps` is using a vector that is iterated over. We describe " "vectors in more detail in the afternoon. " msgstr "" -"
\n" -" \n" -"Wichtige Punkte:\n" "* Alle vier Methoden hier verwenden einen anderen Methodenempfänger.\n" " * Sie können darauf hinweisen, wie sich das ändert, was die Funktion mit den Variablenwerten " "machen kann und ob/wie sie wieder in `main` verwendet werden kann.\n" @@ -6320,11 +5974,8 @@ msgstr "Die Muster können einfache Werte sein, ähnlich wie `switch` in C und C msgid "" "```rust,editable\n" "fn main() {\n" -" let input = 'x';" -msgstr "" - -#: src/pattern-matching.md:12 -msgid "" +" let input = 'x';\n" +"\n" " match input {\n" " 'q' => println!(\"Quitting\"),\n" " 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" @@ -6340,12 +5991,9 @@ msgstr "" msgid "The `_` pattern is a wildcard pattern which matches any value." msgstr "Das `_`-Muster ist ein Platzhaltermuster, das jedem Wert entspricht." -#: src/pattern-matching.md:23 +#: src/pattern-matching.md:26 #, fuzzy msgid "" -"
\n" -" \n" -"Key Points:\n" "* You might point out how some specific characters are being used when in a pattern\n" " * `|` as an `or`\n" " * `..` can expand as much as it needs to be\n" @@ -6356,12 +6004,8 @@ msgid "" "* You can demonstrate matching on a reference.\n" "* This might be a good time to bring up the concept of irrefutable patterns, as the term can show " "up in error messages.\n" -" \n" -"
" +" " msgstr "" -"
\n" -" \n" -"Wichtige Punkte:\n" "* Sie können darauf hinweisen, wie bestimmte Zeichen in einem Muster verwendet werden\n" " * `|` als `oder`\n" " * `..` kann beliebig erweitert werden\n" @@ -6395,30 +6039,16 @@ msgid "" "enum Result {\n" " Ok(i32),\n" " Err(String),\n" -"}" -msgstr "" - -#: src/pattern-matching/destructuring-enums.md:12 -#, fuzzy -msgid "" +"}\n" +"\n" "fn divide_in_two(n: i32) -> Result {\n" " if n % 2 == 0 {\n" " Result::Ok(n / 2)\n" " } else {\n" -" Result::Err(format!(\"cannot divide {} into two equal parts\", n))\n" -" }\n" -"}" -msgstr "" -"fn divide_in_two(n: i32) -> Ergebnis {\n" -" wenn n % 2 == 0 {\n" -" Ergebnis::Okay(n / 2)\n" -" } anders {\n" -" Ergebnis::Err(format!(\"kann {} nicht in zwei gleiche Teile teilen\", n))\n" +" Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" " }\n" -"}" - -#: src/pattern-matching/destructuring-enums.md:20 -msgid "" +"}\n" +"\n" "fn main() {\n" " let n = 100;\n" " match divide_in_two(n) {\n" @@ -6440,16 +6070,14 @@ msgstr "" "arm, `half` ist an den Wert innerhalb der `Ok`-Variante gebunden. Im zweiten Arm,\n" "`msg` wird an die Fehlermeldung gebunden." -#: src/pattern-matching/destructuring-enums.md:35 +#: src/pattern-matching/destructuring-enums.md:36 #, fuzzy msgid "" -"Key points:\n" "* The `if`/`else` expression is returning an enum that is later unpacked with a `match`.\n" "* You can try adding a third variant to the enum definition and displaying the errors when running " -"the code. Point out the places where your code is now inexhaustive and how the compiler trys to " +"the code. Point out the places where your code is now inexhaustive and how the compiler tries to " "give you hints." msgstr "" -"Kernpunkte:\n" "* Der `if`/`else`-Ausdruck gibt eine Aufzählung zurück, die später mit einem `match` entpackt " "wird.\n" "* Sie können versuchen, der Enum-Definition eine dritte Variante hinzuzufügen und die Fehler beim " @@ -6472,23 +6100,26 @@ msgid "" "struct Foo {\n" " x: (u32, u32),\n" " y: u32,\n" -"}" -msgstr "" - -#: src/pattern-matching/destructuring-structs.md:11 -msgid "" +"}\n" +"\n" "#[rustfmt::skip]\n" "fn main() {\n" " let foo = Foo { x: (1, 2), y: 3 };\n" " match foo {\n" " Foo { x: (1, b), y } => println!(\"x.0 = 1, b = {b}, y = {y}\"),\n" -" Foo { y: 2, x: i } => println!(\"y = 2, i = {i:?}\"),\n" +" Foo { y: 2, x: i } => println!(\"y = 2, x = {i:?}\"),\n" " Foo { y, .. } => println!(\"y = {y}, other fields were ignored\"),\n" " }\n" "}\n" "```" 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." +msgstr "" + #: src/pattern-matching/destructuring-arrays.md:1 #, fuzzy msgid "# Destructuring Arrays" @@ -6515,6 +6146,34 @@ msgid "" "```" msgstr "" +#: src/pattern-matching/destructuring-arrays.md:21 +msgid "" +"* Destructuring of slices of unknown length also works with patterns of fixed length.\n" +"\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" inspect(&[0, -2, 3]);\n" +" inspect(&[0, -2, 3, 4]);\n" +" }\n" +"\n" +" #[rustfmt::skip]\n" +" fn inspect(slice: &[i32]) {\n" +" println!(\"Tell me about {slice:?}\");\n" +" match slice {\n" +" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +" }\n" +" ```\n" +" \n" +"* Create a new pattern using `_` to represent an element. \n" +"* Add more values to the array.\n" +"* Point out that how `..` will expand to account for different number of elements.\n" +"* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`" +msgstr "" + #: src/pattern-matching/match-guards.md:1 #, fuzzy msgid "# Match Guards" @@ -6547,20 +6206,18 @@ msgid "" "```" msgstr "" -#: src/pattern-matching/match-guards.md:22 +#: src/pattern-matching/match-guards.md:23 #, fuzzy msgid "" -"Key Points:\n" -"* Match guards as a separate syntax feature are important and necessary.\n" +"* Match guards as a separate syntax feature are important and necessary when we wish to concisely " +"express more complex ideas than patterns alone would allow.\n" "* They are not the same as separate `if` expression inside of the match arm. An `if` expression " "inside of the branch block (after `=>`) happens after the match arm is selected. Failing the `if` " "condition inside of that block won't result in other arms\n" "of the original `match` expression being considered. \n" "* You can use the variables defined in the pattern in your if expression.\n" -"* The condition defined in the guard applies to every expression in a pattern with an `|`.\n" -"
" +"* The condition defined in the guard applies to every expression in a pattern with an `|`." msgstr "" -"Wichtige Punkte:\n" "* Match Guards als separates Syntax-Feature sind wichtig und notwendig.\n" "* Sie sind nicht dasselbe wie ein separater „if“-Ausdruck innerhalb des Match-Arms. Ein „if“-" "Ausdruck innerhalb des Verzweigungsblocks (nach „=>“) erfolgt, nachdem der Match-Arm ausgewählt " @@ -6583,12 +6240,10 @@ msgstr "Wir werden Implementierungsmethoden in zwei Kontexten betrachten:" #: src/exercises/day-2/morning.md:5 #, fuzzy -msgid "* Simple struct which tracks health statistics." -msgstr "* Einfache Struktur, die Gesundheitsstatistiken verfolgt." - -#: src/exercises/day-2/morning.md:7 -#, fuzzy -msgid "* Multiple structs and enums for a drawing library." +msgid "" +"* Simple struct which tracks health statistics.\n" +"\n" +"* Multiple structs and enums for a drawing library." msgstr "* Mehrere Strukturen und Aufzählungen für eine Zeichnungsbibliothek." #: src/exercises/day-2/health-statistics.md:1 @@ -6626,110 +6281,55 @@ msgstr "" "aus\n" "Methoden:" -#: src/exercises/day-2/health-statistics.md:17 -#, fuzzy +#: src/exercises/day-2/health-statistics.md:13 msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" "struct User {\n" " name: String,\n" " age: u32,\n" " weight: f32,\n" -"}" -msgstr "" -"Struktur Benutzer {\n" -" Name: Zeichenfolge,\n" -" Alter: u32,\n" -" Gewicht: f32,\n" -"}" - -#: src/exercises/day-2/health-statistics.md:23 -#, fuzzy -msgid "" +"}\n" +"\n" "impl User {\n" " pub fn new(name: String, age: u32, weight: f32) -> Self {\n" " unimplemented!()\n" -" }" -msgstr "" -"impl Benutzer {\n" -" pub fn new(name: String, age: u32, weight: f32) -> Self {\n" -" nicht implementiert!()\n" -" }" - -#: src/exercises/day-2/health-statistics.md:28 -#, fuzzy -msgid "" +" }\n" +"\n" " pub fn name(&self) -> &str {\n" " unimplemented!()\n" -" }" -msgstr "" -" pub fn name(&self) -> &str {\n" -" nicht implementiert!()\n" -" }" - -#: src/exercises/day-2/health-statistics.md:32 -#, fuzzy -msgid "" +" }\n" +"\n" " pub fn age(&self) -> u32 {\n" " unimplemented!()\n" -" }" -msgstr "" -" pub fn alter(&selbst) -> u32 {\n" -" nicht implementiert!()\n" -" }" - -#: src/exercises/day-2/health-statistics.md:36 -#, fuzzy -msgid "" +" }\n" +"\n" " pub fn weight(&self) -> f32 {\n" " unimplemented!()\n" -" }" -msgstr "" -" pub fn Gewicht(&self) -> f32 {\n" -" nicht implementiert!()\n" -" }" - -#: src/exercises/day-2/health-statistics.md:40 -#, fuzzy -msgid "" +" }\n" +"\n" " pub fn set_age(&mut self, new_age: u32) {\n" " unimplemented!()\n" -" }" -msgstr "" -" pub fn set_age(&mut selbst, new_age: u32) {\n" -" nicht implementiert!()\n" -" }" - -#: src/exercises/day-2/health-statistics.md:44 -#, fuzzy -msgid "" -" pub fn set_weight(&mut self, new_weight: f32) {\n" -" unimplemented!()\n" " }\n" -"}" -msgstr "" +"\n" " pub fn set_weight(&mut self, new_weight: f32) {\n" -" nicht implementiert!()\n" +" unimplemented!()\n" " }\n" -"}" - -#: src/exercises/day-2/health-statistics.md:49 -msgid "" +"}\n" +"\n" "fn main() {\n" " let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" " println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" -"}" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:54 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_weight() {\n" " let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" " assert_eq!(bob.weight(), 155.2);\n" -"}" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:60 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_set_age() {\n" " let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" @@ -6757,181 +6357,93 @@ msgstr "" "zu und füllen Sie die fehlenden Methoden aus, um die\n" "Tests bestehen:" -#: src/exercises/day-2/points-polygons.md:7 src/exercises/day-2/luhn.md:23 -#: src/exercises/day-2/strings-iterators.md:12 +#: src/exercises/day-2/points-polygons.md:7 msgid "" "```rust\n" "// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:11 -#, fuzzy -msgid "" +"#![allow(unused_variables, dead_code)]\n" +"\n" "pub struct Point {\n" " // add fields\n" -"}" -msgstr "" -"pub struct Punkt {\n" -" // Felder hinzufügen\n" -"}" - -#: src/exercises/day-2/points-polygons.md:15 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Point {\n" " // add methods\n" -"}" -msgstr "" -"impl Punkt {\n" -" // Methoden hinzufügen\n" -"}" - -#: src/exercises/day-2/points-polygons.md:19 -#, fuzzy -msgid "" +"}\n" +"\n" "pub struct Polygon {\n" " // add fields\n" -"}" -msgstr "" -"pub struct Polygon {\n" -" // Felder hinzufügen\n" -"}" - -#: src/exercises/day-2/points-polygons.md:23 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Polygon {\n" " // add methods\n" -"}" -msgstr "" -"impl Polygon {\n" -" // Methoden hinzufügen\n" -"}" - -#: src/exercises/day-2/points-polygons.md:27 -#, fuzzy -msgid "" +"}\n" +"\n" "pub struct Circle {\n" " // add fields\n" -"}" -msgstr "" -"pub struct Kreis {\n" -" // Felder hinzufügen\n" -"}" - -#: src/exercises/day-2/points-polygons.md:31 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Circle {\n" " // add methods\n" -"}" -msgstr "" -"impl Kreis {\n" -" // Methoden hinzufügen\n" -"}" - -#: src/exercises/day-2/points-polygons.md:35 -#, fuzzy -msgid "" +"}\n" +"\n" "pub enum Shape {\n" " Polygon(Polygon),\n" " Circle(Circle),\n" -"}" -msgstr "" -"Pub-Aufzählung Form {\n" -" Vieleck(Vieleck),\n" -" Kreis (Kreis),\n" -"}" - -#: src/exercises/day-2/points-polygons.md:40 src/testing/test-modules.md:15 -msgid "" +"}\n" +"\n" "#[cfg(test)]\n" "mod tests {\n" -" use super::*;" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:44 src/exercises/day-2/solutions-morning.md:165 -#, fuzzy -msgid "" +" use super::*;\n" +"\n" " fn round_two_digits(x: f64) -> f64 {\n" " (x * 100.0).round() / 100.0\n" -" }" -msgstr "" -" fn round_two_digits(x: f64) -> f64 {\n" -" (x * 100.0).round() / 100.0\n" -" }" - -#: src/exercises/day-2/points-polygons.md:48 src/exercises/day-2/solutions-morning.md:169 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_point_magnitude() {\n" " let p1 = Point::new(12, 13);\n" " assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:54 src/exercises/day-2/solutions-morning.md:175 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_point_dist() {\n" " let p1 = Point::new(10, 10);\n" " let p2 = Point::new(14, 13);\n" " assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:61 src/exercises/day-2/solutions-morning.md:182 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_point_add() {\n" " let p1 = Point::new(16, 16);\n" " let p2 = p1 + Point::new(-4, 3);\n" " assert_eq!(p2, Point::new(12, 19));\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:68 src/exercises/day-2/solutions-morning.md:189 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_polygon_left_most_point() {\n" " let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:73 src/exercises/day-2/solutions-morning.md:194 -msgid "" +" let p2 = Point::new(16, 16);\n" +"\n" " let mut poly = Polygon::new();\n" " poly.add_point(p1);\n" " poly.add_point(p2);\n" " assert_eq!(poly.left_most_point(), Some(p1));\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:79 src/exercises/day-2/solutions-morning.md:200 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_polygon_iter() {\n" " let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:84 src/exercises/day-2/solutions-morning.md:205 -msgid "" +" let p2 = Point::new(16, 16);\n" +"\n" " let mut poly = Polygon::new();\n" " poly.add_point(p1);\n" -" poly.add_point(p2);" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:88 src/exercises/day-2/solutions-morning.md:209 -msgid "" +" poly.add_point(p2);\n" +"\n" " let points = poly.iter().cloned().collect::>();\n" " assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:92 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_shape_perimeters() {\n" " let mut poly = Polygon::new();\n" @@ -6949,12 +6461,8 @@ msgid "" " .collect::>();\n" " assert_eq!(perimeters, vec![15.48, 31.42]);\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:111 src/exercises/day-2/luhn.md:68 -#: src/exercises/day-2/solutions-morning.md:233 -msgid "" +"}\n" +"\n" "#[allow(dead_code)]\n" "fn main() {}\n" "```" @@ -6964,22 +6472,24 @@ msgstr "" #, fuzzy msgid "" "Since the method signatures are missing from the problem statements, the key part\n" -"of the exercise is to specify those correctly." +"of the exercise is to specify those correctly. You don't have to modify the tests." msgstr "" "Da die Methodensignaturen in den Problembeschreibungen fehlen, ist der Schlüsselteil\n" "der Übung ist es, diese richtig anzugeben." #: src/exercises/day-2/points-polygons.md:120 #, fuzzy +msgid "Other interesting parts of the exercise:" +msgstr "Weitere interessante Teile der Übung:\n" + +#: src/exercises/day-2/points-polygons.md:122 +#, fuzzy msgid "" -"Other interesting parts of the exercise:\n" -" \n" "* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their " "arguments.\n" -"* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". " +"* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". Note that " +"we do not discuss generics until Day 3." msgstr "" -"Weitere interessante Teile der Übung:\n" -" \n" "* Leiten Sie ein `Copy`-Merkmal für einige Strukturen ab, da die Methoden in Tests ihre Argumente " "manchmal nicht ausleihen.\n" "* Entdecken Sie, dass die Eigenschaft „Hinzufügen“ implementiert werden muss, damit zwei Objekte " @@ -7053,11 +6563,8 @@ msgid "" "```rust,editable\n" "fn double(x: i32) -> i32 {\n" " x + x\n" -"}" -msgstr "" - -#: src/control-flow/blocks.md:33 -msgid "" +"}\n" +"\n" "fn main() {\n" " println!(\"doubled: {}\", double(7));\n" "}\n" @@ -7068,17 +6575,14 @@ msgstr "" msgid "However if the last expression ends with `;`, then the resulting value and type is `()`." msgstr "" -#: src/control-flow/blocks.md:42 +#: src/control-flow/blocks.md:43 #, fuzzy msgid "" -"Key Points:\n" "* The point of this slide is to show that blocks have a type and value in Rust. \n" "* You can show how the value of the block changes by changing the last line in the block. For " "instance, adding/removing a semicolon or using a `return`.\n" -" \n" -"
" +" " msgstr "" -"Wichtige Punkte:\n" "* Der Zweck dieser Folie ist es zu zeigen, dass Blöcke in Rust einen Typ und einen Wert haben.\n" "* Sie können zeigen, wie sich der Wert des Blocks ändert, indem Sie die letzte Zeile im Block " "ändern. Zum Beispiel das Hinzufügen/Entfernen eines Semikolons oder die Verwendung eines " @@ -7132,9 +6636,7 @@ msgstr "" #: src/control-flow/if-expressions.md:31 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.\n" -" \n" -"
" +"the same type. Consider showing what happens if you add `;` after `x / 2` in the second example." msgstr "" #: src/control-flow/if-let-expressions.md:1 @@ -7172,21 +6674,28 @@ msgstr "" "Rost." #: src/control-flow/if-let-expressions.md:21 -#, fuzzy 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" -" * For the similar use case consider demonstrating a newly stabilized [`let else`](https://" -"github.com/rust-lang/rust/pull/93628) feature.\n" "* A common usage is handling `Some` values when working with `Option`.\n" -"* Unlike `match`, `if let` does not support guard clauses for pattern matching." +"* Unlike `match`, `if let` does not support guard clauses for pattern matching.\n" +"* Since 1.65, a similar [let-else](https://doc.rust-lang.org/rust-by-example/flow_control/let_else." +"html) construct allows to do a destructuring assignment, or if it fails, have a non-returning " +"block branch (panic/return/break/continue):\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" println!(\"{:?}\", second_word_to_upper(\"foo bar\"));\n" +" }\n" +" \n" +" fn second_word_to_upper(s: &str) -> Option {\n" +" let mut it = s.split(' ');\n" +" let (Some(_), Some(item)) = (it.next(), it.next()) else {\n" +" return None;\n" +" };\n" +" Some(item.to_uppercase())\n" +" }" msgstr "" -"* `if let` kann prägnanter sein als `match`, z. B. wenn nur ein Fall interessant ist. Im Gegensatz " -"dazu erfordert \"Match\", dass alle Zweige abgedeckt werden.\n" -" * Ziehen Sie für einen ähnlichen Anwendungsfall in Betracht, eine neu stabilisierte [`let " -"else`](https://github.com/rust-lang/rust/pull/93628)-Funktion zu demonstrieren.\n" -"* Eine übliche Verwendung ist die Handhabung von `Some`-Werten bei der Arbeit mit `Option`.\n" -"* Im Gegensatz zu `match` unterstützt `if let` keine Schutzklauseln für den Mustervergleich." #: src/control-flow/while-expressions.md:1 #, fuzzy @@ -7234,11 +6743,8 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();" -msgstr "" - -#: src/control-flow/while-let-expressions.md:11 -msgid "" +" let mut iter = v.into_iter();\n" +"\n" " while let Some(x) = iter.next() {\n" " println!(\"x: {x}\");\n" " }\n" @@ -7264,8 +6770,7 @@ msgid "" "* You could rewrite the `while let` loop as an infinite loop with an if statement that breaks when " "there is no value to unwrap for `iter.next()`. The `while let` provides syntactic sugar for the " "above scenario.\n" -" \n" -"
" +" " msgstr "" "* Weisen Sie darauf hin, dass die „while let“-Schleife so lange läuft, wie der Wert mit dem Muster " "übereinstimmt.\n" @@ -7293,11 +6798,8 @@ msgstr "" msgid "" "```rust,editable\n" "fn main() {\n" -" let v = vec![10, 20, 30];" -msgstr "" - -#: src/control-flow/for-expressions.md:10 -msgid "" +" let v = vec![10, 20, 30];\n" +"\n" " for x in v {\n" " println!(\"x: {x}\");\n" " }\n" @@ -7314,19 +6816,15 @@ msgstr "" 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:22 +#: src/control-flow/for-expressions.md:24 #, fuzzy msgid "" -"
\n" -" \n" "* Index iteration is not a special syntax in Rust for just that case.\n" "* `(0..10)` is a range that implements an `Iterator` trait. \n" "* `step_by` is a method that returns another `Iterator` that skips every other element. \n" -" \n" -"
" +"* Modify the elements in the vector and explain the compiler errors. Change vector `v` to be " +"mutable and the for loop to `for x in v.iter_mut()`." msgstr "" -"
\n" -" \n" "* Index-Iteration ist in Rust keine spezielle Syntax für genau diesen Fall.\n" "* „(0..10)“ ist ein Bereich, der ein „Iterator“-Merkmal implementiert.\n" "* „step_by“ ist eine Methode, die einen weiteren „Iterator“ zurückgibt, der jedes andere Element " @@ -7369,6 +6867,10 @@ msgid "" "```" msgstr "" +#: src/control-flow/loop-expressions.md:25 +msgid "* Break the `loop` with a value (e.g. `break 8`) and print it out." +msgstr "" + #: src/control-flow/match-expressions.md:1 #, fuzzy msgid "# `match` expressions" @@ -7409,6 +6911,17 @@ 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 +msgid "" +"* Save the match expression to a variable and print it out.\n" +"* Remove `.as_deref()` and explain the error.\n" +" * `std::env::args().next()` returns an `Option`, but we cannot match against " +"`String`.\n" +" * `as_deref()` transforms an `Option` to `Option<&T::Target>`. In our case, this turns " +"`Option` into `Option<&str>`.\n" +" * We can now use pattern matching to match against the `&str` inside `Option`." +msgstr "" + #: src/control-flow/break-continue.md:1 #, fuzzy msgid "# `break` and `continue`" @@ -7477,57 +6990,31 @@ msgid "The common vocabulary types include:" msgstr "Zu den gängigen Wortschatztypen gehören:" #: src/std.md:9 -#, fuzzy msgid "" "* [`Option` and `Result`](std/option-result.md) types: used for optional values\n" -" and [error handling](error-handling.md)." -msgstr "" -"* Typen von [`Option` und `Result`](std/option-result.md): Wird für optionale Werte verwendet\n" -" und [Fehlerbehandlung](error-handling.md)." - -#: src/std.md:12 -#, fuzzy -msgid "* [`String`](std/string.md): the default string type used for owned data." -msgstr "* [`String`](std/string.md): der Standard-String-Typ, der für eigene Daten verwendet wird." - -#: src/std.md:14 -#, fuzzy -msgid "* [`Vec`](std/vec.md): a standard extensible vector." -msgstr "* [`Vec`](std/vec.md): ein erweiterbarer Standardvektor." - -#: src/std.md:16 -#, fuzzy -msgid "" +" and [error handling](error-handling.md).\n" +"\n" +"* [`String`](std/string.md): the default string type used for owned data.\n" +"\n" +"* [`Vec`](std/vec.md): a standard extensible vector.\n" +"\n" "* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" -" algorithm." -msgstr "" -"* [`HashMap`](std/hashmap.md): ein Hash-Map-Typ mit konfigurierbarem Hashing\n" -" Algorithmus." - -#: src/std.md:19 -#, fuzzy -msgid "* [`Box`](std/box.md): an owned pointer for heap-allocated data." -msgstr "* [`Box`](std/box.md): ein eigener Zeiger für Heap-zugewiesene Daten." - -#: src/std.md:21 -#, fuzzy -msgid "* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated data." +" algorithm.\n" +"\n" +"* [`Box`](std/box.md): an owned pointer for heap-allocated data.\n" +"\n" +"* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated data." msgstr "" -"* [`Rc`](std/rc.md): ein gemeinsam genutzter referenzgezählter Zeiger für Heap-zugeordnete Daten." -#: src/std.md:23 +#: src/std.md:25 #, fuzzy msgid "" -"
\n" -" \n" " * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. \n" " * `core` includes the most basic types and functions that don't depend on `libc`, allocator or\n" " even the presence of an operating system. \n" " * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`.\n" " * Embedded Rust applications often only use `core`, and sometimes `alloc`." msgstr "" -"
\n" -" \n" " * Tatsächlich enthält Rust mehrere Schichten der Standardbibliothek: `core`, `alloc` und `std`.\n" " * `core` enthält die grundlegendsten Typen und Funktionen, die nicht von `libc`, allocator oder " "abhängen\n" @@ -7552,11 +7039,8 @@ msgid "" "fn main() {\n" " let numbers = vec![10, 20, 30];\n" " let first: Option<&i8> = numbers.first();\n" -" println!(\"first: {first:?}\");" -msgstr "" - -#: src/std/option-result.md:11 -msgid "" +" println!(\"first: {first:?}\");\n" +"\n" " let idx: Result = numbers.binary_search(&10);\n" " println!(\"idx: {idx:?}\");\n" "}\n" @@ -7597,19 +7081,13 @@ msgid "" "fn main() {\n" " let mut s1 = String::new();\n" " s1.push_str(\"Hello\");\n" -" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());" -msgstr "" - -#: src/std/string.md:11 -msgid "" +" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());\n" +"\n" " let mut s2 = String::with_capacity(s1.len() + 1);\n" " s2.push_str(&s1);\n" " s2.push('!');\n" -" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());" -msgstr "" - -#: src/std/string.md:16 -msgid "" +" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());\n" +"\n" " let s3 = String::from(\"🇨🇭\");\n" " println!(\"s3: len = {}, number of chars = {}\", s3.len(),\n" " s3.chars().count());\n" @@ -7626,26 +7104,26 @@ msgstr "" "`String` implementiert [`Deref`][2], was bedeutet, dass Sie alle aufrufen können\n" "`str`-Methoden auf einem `String`." -#: src/std/string.md:25 -#, fuzzy -msgid "" -"[1]: https://doc.rust-lang.org/std/string/struct.String.html\n" -"[2]: https://doc.rust-lang.org/std/string/struct.String.html#deref-methods-str" -msgstr "" -"[1]: https://doc.rust-lang.org/std/string/struct.String.html\n" -"[2]: https://doc.rust-lang.org/std/string/struct.String.html#deref-methods-str" - #: src/std/string.md:30 -#, fuzzy msgid "" -"* `len` returns the size of the `String` in bytes, not its length in characters.\n" -"* `chars` returns an iterator over the actual characters.\n" -"* `String` implements `Deref` which transparently gives it access to `str`'s methods." +"* `String::new` returns a new empty string, use `String::with_capacity` when you know how much " +"data you want to push to the string.\n" +"* `String::len` returns the size of the `String` in bytes (which can be different from its length " +"in characters).\n" +"* `String::chars` returns an iterator over the actual characters. Note that a `char` can be " +"different from what a human will consider a \"character\" due to [grapheme clusters](https://docs." +"rs/unicode-segmentation/latest/unicode_segmentation/struct.Graphemes.html).\n" +"* When people refer to strings they could either be talking about `&str` or `String`. \n" +"* When a type implements `Deref`, the compiler will let you transparently call methods " +"from `T`.\n" +" * `String` implements `Deref` which transparently gives it access to `str`'s " +"methods.\n" +" * 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." msgstr "" -"* `len` gibt die Größe des `String` in Bytes zurück, nicht seine Länge in Zeichen.\n" -"* `chars` gibt einen Iterator über die eigentlichen Zeichen zurück.\n" -"* `String` implementiert `Deref`, wodurch es transparent Zugriff auf die Methoden " -"von `str` erhält." #: src/std/vec.md:1 #, fuzzy @@ -7663,20 +7141,28 @@ msgid "" "fn main() {\n" " let mut v1 = Vec::new();\n" " v1.push(42);\n" -" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());" -msgstr "" - -#: src/std/vec.md:11 -msgid "" +" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());\n" +"\n" " let mut v2 = Vec::with_capacity(v1.len() + 1);\n" " v2.extend(v1.iter());\n" " v2.push(9999);\n" " println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());\n" +"\n" +" // Canonical macro to initialize a vector with elements.\n" +" let mut v3 = vec![0, 0, 1, 2, 3, 4];\n" +"\n" +" // Retain only the even elements.\n" +" v3.retain(|x| x % 2 == 0);\n" +" println!(\"{v3:?}\");\n" +"\n" +" // Remove consecutive duplicates.\n" +" v3.dedup();\n" +" println!(\"{v3:?}\");\n" "}\n" "```" msgstr "" -#: src/std/vec.md:18 +#: src/std/vec.md:29 #, fuzzy msgid "" "`Vec` implements [`Deref`][2], which means that you can call slice\n" @@ -7685,19 +7171,8 @@ msgstr "" "`Vec` implementiert [`Deref`][2], was bedeutet, dass Sie Slice aufrufen können\n" "Methoden auf einem `Vec`." -#: src/std/vec.md:21 -#, fuzzy -msgid "" -"[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" -"[2]: https://doc.rust-lang.org/std/vec/struct.Vec.html#deref-methods-[T]" -msgstr "" -"[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" -"[2]: https://doc.rust-lang.org/std/vec/struct.Vec.html#deref-methods-[T]" - -#: src/std/vec.md:24 +#: src/std/vec.md:37 msgid "" -"
\n" -" \n" "* `Vec` is a type of collection, along with `String` and `HashMap`. The data it contains is " "stored\n" " on the heap. This means the amount of data doesn't need to be known at compile time. It can " @@ -7707,7 +7182,7 @@ msgid "" "always\n" " with Rust type inference, the `T` was established during the first `push` call.\n" "* `vec![...]` is a canonical macro to use instead of `Vec::new()` and it supports adding initial\n" -" elements to the vector. \n" +" elements to the vector.\n" "* To index the vector you use `[` `]`, but they will panic if out of bounds. Alternatively, using\n" " `get` will return an `Option`. The `pop` function will remove the last element.\n" "* Show iterating over a vector and mutating the value:\n" @@ -7727,38 +7202,71 @@ msgstr "Standard-Hash-Map mit Schutz vor HashDoS-Angriffen:" #: src/std/hashmap.md:5 msgid "" "```rust,editable\n" -"use std::collections::HashMap;" -msgstr "" - -#: src/std/hashmap.md:8 -msgid "" +"use std::collections::HashMap;\n" +"\n" "fn main() {\n" " let mut page_counts = HashMap::new();\n" " page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), 207);\n" " page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" -" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);" -msgstr "" - -#: src/std/hashmap.md:14 -msgid "" +" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);\n" +"\n" " if !page_counts.contains_key(\"Les Misérables\") {\n" -" println!(\"We've know about {} books, but not Les Misérables.\",\n" +" println!(\"We know about {} books, but not Les Misérables.\",\n" " page_counts.len());\n" -" }" -msgstr "" - -#: src/std/hashmap.md:19 -msgid "" +" }\n" +"\n" " for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" " match page_counts.get(book) {\n" " Some(count) => println!(\"{book}: {count} pages\"),\n" " None => println!(\"{book} is unknown.\")\n" " }\n" " }\n" +"\n" +" // Use the .entry() method to insert a value if nothing is found.\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" +" let page_count: &mut i32 = page_counts.entry(book.to_string()).or_insert(0);\n" +" *page_count += 1;\n" +" }\n" +"\n" +" println!(\"{page_counts:#?}\");\n" "}\n" "```" msgstr "" +#: src/std/hashmap.md:38 +msgid "" +"* `HashMap` is not defined in the prelude and needs to be brought into scope.\n" +"* Try the following lines of code. The first line will see if a book is in the hashmap and if not " +"return an alternative value. The second line will insert the alternative value in the hashmap if " +"the book is not found.\n" +"\n" +" ```rust,ignore\n" +" let pc1 = page_counts\n" +" .get(\"Harry Potter and the Sorcerer's Stone \")\n" +" .unwrap_or(&336);\n" +" let pc2 = page_counts\n" +" .entry(\"The Hunger Games\".to_string())\n" +" .or_insert(374);\n" +" ```\n" +"* Unlike `vec!`, there is unfortunately no standard `hashmap!` macro.\n" +" * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], which allows us to " +"easily initialize a hash map from a literal array:\n" +"\n" +" ```rust,ignore\n" +" let page_counts = HashMap::from([\n" +" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" +" (\"The Hunger Games\".to_string(), 374),\n" +" ]);\n" +" ```\n" +"\n" +" * Alternatively HashMap can be built from any `Iterator` which yields key-value tuples.\n" +"* We are showing `HashMap`, and avoid using `&str` as key to make examples easier. " +"Using references in collections can, of course, be done,\n" +" but it can lead into complications with the borrow checker.\n" +" * Try removing `to_string()` from the example above and see if it still compiles. Where do you " +"think we might run into issues?" +msgstr "" + #: src/std/box.md:1 #, fuzzy msgid "# `Box`" @@ -7804,24 +7312,17 @@ msgstr "" "`Box` implementiert `Deref`, was bedeutet, dass Sie [Methoden aufrufen können\n" "von `T` direkt auf eine `Box`][2]." -#: src/std/box.md:29 -#, fuzzy -msgid "" -"[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" -"[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion" -msgstr "" -"[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" -"[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion" - #: src/std/box.md:34 -#, fuzzy msgid "" -"* `Box` is like `std::unique_ptr` in C++.\n" +"* `Box` is like `std::unique_ptr` in C++, except that it's guaranteed to be not null. \n" "* In the above example, you can even leave out the `*` in the `println!` statement thanks to " -"`Deref`." +"`Deref`. \n" +"* A `Box` can be useful when you:\n" +" * have a type whose size that can't be known at compile time, but the Rust compiler wants to " +"know an exact size.\n" +" * want to transfer ownership of a large amount of data. To avoid copying large amounts of data " +"on the stack, instead store the data on the heap in a `Box` so only the pointer is moved." msgstr "" -"* `Box` ist wie `std::unique_ptr` in C++.\n" -"* Im obigen Beispiel können Sie dank `Deref` sogar das `*` in der `println!`-Anweisung weglassen." #: src/std/box-recursive.md:1 #, fuzzy @@ -7840,11 +7341,8 @@ msgid "" "enum List {\n" " Cons(T, Box>),\n" " Nil,\n" -"}" -msgstr "" - -#: src/std/box-recursive.md:12 src/std/box-niche.md:10 -msgid "" +"}\n" +"\n" "fn main() {\n" " let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));\n" " println!(\"{list:?}\");\n" @@ -7859,43 +7357,29 @@ msgid "" ".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" ": : : :\n" ": list : : :\n" -": +--------+-------+ : : +--------+--------+ +--------+------+ :\n" -": | Tag | Cons | : : .->| Tag | Cons | .->| Tag | Nil | :\n" -": | 0 | 1 | : : | | 0 | 2 | | | ////// | //// | :\n" -": | 1 | o-----+----+-----+-' | 1 | o------+-' | ////// | //// | :\n" -": +--------+-------+ : : +--------+--------+ +--------+------+ :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----+ :\n" +": | Cons | 1 | o--+----+-----+--->| Cons | 2 | o--+--->| Nil | // | // | :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----+ :\n" ": : : :\n" ": : : :\n" -"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" +"'- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" "```" msgstr "" #: src/std/box-recursive.md:33 -#, fuzzy msgid "" -"
\n" -" \n" -"If the `Box` was not used here and we attempted to embed a `List` directly into the `List`,\n" +"* If the `Box` was not used here and we attempted to embed a `List` directly into the `List`,\n" "the compiler would not compute a fixed size of the struct in memory, it would look infinite.\n" -" \n" -"`Box` solves this problem as it has the same size as a regular pointer and just points at the " +"\n" +"* `Box` solves this problem as it has the same size as a regular pointer and just points at the " "next\n" -"element of the `List` in the heap. \n" -" \n" -"
" +"element of the `List` in the heap.\n" +"\n" +"* Remove the `Box` in the List definition and show the compiler error. \"Recursive with " +"indirection\" is a hint you might want to use a Box or reference of some kind, instead of storing " +"a value directly. \n" +" " msgstr "" -"
\n" -" \n" -"Wenn die `Box` hier nicht verwendet wurde und wir versucht haben, eine `List` direkt in die `List` " -"einzubetten,\n" -"Der Compiler würde keine feste Größe der Struktur im Speicher berechnen, es würde unendlich " -"aussehen.\n" -" \n" -"`Box` löst dieses Problem, da es die gleiche Größe wie ein normaler Zeiger hat und nur auf den " -"nächsten zeigt\n" -"Element der `Liste` im Heap.\n" -" \n" -"
" #: src/std/box-niche.md:1 #, fuzzy @@ -7915,16 +7399,15 @@ msgstr "" msgid "" "```bob\n" " Stack Heap\n" -".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" -": : : :\n" -": list : : :\n" -": +--------+-------+ : : +--------+--------+ +--------+------+ :\n" -": | 0 | 1 | : : .->| 0 | 2 | .->| ////// | //// | :\n" -": | \"1/Tag\"| o-----+----+-----+-' | \"1/Tag\"| o-----+-' | \"1/Tag\"| null | :\n" -": +--------+-------+ : : +--------+--------+ +--------+------+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": list : : :\n" +": +----+----+ : : +----+----+ +----+------+ :\n" +": | 1 | o--+-----------+-----+--->| 2 | o--+--->| // | null | :\n" +": +----+----+ : : +----+----+ +----+------+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - -'\n" "```" msgstr "" @@ -7946,52 +7429,80 @@ msgstr "" #: src/std/rc.md:6 msgid "" "```rust,editable\n" -"use std::rc::Rc;" -msgstr "" - -#: src/std/rc.md:9 -msgid "" +"use std::rc::Rc;\n" +"\n" "fn main() {\n" " let mut a = Rc::new(10);\n" -" let mut b = a.clone();" +" let mut b = a.clone();\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" msgstr "" #: src/std/rc.md:18 #, fuzzy msgid "" -"If you need to mutate the data inside an `Rc`, you will need to wrap the data in\n" -"a type such as [`Cell` or `RefCell`][2]. See [`Arc`][3] if you are in a multi-threaded\n" -"context." +"* If you need to mutate the data inside an `Rc`, you will need to wrap the data in\n" +" a type such as [`Cell` or `RefCell`][2].\n" +"* See [`Arc`][3] if you are in a multi-threaded context.\n" +"* You can *downgrade* a shared pointer into a [`Weak`][4] pointer to create cycles\n" +" that will get dropped." msgstr "" "Wenn Sie die Daten innerhalb eines „Rc“ mutieren müssen, müssen Sie die Daten einschließen\n" "ein Typ wie [`Cell` oder `RefCell`][2]. Siehe [`Arc`][3], wenn Sie sich in einem Multithreading " "befinden\n" "Kontext." -#: src/std/rc.md:22 -#, fuzzy +#: src/std/rc.md:31 msgid "" -"[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" -"[2]: https://doc.rust-lang.org/std/cell/index.html\n" -"[3]: ../concurrency/shared_state/arc.md" +"* `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" +"* `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" +" create cycles that will be dropped properly (likely in combination with\n" +" `RefCell`)." msgstr "" -"[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" -"[2]: https://doc.rust-lang.org/std/cell/index.html\n" -"[3]: ../concurrency/shared_state/arc.md" -#: src/std/rc.md:28 -#, fuzzy +#: src/std/rc.md:41 msgid "" -"* Like C++'s `std::shared_ptr`.\n" -"* `clone` is cheap: creates a pointer to the same allocation and increases the reference count.\n" -"* `make_mut` actually clones the inner value if necessary (\"clone-on-write\") and returns a " -"mutable reference." +"```rust,editable\n" +"use std::rc::{Rc, Weak};\n" +"use std::cell::RefCell;\n" +"\n" +"#[derive(Debug)]\n" +"struct Node {\n" +" value: i64,\n" +" parent: Option>>,\n" +" children: Vec>>,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut root = Rc::new(RefCell::new(Node {\n" +" value: 42,\n" +" parent: None,\n" +" children: vec![],\n" +" }));\n" +" let child = Rc::new(RefCell::new(Node {\n" +" value: 43,\n" +" children: vec![],\n" +" parent: Some(Rc::downgrade(&root))\n" +" }));\n" +" root.borrow_mut().children.push(child);\n" +"\n" +" println!(\"graph: {root:#?}\");\n" +"}\n" +"```" msgstr "" -"* Wie `std::shared_ptr` von C++.\n" -"* `clone` ist billig: erstellt einen Zeiger auf die gleiche Zuweisung und erhöht die " -"Referenzanzahl.\n" -"* `make_mut` klont bei Bedarf tatsächlich den inneren Wert (\"clone-on-write\") und gibt eine " -"veränderliche Referenz zurück." #: src/modules.md:1 #, fuzzy @@ -8015,20 +7526,14 @@ msgid "" " pub fn do_something() {\n" " println!(\"In the foo module\");\n" " }\n" -"}" -msgstr "" - -#: src/modules.md:14 -msgid "" +"}\n" +"\n" "mod bar {\n" " pub fn do_something() {\n" " println!(\"In the bar module\");\n" " }\n" -"}" -msgstr "" - -#: src/modules.md:20 -msgid "" +"}\n" +"\n" "fn main() {\n" " foo::do_something();\n" " bar::do_something();\n" @@ -8036,6 +7541,15 @@ msgid "" "```" msgstr "" +#: src/modules.md:28 +msgid "" +"* Packages provide functionality and include a `Cargo.toml` file that describes how to build a " +"bundle of 1+ crates.\n" +"* Crates are a tree of modules, where a binary crate creates an executable and a library crate " +"compiles to a library.\n" +"* Modules define organization, scope, and are the focus of this section." +msgstr "" + #: src/modules/visibility.md:1 #, fuzzy msgid "# Visibility" @@ -8050,53 +7564,61 @@ msgstr "Module sind eine Datenschutzgrenze:" #, fuzzy msgid "" "* Module items are private by default (hides implementation details).\n" -"* Parent and sibling items are always visible." +"* Parent and sibling items are always visible.\n" +"* In other words, if an item is visible in module `foo`, it's visible in all the\n" +" descendants of `foo`." msgstr "" "* Modulelemente sind standardmäßig privat (versteckt Implementierungsdetails).\n" "* Übergeordnete und gleichgeordnete Elemente sind immer sichtbar." -#: src/modules/visibility.md:8 +#: src/modules/visibility.md:10 msgid "" "```rust,editable\n" "mod outer {\n" " fn private() {\n" " println!(\"outer::private\");\n" -" }" -msgstr "" - -#: src/modules/visibility.md:14 -msgid "" +" }\n" +"\n" " pub fn public() {\n" " println!(\"outer::public\");\n" -" }" -msgstr "" - -#: src/modules/visibility.md:18 -msgid "" +" }\n" +"\n" " mod inner {\n" " fn private() {\n" " println!(\"outer::inner::private\");\n" -" }" -msgstr "" - -#: src/modules/visibility.md:23 -msgid "" +" }\n" +"\n" " pub fn public() {\n" " println!(\"outer::inner::public\");\n" " super::private();\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/modules/visibility.md:30 -msgid "" +"}\n" +"\n" "fn main() {\n" " outer::public();\n" "}\n" "```" msgstr "" +#: src/modules/visibility.md:39 +msgid "* Use the `pub` keyword to make modules public." +msgstr "" + +#: src/modules/visibility.md:41 +msgid "" +"Additionally, there are advanced `pub(...)` specifiers to restrict the scope of public visibility." +msgstr "" + +#: src/modules/visibility.md:43 +msgid "" +"* See the [Rust Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-" +"path-pubcrate-pubsuper-and-pubself).\n" +"* Configuring `pub(crate)` visibility is a common pattern.\n" +"* Less commonly, you can give visibility to a specific path.\n" +"* In any case, visibility must be granted to an ancestor module (and all of its descendants)." +msgstr "" + #: src/modules/paths.md:1 #, fuzzy msgid "# Paths" @@ -8112,15 +7634,8 @@ msgstr "Pfade werden wie folgt aufgelöst:" msgid "" "1. As a relative path:\n" " * `foo` or `self::foo` refers to `foo` in the current module,\n" -" * `super::foo` refers to `foo` in the parent module." -msgstr "" -"1. Als relativer Pfad:\n" -" * `foo` oder `self::foo` bezieht sich auf `foo` im aktuellen Modul,\n" -" * „super::foo“ bezieht sich auf „foo“ im übergeordneten Modul." - -#: src/modules/paths.md:9 -#, fuzzy -msgid "" +" * `super::foo` refers to `foo` in the parent module.\n" +"\n" "2. As an absolute path:\n" " * `crate::foo` refers to `foo` in the root of the current crate,\n" " * `bar::foo` refers to `foo` in the `bar` crate." @@ -8188,6 +7703,57 @@ msgstr "" "* `src/lib.rs` (für eine Bibliothekskiste)\n" "* `src/main.rs` (für eine Binärkiste)" +#: src/modules/filesystem.md:24 +msgid "" +"Modules defined in files can be documented, too, using \"inner doc comments\".\n" +"These document the item that contains them -- in this case, a module." +msgstr "" + +#: src/modules/filesystem.md:27 +msgid "" +"```rust,editable,compile_fail\n" +"//! 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" +"\n" +"// Harvest the produce in the garden that is ready.\n" +"fn harvest(garden: &mut Garden) { todo!() }\n" +"```" +msgstr "" + +#: src/modules/filesystem.md:40 +msgid "" +"* The change from `module/mod.rs` to `module.rs` doesn't preclude the use of submodules in Rust " +"2018.\n" +" (It was mandatory in Rust 2015.)\n" +"\n" +" The following is valid:\n" +"\n" +" ```ignore\n" +" src/\n" +" ├── main.rs\n" +" ├── top_module.rs\n" +" └── top_module/\n" +" └── sub_module.rs\n" +" ```\n" +"\n" +"* The main reason for the change is to prevent many files named `mod.rs`, which can be hard\n" +" to distinguish in IDEs.\n" +"\n" +"* Rust will look for modules in `modulename/mod.rs` and `modulename.rs`, but this can be changed\n" +" with a compiler directive:\n" +"\n" +" ```rust,ignore\n" +" #[path = \"some/path.rs\"]\n" +" mod some_module { }\n" +" ```\n" +"\n" +" This is useful, for example, if you would like to place tests for a module in a file named\n" +" `some_module_test.rs`, similar to the convention in Go." +msgstr "" + #: src/exercises/day-2/afternoon.md:1 #, fuzzy msgid "# Day 2: Afternoon Exercises" @@ -8216,39 +7782,19 @@ msgstr "" "Folgendes, um die Kreditkartennummer zu validieren:" #: src/exercises/day-2/luhn.md:7 -#, fuzzy -msgid "* Ignore all spaces. Reject number with less than two digits." -msgstr "* Ignoriere alle Leerzeichen. Ablehnungsnummer mit weniger als zwei Ziffern." - -#: src/exercises/day-2/luhn.md:9 -#, fuzzy msgid "" +"* Ignore all spaces. Reject number with less than two digits.\n" +"\n" "* Moving from right to left, double every second digit: for the number `1234`,\n" -" we double `3` and `1`." -msgstr "" -"* Bewegen Sie sich von rechts nach links, verdoppeln Sie jede zweite Ziffer: für die Zahl " -"\"1234\",\n" -" wir verdoppeln `3` und `1`." - -#: src/exercises/day-2/luhn.md:12 -#, fuzzy -msgid "" +" we double `3` and `1`.\n" +"\n" "* After doubling a digit, sum the digits. So doubling `7` becomes `14` which\n" -" becomes `5`." +" becomes `5`.\n" +"\n" +"* Sum all the undoubled and doubled digits.\n" +"\n" +"* The credit card number is valid if the sum ends with `0`." msgstr "" -"* Nachdem Sie eine Ziffer verdoppelt haben, addieren Sie die Ziffern. Das Verdoppeln von '7' wird " -"also zu '14', was\n" -" wird \"5\"." - -#: src/exercises/day-2/luhn.md:15 -#, fuzzy -msgid "* Sum all the undoubled and doubled digits." -msgstr "* Summiere alle unverdoppelten und verdoppelten Ziffern." - -#: src/exercises/day-2/luhn.md:17 -#, fuzzy -msgid "* The credit card number is valid if the sum ends with `0`." -msgstr "* Die Kreditkartennummer ist gültig, wenn die Summe mit `0` endet." #: src/exercises/day-2/luhn.md:19 #, fuzzy @@ -8259,70 +7805,56 @@ msgstr "" "Kopieren Sie den folgenden Code nach und implementieren Sie die\n" "Funktion:" -#: src/exercises/day-2/luhn.md:27 -#, fuzzy +#: src/exercises/day-2/luhn.md:23 msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" "pub fn luhn(cc_number: &str) -> bool {\n" " unimplemented!()\n" -"}" -msgstr "" -"pub fn luhn(cc_number: &str) -> bool {\n" -" nicht implementiert!()\n" -"}" - -#: src/exercises/day-2/luhn.md:31 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_non_digit_cc_number() {\n" " assert!(!luhn(\"foo\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:36 src/exercises/day-2/solutions-afternoon.md:64 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_empty_cc_number() {\n" " assert!(!luhn(\"\"));\n" " assert!(!luhn(\" \"));\n" " assert!(!luhn(\" \"));\n" " assert!(!luhn(\" \"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:44 src/exercises/day-2/solutions-afternoon.md:72 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_single_digit_cc_number() {\n" " assert!(!luhn(\"0\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:49 src/exercises/day-2/solutions-afternoon.md:77 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_two_digit_cc_number() {\n" " assert!(luhn(\" 0 0 \"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:54 src/exercises/day-2/solutions-afternoon.md:82 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_valid_cc_number() {\n" " assert!(luhn(\"4263 9826 4026 9299\"));\n" " assert!(luhn(\"4539 3195 0343 6467\"));\n" " assert!(luhn(\"7992 7398 713\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:61 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_invalid_cc_number() {\n" " assert!(!luhn(\"4223 9826 4026 9299\"));\n" " assert!(!luhn(\"4539 3195 0343 6476\"));\n" " assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" msgstr "" #: src/exercises/day-2/strings-iterators.md:1 @@ -8352,36 +7884,27 @@ msgstr "" "Kopieren Sie den folgenden Code nach und führen Sie die Tests durch\n" "passieren. Versuchen Sie, Ihren Zwischenergebnissen kein „Vec“ zuzuweisen:" -#: src/exercises/day-2/strings-iterators.md:16 -#, fuzzy +#: src/exercises/day-2/strings-iterators.md:12 msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" "pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" " unimplemented!()\n" -"}" -msgstr "" -"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" -" nicht implementiert!()\n" -"}" - -#: src/exercises/day-2/strings-iterators.md:20 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_matches_without_wildcard() {\n" " assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" " assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" -msgstr "" - -#: src/exercises/day-2/strings-iterators.md:26 src/exercises/day-2/solutions-afternoon.md:146 -msgid "" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));\n" +"\n" " assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" " assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" " assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/strings-iterators.md:31 src/exercises/day-2/solutions-afternoon.md:151 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_matches_with_wildcard() {\n" " assert!(prefix_matches(\n" @@ -8395,11 +7918,8 @@ msgid "" " assert!(prefix_matches(\n" " \"/v1/publishers/*/books\",\n" " \"/v1/publishers/foo/books/book1\"\n" -" ));" -msgstr "" - -#: src/exercises/day-2/strings-iterators.md:46 -msgid "" +" ));\n" +"\n" " assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" " assert!(!prefix_matches(\n" " \"/v1/publishers/*/books\",\n" @@ -8420,41 +7940,173 @@ msgid "Today, we will cover some more advanced topics of Rust:" msgstr "Heute werden wir einige fortgeschrittenere Themen von Rust behandeln:" #: src/welcome-day-3.md:5 -#, fuzzy msgid "" "* Traits: deriving traits, default methods, and important standard library\n" -" traits." +" traits.\n" +"\n" +"* Generics: generic data types, generic methods, monomorphization, and trait\n" +" objects.\n" +"\n" +"* Error handling: panics, `Result`, and the try operator `?`.\n" +"\n" +"* Testing: unit tests, documentation tests, and integration tests.\n" +"\n" +"* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" +" functions." msgstr "" -"* Merkmale: Ableitung von Merkmalen, Standardmethoden und wichtige Standardbibliothek\n" -" Züge." -#: src/welcome-day-3.md:8 +#: src/generics.md:1 +#, fuzzy +msgid "# Generics" +msgstr "# Generika" + +#: src/generics.md:3 #, fuzzy msgid "" -"* Generics: generic data types, generic methods, monomorphization, and trait\n" -" objects." +"Rust support generics, which lets you abstract an algorithm (such as sorting)\n" +"over the types used in the algorithm." +msgstr "" +"Rust unterstützt Generika, mit denen Sie einen Algorithmus abstrahieren können (z. B. Sortieren)\n" +"über die im Algorithmus verwendeten Typen." + +#: src/generics/data-types.md:1 +#, fuzzy +msgid "# Generic Data Types" +msgstr "# Generische Datentypen" + +#: src/generics/data-types.md:3 +#, fuzzy +msgid "You can use generics to abstract over the concrete field type:" +msgstr "Mit Generika können Sie über den konkreten Feldtyp abstrahieren:" + +#: src/generics/data-types.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point {\n" +" x: T,\n" +" y: T,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Point { x: 5, y: 10 };\n" +" let float = Point { x: 1.0, y: 4.0 };\n" +" println!(\"{integer:?} and {float:?}\");\n" +"}\n" +"```" msgstr "" -"* Generics: generische Datentypen, generische Methoden, Monomorphisierung und Eigenschaften\n" -" Objekte." -#: src/welcome-day-3.md:11 +#: src/generics/data-types.md:21 +msgid "" +"* Try declaring a new variable `let p = Point { x: 5, y: 10.0 };`.\n" +"\n" +"* Fix the code to allow points that have elements of different types." +msgstr "" + +#: src/generics/methods.md:1 #, fuzzy -msgid "* Error handling: panics, `Result`, and the try operator `?`." -msgstr "* Fehlerbehandlung: Panics, `Result` und der Try-Operator `?`." +msgid "# Generic Methods" +msgstr "# Generische Methoden" -#: src/welcome-day-3.md:13 +#: src/generics/methods.md:3 #, fuzzy -msgid "* Testing: unit tests, documentation tests, and integration tests." -msgstr "* Testen: Einheitentests, Dokumentationstests und Integrationstests." +msgid "You can declare a generic type on your `impl` block:" +msgstr "Sie können einen generischen Typ in Ihrem `impl`-Block deklarieren:" + +#: src/generics/methods.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(T, T);\n" +"\n" +"impl Point {\n" +" fn x(&self) -> &T {\n" +" &self.0 // + 10\n" +" }\n" +"\n" +" // fn set_x(&mut self, x: T)\n" +"}\n" +"\n" +"fn main() {\n" +" let p = Point(5, 10);\n" +" println!(\"p.x = {}\", p.x());\n" +"}\n" +"```" +msgstr "" -#: src/welcome-day-3.md:15 +#: src/generics/methods.md:25 #, fuzzy msgid "" -"* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" -" functions." +"* *Q:* Why `T` is specified twice in `impl Point {}`? Isn't that redundant?\n" +" * This is because it is a generic implementation section for generic type. They are " +"independently generic.\n" +" * It means these methods are defined for any `T`.\n" +" * It is possible to write `impl Point { .. }`. \n" +" * `Point` is still generic and you can use `Point`, but methods in this block will only " +"be available for `Point`." msgstr "" -"* Unsicherer Rost: rohe Zeiger, statische Variablen, unsichere Funktionen und extern\n" -" Funktionen." +"* *F:* Warum wird `T` zweimal in `impl Point {}` angegeben? Ist das nicht überflüssig?\n" +" * Dies liegt daran, dass es sich um einen generischen Implementierungsabschnitt für einen " +"generischen Typ handelt. Sie sind unabhängig generisch.\n" +" * Dies bedeutet, dass diese Methoden für jedes `T` definiert sind.\n" +" * Es ist möglich `impl Point { .. }` zu schreiben.\n" +" * „Point“ ist immer noch generisch und Sie können „Point“ verwenden, aber Methoden in " +"diesem Block sind nur für „Point“ verfügbar." + +#: src/generics/monomorphization.md:1 +#, fuzzy +msgid "# Monomorphization" +msgstr "# Monomorphisierung" + +#: src/generics/monomorphization.md:3 +#, fuzzy +msgid "Generic code is turned into non-generic code based on the call sites:" +msgstr "Basierend auf den Aufrufseiten wird generischer Code in nicht generischen Code umgewandelt:" + +#: src/generics/monomorphization.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let integer = Some(5);\n" +" let float = Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:12 +#, fuzzy +msgid "behaves as if you wrote" +msgstr "verhält sich so, als hättest du geschrieben" + +#: src/generics/monomorphization.md:14 +msgid "" +"```rust,editable\n" +"enum Option_i32 {\n" +" Some(i32),\n" +" None,\n" +"}\n" +"\n" +"enum Option_f64 {\n" +" Some(f64),\n" +" None,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Option_i32::Some(5);\n" +" let float = Option_f64::Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:31 +#, fuzzy +msgid "" +"This is a zero-cost abstraction: you get exactly the same result as if you had\n" +"hand-coded the data structures without the abstraction." +msgstr "" +"Dies ist eine Null-Kosten-Abstraktion: Sie erhalten genau das gleiche Ergebnis, als ob Sie es " +"hätten\n" +"die Datenstrukturen ohne die Abstraktion von Hand codiert." #: src/traits.md:1 #, fuzzy @@ -8469,70 +8121,140 @@ msgstr "Mit Rust können Sie über Typen mit Merkmalen abstrahieren. Sie ähneln #: src/traits.md:5 msgid "" "```rust,editable\n" -"trait Greet {\n" -" fn say_hello(&self);\n" -"}" -msgstr "" - -#: src/traits.md:10 -#, fuzzy -msgid "" +"trait Pet {\n" +" fn name(&self) -> String;\n" +"}\n" +"\n" "struct Dog {\n" " name: String,\n" -"}" +"}\n" +"\n" +"struct Cat;\n" +"\n" +"impl Pet for Dog {\n" +" fn name(&self) -> String {\n" +" self.name.clone()\n" +" }\n" +"}\n" +"\n" +"impl Pet for Cat {\n" +" fn name(&self) -> String {\n" +" String::from(\"The cat\") // No name, cats won't respond to it anyway.\n" +" }\n" +"}\n" +"\n" +"fn greet(pet: &P) {\n" +" println!(\"Who's a cutie? {} is!\", pet.name());\n" +"}\n" +"\n" +"fn main() {\n" +" let fido = Dog { name: \"Fido\".into() };\n" +" greet(&fido);\n" +"\n" +" let captain_floof = Cat;\n" +" greet(&captain_floof);\n" +"}\n" +"```" msgstr "" -"struct Hund {\n" -" Name: Zeichenfolge,\n" -"}" -#: src/traits.md:14 -msgid "struct Cat; // No name, cats won't respond to it anyway." -msgstr "" +#: src/traits/trait-objects.md:1 +#, fuzzy +msgid "# Trait Objects" +msgstr "# Eigenschaftsobjekte" -#: src/traits.md:16 -msgid "" -"impl Greet for Dog {\n" -" fn say_hello(&self) {\n" -" println!(\"Wuf, my name is {}!\", self.name);\n" -" }\n" -"}" +#: src/traits/trait-objects.md:3 +msgid "Trait objects allow for values of different types, for instance in a collection:" msgstr "" -#: src/traits.md:22 +#: src/traits/trait-objects.md:5 msgid "" -"impl Greet for Cat {\n" -" fn say_hello(&self) {\n" -" println!(\"Miau!\");\n" +"```rust\n" +"trait Pet {\n" +" fn name(&self) -> String;\n" +"}\n" +"\n" +"struct Dog {\n" +" name: String,\n" +"}\n" +"\n" +"struct Cat;\n" +"\n" +"impl Pet for Dog {\n" +" fn name(&self) -> String {\n" +" self.name.clone()\n" " }\n" -"}" -msgstr "" - -#: src/traits.md:28 -msgid "" +"}\n" +"\n" +"impl Pet for Cat {\n" +" fn name(&self) -> String {\n" +" String::from(\"The cat\") // No name, cats won't respond to it anyway.\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let pets: Vec> = vec![\n" +" let pets: Vec> = vec![\n" " Box::new(Dog { name: String::from(\"Fido\") }),\n" " Box::new(Cat),\n" " ];\n" " for pet in pets {\n" -" pet.say_hello();\n" +" println!(\"Hello {}!\", pet.name());\n" " }\n" "}\n" "```" msgstr "" -#: src/traits.md:41 +#: src/traits/trait-objects.md:40 +#, fuzzy +msgid "Memory layout after allocating `pets`:" +msgstr "Speicherlayout nach Zuweisung von `xs`:" + +#: src/traits/trait-objects.md:42 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": pets : : :\n" +": +-----------+-------+ : : +-----+-----+ :\n" +": | ptr | o---+---+-----+-->| o o | o o | :\n" +": | len | 2 | : : +-|-|-+-|-|-+ :\n" +": | capacity | 2 | : : | | | | +---------------+ :\n" +": +-----------+-------+ : : | | | '-->| name: \"Fido\" | :\n" +": : : | | | +---------------+ :\n" +"`- - - - - - - - - - - - - -' : | | | :\n" +" : | | | +----------------------+ : \n" +" : | | '---->| \"::name\" | :\n" +" : | | +----------------------+ : \n" +" : | | : \n" +" : | | +-+ : \n" +" : | '-->|\\| : \n" +" : | +-+ : \n" +" : | : \n" +" : | +----------------------+ : \n" +" : '---->| \"::name\" | : \n" +" : +----------------------+ :\n" +" : :\n" +" '- - - - - - - - - - - - - - - - - - - - - - -'\n" +"\n" +"```" +msgstr "" + +#: src/traits/trait-objects.md:72 #, fuzzy msgid "" -"* Traits may specify pre-implemented (default) methods and methods that users are required to " -"implement themselves. Methods with default implementations can rely on required methods.\n" "* Types that implement a given trait may be of different sizes. This makes it impossible to have " -"things like `Vec` in the example above.\n" -"* `dyn Greet` is a way to tell the compiler about a dynamically sized type that implements " -"`Greet`.\n" -"* In the example, `pets` holds Fat Pointers to objects that implement `Greet`. The Fat Pointer " +"things like `Vec` in the example above.\n" +"* `dyn Pet` is a way to tell the compiler about a dynamically sized type that implements `Pet`.\n" +"* In the example, `pets` holds *fat pointers* to objects that implement `Pet`. The fat pointer " "consists of two components, a pointer to the actual object and a pointer to the virtual method " -"table for the `Greet` implementation of that particular object." +"table for the `Pet` implementation of that particular object.\n" +"* Compare these outputs in the above example:\n" +" ```rust,ignore\n" +" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::());\n" +" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n" +" println!(\"{}\", std::mem::size_of::<&dyn Pet>());\n" +" println!(\"{}\", std::mem::size_of::>());\n" +" ```" msgstr "" "* Merkmale können vorimplementierte (Standard-)Methoden und Methoden spezifizieren, die Benutzer " "selbst implementieren müssen. Methoden mit Standardimplementierungen können sich auf erforderliche " @@ -8545,17 +8267,6 @@ msgstr "" "besteht aus zwei Komponenten, einem Zeiger auf das tatsächliche Objekt und einem Zeiger auf die " "virtuelle Methodentabelle für die \"Greet\"-Implementierung dieses bestimmten Objekts." -#: src/traits.md:46 -msgid "" -"Compare these outputs in the above example:\n" -"```rust,ignore\n" -" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::());\n" -" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n" -" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n" -" println!(\"{}\", std::mem::size_of::>());\n" -"```" -msgstr "" - #: src/traits/deriving-traits.md:1 #, fuzzy msgid "# Deriving Traits" @@ -8574,11 +8285,8 @@ msgid "" " name: String,\n" " strength: u8,\n" " hit_points: u8,\n" -"}" -msgstr "" - -#: src/traits/deriving-traits.md:13 -msgid "" +"}\n" +"\n" "fn main() {\n" " let p1 = Player::default();\n" " let p2 = p1.clone();\n" @@ -8606,32 +8314,17 @@ msgid "" " fn not_equal(&self, other: &Self) -> bool {\n" " !self.equal(other)\n" " }\n" -"}" -msgstr "" - -#: src/traits/default-methods.md:13 -msgid "" +"}\n" +"\n" "#[derive(Debug)]\n" -"struct Centimeter(i16);" -msgstr "" - -#: src/traits/default-methods.md:16 -#, fuzzy -msgid "" +"struct Centimeter(i16);\n" +"\n" "impl Equals for Centimeter {\n" " fn equal(&self, other: &Centimeter) -> bool {\n" " self.0 == other.0\n" " }\n" -"}" -msgstr "" -"impl Gleich für Zentimeter {\n" -" fn gleich(&selbst, andere: &Zentimeter) -> bool {\n" -" self.0 == andere.0\n" -" }\n" -"}" - -#: src/traits/default-methods.md:22 -msgid "" +"}\n" +"\n" "fn main() {\n" " let a = Centimeter(10);\n" " let b = Centimeter(20);\n" @@ -8641,6 +8334,188 @@ msgid "" "```" msgstr "" +#: src/traits/default-methods.md:32 +msgid "" +"* Traits may specify pre-implemented (default) methods and methods that users are required to\n" +" implement themselves. Methods with default implementations can rely on required methods.\n" +"\n" +"* Move method `not_equal` to a new trait `NotEqual`.\n" +"\n" +"* Make `NotEqual` a super trait for `Equal`.\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`." +msgstr "" + +#: src/traits/trait-bounds.md:1 +#, fuzzy +msgid "# Trait Bounds" +msgstr "# Eigenschaftsgrenzen" + +#: src/traits/trait-bounds.md:3 +#, fuzzy +msgid "" +"When working with generics, you often want to require the types to implement\n" +"some trait, so that you can call this trait's methods." +msgstr "" +"Wenn Sie mit Generika arbeiten, möchten Sie häufig die Typen einschränken. Du kannst das\n" +"mit `T:Trait` oder `impl Trait`:" + +#: src/traits/trait-bounds.md:6 +msgid "You can do this with `T: Trait` or `impl Trait`:" +msgstr "" + +#: src/traits/trait-bounds.md:8 +msgid "" +"```rust,editable\n" +"fn duplicate(a: T) -> (T, T) {\n" +" (a.clone(), a.clone())\n" +"}\n" +"\n" +"// Syntactic sugar for:\n" +"// fn add_42_millions>(x: T) -> i32 {\n" +"fn add_42_millions(x: impl Into) -> i32 {\n" +" x.into() + 42_000_000\n" +"}\n" +"\n" +"// struct NotClonable;\n" +"\n" +"fn main() {\n" +" let foo = String::from(\"foo\");\n" +" let pair = duplicate(foo);\n" +" println!(\"{pair:?}\");\n" +"\n" +" let many = add_42_millions(42_i8);\n" +" println!(\"{many}\");\n" +" let many_more = add_42_millions(10_000_000);\n" +" println!(\"{many_more}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-bounds.md:35 +msgid "Show a `where` clause, students will encounter it when reading code." +msgstr "" + +#: src/traits/trait-bounds.md:37 +msgid "" +"```rust,ignore\n" +"fn duplicate(a: T) -> (T, T)\n" +"where\n" +" T: Clone,\n" +"{\n" +" (a.clone(), a.clone())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-bounds.md:46 +#, fuzzy +msgid "" +"* It declutters the function signature if you have many parameters.\n" +"* It has additional features making it more powerful.\n" +" * If someone asks, the extra feature is that the type on the left of \":\" can be arbitrary, " +"like `Option`.\n" +" " +msgstr "" +"* Es entrümpelt die Funktionssignatur, wenn Sie viele Parameter haben.\n" +"* Es hat zusätzliche Funktionen, die es leistungsfähiger machen.\n" +" * Wenn jemand fragt, das zusätzliche Feature ist, dass der Typ links von \":\" beliebig sein " +"kann, wie `Option`.\n" +" \n" +"
" + +#: src/traits/impl-trait.md:1 +#, fuzzy +msgid "# `impl Trait`" +msgstr "# `imple Merkmal`" + +#: src/traits/impl-trait.md:3 +#, fuzzy +msgid "" +"Similar to trait bounds, an `impl Trait` syntax can be used in function\n" +"arguments and return values:" +msgstr "" +"Ähnlich wie Merkmalsgrenzen kann eine \"impl Trait\"-Syntax in Funktion verwendet werden\n" +"Argumente und Rückgabewerte:" + +#: src/traits/impl-trait.md:6 +msgid "" +"```rust,editable\n" +"use std::fmt::Display;\n" +"\n" +"fn get_x(name: impl Display) -> impl Display {\n" +" format!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let x = get_x(\"foo\");\n" +" println!(\"{x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/impl-trait.md:19 +#, fuzzy +msgid "* `impl Trait` allows you to work with types which you cannot name." +msgstr "" +"* `impl Trait` kann nicht mit der `::<>` Turbofish-Syntax verwendet werden.\n" +"* `impl Trait` ermöglicht es Ihnen, mit Typen zu arbeiten, die Sie nicht benennen können." + +#: src/traits/impl-trait.md:23 +#, fuzzy +msgid "The meaning of `impl Trait` is a bit different in the different positions." +msgstr "Die Bedeutung von „impl Trait“ ist in den verschiedenen Positionen etwas unterschiedlich." + +#: src/traits/impl-trait.md:25 +#, fuzzy +msgid "" +"* For a parameter, `impl Trait` is like an anonymous generic parameter with a trait bound.\n" +"\n" +"* For a return type, it means that the return type is some concrete type that implements the " +"trait,\n" +" without naming the type. This can be useful when you don't want to expose the concrete type in " +"a\n" +" public API.\n" +"\n" +" Inference is hard in return position. A function returning `impl Foo` picks\n" +" the concrete type it returns, without writing it out in the source. A function\n" +" returning a generic type like `collect() -> B` can return any type\n" +" satisfying `B`, and the caller may need to choose one, such as with `let x:\n" +" Vec<_> = foo.collect()` or with the turbofish, `foo.collect::>()`." +msgstr "" +"* Für einen Parameter ist `impl Trait` wie ein anonymer generischer Parameter mit einer " +"Eigenschaftsbindung.\n" +"* Für einen Rückgabetyp bedeutet dies, dass der Rückgabetyp ein konkreter Typ ist, der die " +"Eigenschaft implementiert,\n" +" ohne den Typ zu nennen. Dies kann nützlich sein, wenn Sie den konkreten Typ in a nicht verfügbar " +"machen möchten\n" +" öffentliche API." + +#: src/traits/impl-trait.md:37 +#, fuzzy +msgid "" +"This example is great, because it uses `impl Display` twice. It helps to explain that\n" +"nothing here enforces that it is _the same_ `impl Display` type. If we used a single \n" +"`T: Display`, it would enforce the constraint that input `T` and return `T` type are the same " +"type.\n" +"It would not work for this particular function, as the type we expect as input is likely not\n" +"what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two\n" +"independent generic parameters." +msgstr "" +"Dieses Beispiel ist großartig, weil es `impl Display` zweimal verwendet. Es hilft, das zu " +"erklären\n" +"nichts hier erzwingt, dass es _derselbe_ `impl Display`-Typ ist. Wenn wir eine Single benutzten\n" +"`T: Display`, es würde die Einschränkung erzwingen, dass der Eingabe-`T`- und der Rückgabe-`T-Typ " +"derselbe Typ sind.\n" +"Es würde für diese spezielle Funktion nicht funktionieren, da der Typ, den wir als Eingabe " +"erwarten, wahrscheinlich nicht der Fall ist\n" +"welches `format!` zurückgibt. Wenn wir dasselbe über die `: Display`-Syntax machen wollten, " +"bräuchten wir zwei\n" +"unabhängige generische Parameter.\n" +" \n" +"
" + #: src/traits/important-traits.md:1 #, fuzzy msgid "# Important Traits" @@ -8654,11 +8529,12 @@ msgstr "Wir werden uns nun einige der häufigsten Merkmale der Rust-Standardbibl #: src/traits/important-traits.md:5 #, fuzzy msgid "" -"* `Iterator` and `IntoIterator` used in `for` loops,\n" -"* `From` and `Into` used to convert values,\n" -"* `Read` and `Write` used for IO,\n" -"* `Add`, `Mul`, ... used for operator overloading, and\n" -"* `Drop` used for defining destructors." +"* [`Iterator`][1] and [`IntoIterator`][2] used in `for` loops,\n" +"* [`From`][3] and [`Into`][4] used to convert values,\n" +"* [`Read`][5] and [`Write`][6] used for IO,\n" +"* [`Add`][7], [`Mul`][8], ... used for operator overloading, and\n" +"* [`Drop`][9] used for defining destructors.\n" +"* [`Default`][10] used to construct a default instance of a type." msgstr "" "* `Iterator` und `IntoIterator` werden in `for`-Schleifen verwendet,\n" "* `From` und `Into` werden verwendet, um Werte zu konvertieren,\n" @@ -8673,7 +8549,7 @@ msgstr "# Iteratoren" #: src/traits/iterator.md:3 #, fuzzy -msgid "You can implement the `Iterator` trait on your own types:" +msgid "You can implement the [`Iterator`][1] trait on your own types:" msgstr "Sie können das `Iterator`-Merkmal für Ihre eigenen Typen implementieren:" #: src/traits/iterator.md:5 @@ -8682,28 +8558,19 @@ msgid "" "struct Fibonacci {\n" " curr: u32,\n" " next: u32,\n" -"}" -msgstr "" - -#: src/traits/iterator.md:11 -msgid "" +"}\n" +"\n" "impl Iterator for Fibonacci {\n" -" type Item = u32;" -msgstr "" - -#: src/traits/iterator.md:14 -msgid "" +" type Item = u32;\n" +"\n" " fn next(&mut self) -> Option {\n" " let new_next = self.curr + self.next;\n" " self.curr = self.next;\n" " self.next = new_next;\n" " Some(self.curr)\n" " }\n" -"}" -msgstr "" - -#: src/traits/iterator.md:22 -msgid "" +"}\n" +"\n" "fn main() {\n" " let fib = Fibonacci { curr: 0, next: 1 };\n" " for (i, n) in fib.enumerate().take(5) {\n" @@ -8714,11 +8581,7 @@ msgid "" msgstr "" #: src/traits/iterator.md:32 -#, fuzzy msgid "" -"* `IntoIterator` is the trait that makes for loops work. It is implemented by collection types " -"such as\n" -" `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also implement it.\n" "* The `Iterator` trait implements many common functional programming operations over collections \n" " (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can find all the " "documentation\n" @@ -8726,19 +8589,13 @@ msgid "" "imperative\n" " implementations.\n" " \n" -"
" +"* `IntoIterator` is the trait that makes for loops work. It is implemented by collection types " +"such as\n" +" `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also implement it. This is " +"why\n" +" you can iterate over a vector with `for i in some_vec { .. }` but\n" +" `some_vec.next()` doesn't exist." msgstr "" -"* `IntoIterator` ist die Eigenschaft, die dafür sorgt, dass for-Schleifen funktionieren. Es wird " -"durch Sammlungstypen wie implementiert\n" -" `Vec` und Verweise darauf wie `&Vec` und `&[T]`. Ranges implementieren es auch.\n" -"* Die Eigenschaft „Iterator“ implementiert viele gängige funktionale Programmieroperationen über " -"Sammlungen\n" -" (z. B. `map`, `filter`, `reduce`, etc). Dies ist die Eigenschaft, in der Sie die gesamte " -"Dokumentation finden können\n" -" über sie. In Rust sollten diese Funktionen den Code so effizient wie gleichwertig erzeugen\n" -" Implementierungen.\n" -" \n" -"
" #: src/traits/from-iterator.md:1 #, fuzzy @@ -8747,7 +8604,7 @@ msgstr "# FromIterator" #: src/traits/from-iterator.md:3 #, fuzzy -msgid "`FromIterator` lets you build a collection from an `Iterator`." +msgid "[`FromIterator`][1] lets you build a collection from an [`Iterator`][2]." msgstr "Mit „FromIterator“ können Sie eine Sammlung aus einem „Iterator“ erstellen." #: src/traits/from-iterator.md:5 @@ -8755,12 +8612,15 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let primes = vec![2, 3, 5, 7];\n" -" let prime_squares = primes.into_iter().map(|prime| prime * prime).collect::>();\n" +" let prime_squares = primes\n" +" .into_iter()\n" +" .map(|prime| prime * prime)\n" +" .collect::>();\n" "}\n" "```" msgstr "" -#: src/traits/from-iterator.md:14 +#: src/traits/from-iterator.md:17 #, fuzzy msgid "" "`Iterator` implements\n" @@ -8775,7 +8635,7 @@ msgstr "" " B: FromIterator,\n" " Selbst: Sized'" -#: src/traits/from-iterator.md:20 +#: src/traits/from-iterator.md:23 #, fuzzy msgid "" "There are also implementations which let you do cool things like convert an\n" @@ -8791,7 +8651,7 @@ msgstr "# `Von` und `Nach`" #: src/traits/from-into.md:3 #, fuzzy -msgid "Types implement `From` and `Into` to facilitate type conversions:" +msgid "Types implement [`From`][1] and [`Into`][2] to facilitate type conversions:" msgstr "Typen implementieren „From“ und „Into“, um Typkonvertierungen zu erleichtern:" #: src/traits/from-into.md:5 @@ -8809,7 +8669,7 @@ msgstr "" #: src/traits/from-into.md:15 #, fuzzy -msgid "`Into` is automatically implemented when `From` is implemented:" +msgid "[`Into`][2] is automatically implemented when [`From`][1] is implemented:" msgstr "„Into“ wird automatisch implementiert, wenn „From“ implementiert wird:" #: src/traits/from-into.md:17 @@ -8825,21 +8685,16 @@ msgid "" "```" msgstr "" -#: src/traits/from-into.md:27 +#: src/traits/from-into.md:29 #, fuzzy msgid "" -"
\n" -" \n" "* That's why it is common to only implement `From`, as your type will get `Into` implementation " "too.\n" "* When declaring a function argument input type like \"anything that can be converted into a " "`String`\", the rule is opposite, you should use `Into`.\n" " Your function will accept types that implement `From` and those that _only_ implement `Into`.\n" -" \n" -"
" +" " msgstr "" -"
\n" -" \n" "* Aus diesem Grund ist es üblich, nur `From` zu implementieren, da Ihr Typ auch die `Into`-" "Implementierung erhält.\n" "* Beim Deklarieren eines Funktionsargument-Eingabetyps wie „alles, was in einen „String“ " @@ -8856,32 +8711,23 @@ msgstr "# `Lesen` und `Schreiben`" #: src/traits/read-write.md:3 #, fuzzy -msgid "Using `Read` and `BufRead`, you can abstract over `u8` sources:" +msgid "Using [`Read`][1] and [`BufRead`][2], you can abstract over `u8` sources:" msgstr "Mit `Read` und `BufRead` können Sie über `u8`-Quellen abstrahieren:" #: src/traits/read-write.md:5 msgid "" "```rust,editable\n" -"use std::io::{BufRead, BufReader, Read, Result};" -msgstr "" - -#: src/traits/read-write.md:8 -msgid "" +"use std::io::{BufRead, BufReader, Read, Result};\n" +"\n" "fn count_lines(reader: R) -> usize {\n" " let buf_reader = BufReader::new(reader);\n" " buf_reader.lines().count()\n" -"}" -msgstr "" - -#: src/traits/read-write.md:13 -msgid "" +"}\n" +"\n" "fn main() -> Result<()> {\n" " let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" -" println!(\"lines in slice: {}\", count_lines(slice));" -msgstr "" - -#: src/traits/read-write.md:17 -msgid "" +" println!(\"lines in slice: {}\", count_lines(slice));\n" +"\n" " let file = std::fs::File::open(std::env::current_exe()?)?;\n" " println!(\"lines in file: {}\", count_lines(file));\n" " Ok(())\n" @@ -8891,25 +8737,19 @@ msgstr "" #: src/traits/read-write.md:23 #, fuzzy -msgid "Similarly, `Write` lets you abstract over `u8` sinks:" +msgid "Similarly, [`Write`][3] lets you abstract over `u8` sinks:" msgstr "In ähnlicher Weise können Sie mit \"Write\" über \"u8\"-Senken abstrahieren:" #: src/traits/read-write.md:25 msgid "" "```rust,editable\n" -"use std::io::{Result, Write};" -msgstr "" - -#: src/traits/read-write.md:28 -msgid "" +"use std::io::{Result, Write};\n" +"\n" "fn log(writer: &mut W, msg: &str) -> Result<()> {\n" " writer.write_all(msg.as_bytes())?;\n" " writer.write_all(\"\\n\".as_bytes())\n" -"}" -msgstr "" - -#: src/traits/read-write.md:33 -msgid "" +"}\n" +"\n" "fn main() -> Result<()> {\n" " let mut buffer = Vec::new();\n" " log(&mut buffer, \"Hello\")?;\n" @@ -8920,81 +8760,6 @@ msgid "" "```" msgstr "" -#: src/traits/operators.md:1 -#, fuzzy -msgid "# `Add`, `Mul`, ..." -msgstr "# `Hinzufügen`, `Mul`, ..." - -#: src/traits/operators.md:3 -#, fuzzy -msgid "Operator overloading is implemented via traits in `std::ops`:" -msgstr "Das Überladen von Operatoren wird über Traits in `std::ops` implementiert:" - -#: src/traits/operators.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug, Copy, Clone)]\n" -"struct Point { x: i32, y: i32 }" -msgstr "" - -#: src/traits/operators.md:9 src/exercises/day-2/solutions-morning.md:46 -msgid "" -"impl std::ops::Add for Point {\n" -" type Output = Self;" -msgstr "" - -#: src/traits/operators.md:12 -#, fuzzy -msgid "" -" fn add(self, other: Self) -> Self {\n" -" Self {x: self.x + other.x, y: self.y + other.y}\n" -" }\n" -"}" -msgstr "" -" fn add(self, other: Self) -> Self {\n" -" Selbst {x: selbst.x + andere.x, y: selbst.y + andere.y}\n" -" }\n" -"}" - -#: src/traits/operators.md:17 -msgid "" -"fn main() {\n" -" let p1 = Point { x: 10, y: 20 };\n" -" let p2 = Point { x: 100, y: 200 };\n" -" println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" -"}\n" -"```" -msgstr "" - -#: src/traits/operators.md:26 src/traits/drop.md:34 -#, fuzzy -msgid "Discussion points:" -msgstr "Diskussionspunkte:" - -#: src/traits/operators.md:28 -#, fuzzy -msgid "" -"* You could implement `Add` for `&Point`. In which situations is that useful? \n" -" * Answer: `Add:add` consumes `self`. If type `T` for which you are\n" -" 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" -" associated types (like `Output`) are controlled by the implementor of a\n" -" trait." -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" -" Das Überladen des Operators ist nicht \"Kopieren\", Sie sollten das Überladen in Betracht " -"ziehen\n" -" auch der Operator für `&T`. Dies vermeidet unnötiges Klonen auf der\n" -" Website aufrufen.\n" -"* Warum ist `Output` ein assoziierter Typ? Könnte es ein Typparameter gemacht werden?\n" -" * Kurze Antwort: Typparameter werden vom Aufrufer gesteuert, aber\n" -" Zugehörige Typen (wie `Output`) werden vom Implementierer von a gesteuert\n" -" Merkmal." - #: src/traits/drop.md:1 #, fuzzy msgid "# The `Drop` Trait" @@ -9002,7 +8767,7 @@ msgstr "# Die `Drop`-Eigenschaft" #: src/traits/drop.md:3 #, fuzzy -msgid "Values which implement `Drop` can specify code to run when they go out of scope:" +msgid "Values which implement [`Drop`][1] can specify code to run when they go out of scope:" msgstr "" "Werte, die \"Drop\" implementieren, können Code angeben, der ausgeführt werden soll, wenn sie den " "Gültigkeitsbereich verlassen:" @@ -9012,20 +8777,14 @@ msgid "" "```rust,editable\n" "struct Droppable {\n" " name: &'static str,\n" -"}" -msgstr "" - -#: src/traits/drop.md:10 -msgid "" +"}\n" +"\n" "impl Drop for Droppable {\n" " fn drop(&mut self) {\n" " println!(\"Dropping {}\", self.name);\n" " }\n" -"}" -msgstr "" - -#: src/traits/drop.md:16 -msgid "" +"}\n" +"\n" "fn main() {\n" " let a = Droppable { name: \"a\" };\n" " {\n" @@ -9043,10 +8802,15 @@ msgid "" "```" msgstr "" -#: src/traits/drop.md:36 +#: src/traits/drop.md:34 src/traits/operators.md:26 #, fuzzy -msgid "" -"* Why does not `Drop::drop` take `self`?\n" +msgid "Discussion points:" +msgstr "Diskussionspunkte:" + +#: src/traits/drop.md:36 +#, fuzzy +msgid "" +"* Why doesn't `Drop::drop` take `self`?\n" " * Short-answer: If it did, `std::mem::drop` would be called at the end of\n" " the block, resulting in another call to `Drop::drop`, and a stack\n" " overflow!\n" @@ -9058,582 +8822,224 @@ msgstr "" " Überlauf!\n" "* Versuchen Sie, `drop(a)` durch `a.drop()` zu ersetzen." -#: src/generics.md:1 +#: src/traits/default.md:1 #, fuzzy -msgid "# Generics" -msgstr "# Generika" +msgid "# The `Default` Trait" +msgstr "# Die `Drop`-Eigenschaft" -#: src/generics.md:3 -#, fuzzy -msgid "" -"Rust support generics, which lets you abstract an algorithm (such as sorting)\n" -"over the types used in the algorithm." +#: src/traits/default.md:3 +msgid "[`Default`][1] trait provides a default implementation of a trait." msgstr "" -"Rust unterstützt Generika, mit denen Sie einen Algorithmus abstrahieren können (z. B. Sortieren)\n" -"über die im Algorithmus verwendeten Typen." - -#: src/generics/data-types.md:1 -#, fuzzy -msgid "# Generic Data Types" -msgstr "# Generische Datentypen" - -#: src/generics/data-types.md:3 -#, fuzzy -msgid "You can use generics to abstract over the concrete field type:" -msgstr "Mit Generika können Sie über den konkreten Feldtyp abstrahieren:" -#: src/generics/data-types.md:5 +#: src/traits/default.md:5 msgid "" "```rust,editable\n" +"#[derive(Debug, Default)]\n" +"struct Derived {\n" +" x: u32,\n" +" y: String,\n" +" z: Implemented,\n" +"}\n" +"\n" "#[derive(Debug)]\n" -"struct Point {\n" -" x: T,\n" -" y: T,\n" -"}" -msgstr "" - -#: src/generics/data-types.md:12 -msgid "" +"struct Implemented(String);\n" +"\n" +"impl Default for Implemented {\n" +" fn default() -> Self {\n" +" Self(\"John Smith\".into())\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let integer = Point { x: 5, y: 10 };\n" -" let float = Point { x: 1.0, y: 4.0 };\n" -" println!(\"{integer:?} and {float:?}\");\n" +" let default_struct: Derived = Default::default();\n" +" println!(\"{default_struct:#?}\");\n" +"\n" +" let almost_default_struct = Derived {\n" +" y: \"Y is set!\".into(),\n" +" ..Default::default()\n" +" };\n" +" println!(\"{almost_default_struct:#?}\");\n" +"\n" +" let nothing: Option = None;\n" +" println!(\"{:#?}\", nothing.unwrap_or_default());\n" "}\n" +"\n" "```" msgstr "" -#: src/generics/methods.md:1 -#, fuzzy -msgid "# Generic Methods" -msgstr "# Generische Methoden" - -#: src/generics/methods.md:3 -#, fuzzy -msgid "You can declare a generic type on your `impl` block:" -msgstr "Sie können einen generischen Typ in Ihrem `impl`-Block deklarieren:" - -#: src/generics/methods.md:5 +#: src/traits/default.md:40 msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(T, T);" +" * It can be implemented directly or it can be derived via `#[derive(Default)]`.\n" +" * Derived implementation will produce an instance where all fields are set to their default " +"values.\n" +" * This means all types in the struct must implement `Default` too.\n" +" * Standard Rust types often implement `Default` with reasonable values (e.g. `0`, `\"\"`, etc).\n" +" * The partial struct copy works nicely with default.\n" +" * Rust standard library is aware that types can implement `Default` and provides convenience " +"methods that use it." msgstr "" -#: src/generics/methods.md:9 +#: src/traits/operators.md:1 #, fuzzy -msgid "" -"impl Point {\n" -" fn x(&self) -> &T {\n" -" &self.0 // + 10\n" -" }" -msgstr "" -"imple Punkt {\n" -" fn x(&selbst) -> &T {\n" -" &self.0 // + 10\n" -" }" +msgid "# `Add`, `Mul`, ..." +msgstr "# `Hinzufügen`, `Mul`, ..." -#: src/generics/methods.md:14 +#: src/traits/operators.md:3 #, fuzzy -msgid "" -" // fn set_x(&mut self, x: T)\n" -"}" -msgstr "" -" // fn set_x(&mut selbst, x: T)\n" -"}" +msgid "Operator overloading is implemented via traits in [`std::ops`][1]:" +msgstr "Das Überladen von Operatoren wird über Traits in `std::ops` implementiert:" -#: src/generics/methods.md:17 +#: src/traits/operators.md:5 msgid "" +"```rust,editable\n" +"#[derive(Debug, Copy, Clone)]\n" +"struct Point { x: i32, y: i32 }\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self {\n" +" Self {x: self.x + other.x, y: self.y + other.y}\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let p = Point(5, 10);\n" -" println!(\"p.x = {}\", p.x());\n" +" let p1 = Point { x: 10, y: 20 };\n" +" let p2 = Point { x: 100, y: 200 };\n" +" println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" "}\n" "```" msgstr "" -#: src/generics/methods.md:25 +#: src/traits/operators.md:28 #, fuzzy msgid "" -"* *Q:* Why `T` is specified twice in `impl Point {}`? Isn't that redundant?\n" -" * This is because it is a generic implementation section for generic type. They are " -"independently generic.\n" -" * It means these methods are defined for any `T`.\n" -" * It is possible to write `impl Point { .. }`. \n" -" * `Point` is still generic and you can use `Point`, but methods in this block will only " -"be available for `Point`." +"* You could implement `Add` for `&Point`. In which situations is that useful? \n" +" * Answer: `Add:add` consumes `self`. If type `T` for which you are\n" +" 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" +" associated types (like `Output`) are controlled by the implementor of a\n" +" trait." msgstr "" -"* *F:* Warum wird `T` zweimal in `impl Point {}` angegeben? Ist das nicht überflüssig?\n" -" * Dies liegt daran, dass es sich um einen generischen Implementierungsabschnitt für einen " -"generischen Typ handelt. Sie sind unabhängig generisch.\n" -" * Dies bedeutet, dass diese Methoden für jedes `T` definiert sind.\n" -" * Es ist möglich `impl Point { .. }` zu schreiben.\n" -" * „Point“ ist immer noch generisch und Sie können „Point“ verwenden, aber Methoden in " -"diesem Block sind nur für „Point“ verfügbar." +"* 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" +" Das Überladen des Operators ist nicht \"Kopieren\", Sie sollten das Überladen in Betracht " +"ziehen\n" +" auch der Operator für `&T`. Dies vermeidet unnötiges Klonen auf der\n" +" Website aufrufen.\n" +"* Warum ist `Output` ein assoziierter Typ? Könnte es ein Typparameter gemacht werden?\n" +" * Kurze Antwort: Typparameter werden vom Aufrufer gesteuert, aber\n" +" Zugehörige Typen (wie `Output`) werden vom Implementierer von a gesteuert\n" +" Merkmal." -#: src/generics/trait-bounds.md:1 +#: src/traits/closures.md:1 #, fuzzy -msgid "# Trait Bounds" -msgstr "# Eigenschaftsgrenzen" +msgid "# Closures" +msgstr "# Schließungen" -#: src/generics/trait-bounds.md:3 +#: src/traits/closures.md:3 #, fuzzy msgid "" -"When working with generics, you often want to limit the types. You can do this\n" -"with `T: Trait` or `impl Trait`:" +"Closures or lambda expressions have types which cannot be named. However, they\n" +"implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:" msgstr "" -"Wenn Sie mit Generika arbeiten, möchten Sie häufig die Typen einschränken. Du kannst das\n" -"mit `T:Trait` oder `impl Trait`:" +"Closures oder Lambda-Ausdrücke haben Typen, die nicht benannt werden können. Allerdings sie\n" +"spezielles [`Fn`] implementieren (https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html) und\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) Eigenschaften:" -#: src/generics/trait-bounds.md:6 +#: src/traits/closures.md:8 msgid "" "```rust,editable\n" -"fn duplicate(a: T) -> (T, T) {\n" -" (a.clone(), a.clone())\n" -"}" -msgstr "" - -#: src/generics/trait-bounds.md:11 -msgid "// struct NotClonable;" -msgstr "" - -#: src/generics/trait-bounds.md:13 -msgid "" +"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" +" println!(\"Calling function on {input}\");\n" +" func(input)\n" +"}\n" +"\n" "fn main() {\n" -" let foo = String::from(\"foo\");\n" -" let pair = duplicate(foo);\n" -" println!(\"{pair:?}\");\n" +" let add_3 = |x| x + 3;\n" +" let mul_5 = |x| x * 5;\n" +"\n" +" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" +" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" "}\n" "```" msgstr "" -#: src/generics/trait-bounds.md:22 -msgid "" -"Show a `where` clause, students will encounter it when reading code.\n" -" \n" -"```rust,ignore\n" -"fn duplicate(a: T) -> (T, T)\n" -"where\n" -" T: Clone,\n" -"{\n" -" (a.clone(), a.clone())\n" -"}\n" -"```" +#: src/traits/closures.md:25 +#, fuzzy +msgid "If you have an `FnOnce`, you may only call it once. It might consume captured values." msgstr "" +"Wenn Sie ein `FnOnce` haben, können Sie es nur einmal aufrufen. Es kann erfasste Werte verbrauchen." -#: src/generics/trait-bounds.md:33 +#: src/traits/closures.md:27 #, fuzzy msgid "" -"* It declutters the function signature if you have many parameters.\n" -"* It has additional features making it more powerful.\n" -" * If someone asks, the extra feature is that the type on the left of \":\" can be arbitrary, " -"like `Option`.\n" -" \n" -"
" +"An `FnMut` might mutate captured values, so you can call it multiple times but not concurrently." msgstr "" -"* Es entrümpelt die Funktionssignatur, wenn Sie viele Parameter haben.\n" -"* Es hat zusätzliche Funktionen, die es leistungsfähiger machen.\n" -" * Wenn jemand fragt, das zusätzliche Feature ist, dass der Typ links von \":\" beliebig sein " -"kann, wie `Option`.\n" -" \n" -"
" - -#: src/generics/impl-trait.md:1 -#, fuzzy -msgid "# `impl Trait`" -msgstr "# `imple Merkmal`" +"Ein `FnMut` kann erfasste Werte mutieren, sodass Sie es mehrmals, aber nicht gleichzeitig aufrufen " +"können." -#: src/generics/impl-trait.md:3 +#: src/traits/closures.md:29 #, fuzzy msgid "" -"Similar to trait bounds, an `impl Trait` syntax can be used in function\n" -"arguments and return values:" +"An `Fn` neither consumes nor mutates captured values, or perhaps captures nothing at all, so it " +"can\n" +"be called multiple times concurrently." msgstr "" -"Ähnlich wie Merkmalsgrenzen kann eine \"impl Trait\"-Syntax in Funktion verwendet werden\n" -"Argumente und Rückgabewerte:" +"Ein „Fn“ verbraucht oder mutiert erfasste Werte nicht oder erfasst vielleicht gar nichts, also " +"kann es das\n" +"mehrmals gleichzeitig aufgerufen werden." -#: src/generics/impl-trait.md:6 src/generics/trait-objects.md:5 src/generics/trait-objects.md:28 +#: src/traits/closures.md:32 +#, fuzzy msgid "" -"```rust,editable\n" -"use std::fmt::Display;" +"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. I.e. you can use an\n" +"`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever an `FnMut` or " +"`FnOnce`\n" +"is called for." msgstr "" +"`FnMut` ist ein Untertyp von `FnOnce`. „Fn“ ist ein Untertyp von „FnMut“ und „FnOnce“. D.h. Sie " +"können eine verwenden\n" +"„FnMut“, wo immer ein „FnOnce“ verlangt wird, und Sie können ein „Fn“ überall dort verwenden, wo " +"ein „FnMut“ oder „FnOnce“ steht\n" +"ist angesagt." -#: src/generics/impl-trait.md:9 +#: src/traits/closures.md:36 #, fuzzy -msgid "" -"fn get_x(name: impl Display) -> impl Display {\n" -" format!(\"Hello {name}\")\n" -"}" -msgstr "" -"fn get_x(name: impl Display) -> impl Display {\n" -" format!(\"Hallo {Name}\")\n" -"}" +msgid "`move` closures only implement `FnOnce`." +msgstr "`move`-Closures implementieren nur `FnOnce`." -#: src/generics/impl-trait.md:13 -msgid "" -"fn main() {\n" -" let x = get_x(\"foo\");\n" -" println!(\"{x}\");\n" -"}\n" -"```" -msgstr "" +#: src/exercises/day-3/morning.md:1 +#, fuzzy +msgid "# Day 3: Morning Exercises" +msgstr "# Tag 3: Morgengymnastik" -#: src/generics/impl-trait.md:19 +#: src/exercises/day-3/morning.md:3 #, fuzzy -msgid "" -"* `impl Trait` cannot be used with the `::<>` turbo fish syntax.\n" -"* `impl Trait` allows you to work with types which you cannot name." -msgstr "" -"* `impl Trait` kann nicht mit der `::<>` Turbofish-Syntax verwendet werden.\n" -"* `impl Trait` ermöglicht es Ihnen, mit Typen zu arbeiten, die Sie nicht benennen können." +msgid "We will design a classical GUI library traits and trait objects." +msgstr "Wir werden Traits und Trait-Objekte einer klassischen GUI-Bibliothek entwerfen." -#: src/generics/impl-trait.md:24 +#: src/exercises/day-3/simple-gui.md:1 #, fuzzy -msgid "The meaning of `impl Trait` is a bit different in the different positions." -msgstr "Die Bedeutung von „impl Trait“ ist in den verschiedenen Positionen etwas unterschiedlich." +msgid "# A Simple GUI Library" +msgstr "# Eine einfache GUI-Bibliothek" -#: src/generics/impl-trait.md:26 +#: src/exercises/day-3/simple-gui.md:3 #, fuzzy msgid "" -"* For a parameter, `impl Trait` is like an anonymous generic parameter with a trait bound.\n" -"* For a return type, it means that the return type is some concrete type that implements the " -"trait,\n" -" without naming the type. This can be useful when you don't want to expose the concrete type in " -"a\n" -" public API." +"Let us design a classical GUI library using our new knowledge of traits and\n" +"trait objects." msgstr "" -"* Für einen Parameter ist `impl Trait` wie ein anonymer generischer Parameter mit einer " -"Eigenschaftsbindung.\n" -"* Für einen Rückgabetyp bedeutet dies, dass der Rückgabetyp ein konkreter Typ ist, der die " -"Eigenschaft implementiert,\n" -" ohne den Typ zu nennen. Dies kann nützlich sein, wenn Sie den konkreten Typ in a nicht verfügbar " -"machen möchten\n" -" öffentliche API." +"Lassen Sie uns eine klassische GUI-Bibliothek mit unserem neuen Wissen über Traits und entwerfen\n" +"Eigenschaftsobjekte." -#: src/generics/impl-trait.md:31 -#, fuzzy -msgid "" -"This example is great, because it uses `impl Display` twice. It helps to explain that\n" -"nothing here enforces that it is _the same_ `impl Display` type. If we used a single \n" -"`T: Display`, it would enforce the constraint that input `T` and return `T` type are the same " -"type.\n" -"It would not work for this particular function, as the type we expect as input is likely not\n" -"what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two\n" -"independent generic parameters.\n" -" \n" -"
" -msgstr "" -"Dieses Beispiel ist großartig, weil es `impl Display` zweimal verwendet. Es hilft, das zu " -"erklären\n" -"nichts hier erzwingt, dass es _derselbe_ `impl Display`-Typ ist. Wenn wir eine Single benutzten\n" -"`T: Display`, es würde die Einschränkung erzwingen, dass der Eingabe-`T`- und der Rückgabe-`T-Typ " -"derselbe Typ sind.\n" -"Es würde für diese spezielle Funktion nicht funktionieren, da der Typ, den wir als Eingabe " -"erwarten, wahrscheinlich nicht der Fall ist\n" -"welches `format!` zurückgibt. Wenn wir dasselbe über die `: Display`-Syntax machen wollten, " -"bräuchten wir zwei\n" -"unabhängige generische Parameter.\n" -" \n" -"
" - -#: src/generics/closures.md:1 -#, fuzzy -msgid "# Closures" -msgstr "# Schließungen" - -#: src/generics/closures.md:3 -#, fuzzy -msgid "" -"Closures or lambda expressions have types which cannot be named. However, they\n" -"implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" -"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and\n" -"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:" -msgstr "" -"Closures oder Lambda-Ausdrücke haben Typen, die nicht benannt werden können. Allerdings sie\n" -"spezielles [`Fn`] implementieren (https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" -"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html) und\n" -"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) Eigenschaften:" - -#: src/generics/closures.md:8 -msgid "" -"```rust,editable\n" -"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" -" println!(\"Calling function on {input}\");\n" -" func(input)\n" -"}" -msgstr "" - -#: src/generics/closures.md:14 -msgid "" -"fn main() {\n" -" let add_3 = |x| x + 3;\n" -" let mul_5 = |x| x * 5;" -msgstr "" - -#: src/generics/closures.md:18 -msgid "" -" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" -" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" -"}\n" -"```" -msgstr "" - -#: src/generics/closures.md:25 -#, fuzzy -msgid "If you have an `FnOnce`, you may only call it once. It might consume captured values." -msgstr "" -"Wenn Sie ein `FnOnce` haben, können Sie es nur einmal aufrufen. Es kann erfasste Werte verbrauchen." - -#: src/generics/closures.md:27 -#, fuzzy -msgid "" -"An `FnMut` might mutate captured values, so you can call it multiple times but not concurrently." -msgstr "" -"Ein `FnMut` kann erfasste Werte mutieren, sodass Sie es mehrmals, aber nicht gleichzeitig aufrufen " -"können." - -#: src/generics/closures.md:29 -#, fuzzy -msgid "" -"An `Fn` neither consumes nor mutates captured values, or perhaps captures nothing at all, so it " -"can\n" -"be called multiple times concurrently." -msgstr "" -"Ein „Fn“ verbraucht oder mutiert erfasste Werte nicht oder erfasst vielleicht gar nichts, also " -"kann es das\n" -"mehrmals gleichzeitig aufgerufen werden." - -#: src/generics/closures.md:32 -#, fuzzy -msgid "" -"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. I.e. you can use an\n" -"`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever an `FnMut` or " -"`FnOnce`\n" -"is called for." -msgstr "" -"`FnMut` ist ein Untertyp von `FnOnce`. „Fn“ ist ein Untertyp von „FnMut“ und „FnOnce“. D.h. Sie " -"können eine verwenden\n" -"„FnMut“, wo immer ein „FnOnce“ verlangt wird, und Sie können ein „Fn“ überall dort verwenden, wo " -"ein „FnMut“ oder „FnOnce“ steht\n" -"ist angesagt." - -#: src/generics/closures.md:36 -#, fuzzy -msgid "`move` closures only implement `FnOnce`." -msgstr "`move`-Closures implementieren nur `FnOnce`." - -#: src/generics/monomorphization.md:1 -#, fuzzy -msgid "# Monomorphization" -msgstr "# Monomorphisierung" - -#: src/generics/monomorphization.md:3 -#, fuzzy -msgid "Generic code is turned into non-generic code based on the call sites:" -msgstr "Basierend auf den Aufrufseiten wird generischer Code in nicht generischen Code umgewandelt:" - -#: src/generics/monomorphization.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let integer = Some(5);\n" -" let float = Some(5.0);\n" -"}\n" -"```" -msgstr "" - -#: src/generics/monomorphization.md:12 -#, fuzzy -msgid "behaves as if you wrote" -msgstr "verhält sich so, als hättest du geschrieben" - -#: src/generics/monomorphization.md:14 -msgid "" -"```rust,editable\n" -"enum Option_i32 {\n" -" Some(i32),\n" -" None,\n" -"}" -msgstr "" - -#: src/generics/monomorphization.md:20 -#, fuzzy -msgid "" -"enum Option_f64 {\n" -" Some(f64),\n" -" None,\n" -"}" -msgstr "" -"Aufzählung Option_f64 {\n" -" Einige (f64),\n" -" Keiner,\n" -"}" - -#: src/generics/monomorphization.md:25 -msgid "" -"fn main() {\n" -" let integer = Option_i32::Some(5);\n" -" let float = Option_f64::Some(5.0);\n" -"}\n" -"```" -msgstr "" - -#: src/generics/monomorphization.md:31 -#, fuzzy -msgid "" -"This is a zero-cost abstraction: you get exactly the same result as if you had\n" -"hand-coded the data structures without the abstraction." -msgstr "" -"Dies ist eine Null-Kosten-Abstraktion: Sie erhalten genau das gleiche Ergebnis, als ob Sie es " -"hätten\n" -"die Datenstrukturen ohne die Abstraktion von Hand codiert." - -#: src/generics/trait-objects.md:1 -#, fuzzy -msgid "# Trait Objects" -msgstr "# Eigenschaftsobjekte" - -#: src/generics/trait-objects.md:3 -#, fuzzy -msgid "We've seen how a function can take arguments which implement a trait:" -msgstr "" -"Wir haben gesehen, wie eine Funktion Argumente annehmen kann, die ein Merkmal implementieren:" - -#: src/generics/trait-objects.md:8 -msgid "" -"fn print(x: T) {\n" -" println!(\"Your value: {}\", x);\n" -"}" -msgstr "" - -#: src/generics/trait-objects.md:12 -msgid "" -"fn main() {\n" -" print(123);\n" -" print(\"Hello\");\n" -"}\n" -"```" -msgstr "" - -#: src/generics/trait-objects.md:18 -#, fuzzy -msgid "However, how can we store a collection of mixed types which implement `Display`?" -msgstr "" -"Wie können wir jedoch eine Sammlung gemischter Typen speichern, die \"Display\" implementieren?" - -#: src/generics/trait-objects.md:20 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let xs = vec![123, \"Hello\"];\n" -"}\n" -"```" -msgstr "" - -#: src/generics/trait-objects.md:26 -#, fuzzy -msgid "For this, we need _trait objects_:" -msgstr "Dafür brauchen wir _trait objects_:" - -#: src/generics/trait-objects.md:31 -msgid "" -"fn main() {\n" -" let xs: Vec> = vec![Box::new(123), Box::new(\"Hello\")];\n" -" for x in xs {\n" -" println!(\"x: {x}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/generics/trait-objects.md:39 -#, fuzzy -msgid "Memory layout after allocating `xs`:" -msgstr "Speicherlayout nach Zuweisung von `xs`:" - -#: src/generics/trait-objects.md:41 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" -": : : :\n" -": xs : : :\n" -": +-----------+-------+ : : +-----+-----+ :\n" -": | ptr | o---+---+-----+-->| o o | o o | :\n" -": | len | 2 | : : +-|-|-+-|-|-+ :\n" -": | capacity | 2 | : : | | | | +----+----+----+----+----+ :\n" -": +-----------+-------+ : : | | | '-->| H | e | l | l | o | :\n" -": : : | | | +----+----+----+----+----+ :\n" -"`- - - - - - - - - - - - - -' : | | | :\n" -" : | | | +-------------------------+ :\n" -" : | | '---->| \"::fmt\" | :\n" -" : | | +-------------------------+ :\n" -" : | | :\n" -" : | | +----+----+----+----+ :\n" -" : | '-->| 7b | 00 | 00 | 00 | :\n" -" : | +----+----+----+----+ :\n" -" : | :\n" -" : | +-------------------------+ :\n" -" : '---->| \"::fmt\" | :\n" -" : +-------------------------+ :\n" -" : :\n" -" : :\n" -" '- - - - - - - - - - - - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/generics/trait-objects.md:69 -#, fuzzy -msgid "" -"Similarly, you need a trait object if you want to return different values\n" -"implementing a trait:" -msgstr "" -"Ebenso benötigen Sie ein Trait-Objekt, wenn Sie andere Werte zurückgeben möchten\n" -"Implementieren eines Merkmals:" - -#: src/generics/trait-objects.md:72 -msgid "" -"```rust,editable\n" -"fn numbers(n: i32) -> Box> {\n" -" if n > 0 {\n" -" Box::new(0..n)\n" -" } else {\n" -" Box::new((n..0).rev())\n" -" }\n" -"}" -msgstr "" - -#: src/generics/trait-objects.md:81 -msgid "" -"fn main() {\n" -" println!(\"{:?}\", numbers(-5).collect::>());\n" -" println!(\"{:?}\", numbers(5).collect::>());\n" -"}" -msgstr "" - -#: src/exercises/day-3/morning.md:1 -#, fuzzy -msgid "# Day 3: Morning Exercises" -msgstr "# Tag 3: Morgengymnastik" - -#: src/exercises/day-3/morning.md:3 -#, fuzzy -msgid "We will design a classical GUI library traits and trait objects." -msgstr "Wir werden Traits und Trait-Objekte einer klassischen GUI-Bibliothek entwerfen." - -#: src/exercises/day-3/simple-gui.md:1 -#, fuzzy -msgid "# A Simple GUI Library" -msgstr "# Eine einfache GUI-Bibliothek" - -#: src/exercises/day-3/simple-gui.md:3 -#, fuzzy -msgid "" -"Let us design a classical GUI library using our new knowledge of traits and\n" -"trait objects." -msgstr "" -"Lassen Sie uns eine klassische GUI-Bibliothek mit unserem neuen Wissen über Traits und entwerfen\n" -"Eigenschaftsobjekte." - -#: src/exercises/day-3/simple-gui.md:6 +#: src/exercises/day-3/simple-gui.md:6 #, fuzzy msgid "We will have a number of widgets in our library:" msgstr "Wir werden eine Reihe von Widgets in unserer Bibliothek haben:" @@ -9666,83 +9072,44 @@ msgstr "" "aus\n" "`draw_into`-Methoden, sodass Sie das `Widget`-Merkmal implementieren:" -#: src/exercises/day-3/simple-gui.md:18 src/exercises/day-3/safe-ffi-wrapper.md:25 +#: src/exercises/day-3/simple-gui.md:18 msgid "" "```rust,should_panic\n" "// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_imports, unused_variables, dead_code)]" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:22 -msgid "" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" "pub trait Widget {\n" " /// Natural width of `self`.\n" -" fn width(&self) -> usize;" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:26 src/exercises/day-3/solutions-morning.md:27 -msgid "" +" fn width(&self) -> usize;\n" +"\n" " /// Draw the widget into a buffer.\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:29 src/exercises/day-3/solutions-morning.md:30 -msgid "" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" " /// Draw the widget on standard output.\n" " fn draw(&self) {\n" " let mut buffer = String::new();\n" " self.draw_into(&mut buffer);\n" -" println!(\"{}\", &buffer);\n" +" println!(\"{buffer}\");\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:37 src/exercises/day-3/solutions-morning.md:38 -#, fuzzy -msgid "" +"}\n" +"\n" "pub struct Label {\n" " label: String,\n" -"}" -msgstr "" -"Pub-Struktur Label {\n" -" Label: Zeichenkette,\n" -"}" - -#: src/exercises/day-3/simple-gui.md:41 src/exercises/day-3/solutions-morning.md:42 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Label {\n" " fn new(label: &str) -> Label {\n" " Label {\n" " label: label.to_owned(),\n" " }\n" " }\n" -"}" -msgstr "" -"impl Label {\n" -" fn new(label: &str) -> Label {\n" -" Etikett {\n" -" Bezeichnung: label.to_owned(),\n" -" }\n" -" }\n" -"}" - -#: src/exercises/day-3/simple-gui.md:49 src/exercises/day-3/solutions-morning.md:50 -#, fuzzy -msgid "" +"}\n" +"\n" "pub struct Button {\n" " label: Label,\n" " callback: Box,\n" -"}" -msgstr "" -"pub struct Schaltfläche {\n" -" Etikett: Etikett,\n" -" Rückruf: Box,\n" -"}" - -#: src/exercises/day-3/simple-gui.md:54 src/exercises/day-3/solutions-morning.md:55 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Button {\n" " fn new(label: &str, callback: Box) -> Button {\n" " Button {\n" @@ -9750,112 +9117,64 @@ msgid "" " callback,\n" " }\n" " }\n" -"}" -msgstr "" -"impl-Schaltfläche {\n" -" fn new(label: &str, callback: Box) -> Button {\n" -" Taste {\n" -" Label: Label::neu(Label),\n" -" Ruf zurück,\n" -" }\n" -" }\n" -"}" - -#: src/exercises/day-3/simple-gui.md:63 src/exercises/day-3/solutions-morning.md:64 -#, fuzzy -msgid "" +"}\n" +"\n" "pub struct Window {\n" " title: String,\n" " widgets: Vec>,\n" -"}" -msgstr "" -"pub struct Fenster {\n" -" Titel: Zeichenkette,\n" -" Widgets: Vec>,\n" -"}" - -#: src/exercises/day-3/simple-gui.md:68 src/exercises/day-3/solutions-morning.md:69 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Window {\n" " fn new(title: &str) -> Window {\n" " Window {\n" " title: title.to_owned(),\n" " widgets: Vec::new(),\n" " }\n" -" }" -msgstr "" -"impl-Fenster {\n" -" fn new(title: &str) -> Fenster {\n" -" Fenster {\n" -" Titel: title.to_owned(),\n" -" Widgets: Vec::new(),\n" -" }\n" -" }" - -#: src/exercises/day-3/simple-gui.md:76 src/exercises/day-3/solutions-morning.md:77 -msgid "" +" }\n" +"\n" " fn add_widget(&mut self, widget: Box) {\n" " self.widgets.push(widget);\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:82 -#, fuzzy -msgid "" +"\n" +" fn inner_width(&self) -> usize {\n" +" std::cmp::max(\n" +" self.title.chars().count(),\n" +" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +" )\n" +" }\n" +"}\n" +"\n" +"\n" "impl Widget for Label {\n" " fn width(&self) -> usize {\n" " unimplemented!()\n" -" }" -msgstr "" -"impl-Widget für Label {\n" -" fn width(&self) -> use {\n" -" nicht implementiert!()\n" -" }" - -#: src/exercises/day-3/simple-gui.md:87 src/exercises/day-3/simple-gui.md:97 -#: src/exercises/day-3/simple-gui.md:107 -#, fuzzy -msgid "" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" unimplemented!()\n" " }\n" -"}" -msgstr "" +"\n" " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" nicht implementiert!()\n" +" unimplemented!()\n" " }\n" -"}" - -#: src/exercises/day-3/simple-gui.md:92 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Widget for Button {\n" " fn width(&self) -> usize {\n" " unimplemented!()\n" -" }" -msgstr "" -"impl-Widget für Schaltfläche {\n" -" fn width(&self) -> use {\n" -" nicht implementiert!()\n" -" }" - -#: src/exercises/day-3/simple-gui.md:102 -#, fuzzy -msgid "" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" "impl Widget for Window {\n" " fn width(&self) -> usize {\n" " unimplemented!()\n" -" }" -msgstr "" -"impl-Widget für Fenster {\n" -" fn width(&self) -> use {\n" -" nicht implementiert!()\n" -" }" - -#: src/exercises/day-3/simple-gui.md:112 -msgid "" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" "fn main() {\n" " let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" " window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" @@ -9868,31 +9187,25 @@ msgid "" "```" msgstr "" -#: src/exercises/day-3/simple-gui.md:123 +#: src/exercises/day-3/simple-gui.md:130 #, fuzzy msgid "The output of the above program can be something simple like this:" msgstr "Die Ausgabe des obigen Programms kann so einfach sein:" -#: src/exercises/day-3/simple-gui.md:125 +#: src/exercises/day-3/simple-gui.md:132 msgid "" "```text\n" "========\n" "Rust GUI Demo 1.23\n" -"========" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:130 -#, fuzzy -msgid "This is a small text GUI demo." -msgstr "Dies ist eine kleine Text-GUI-Demo." - -#: src/exercises/day-3/simple-gui.md:132 -msgid "" +"========\n" +"\n" +"This is a small text GUI demo.\n" +"\n" "| Click me! |\n" "```" msgstr "" -#: src/exercises/day-3/simple-gui.md:135 +#: src/exercises/day-3/simple-gui.md:142 #, fuzzy msgid "" "If you want to draw aligned text, you can use the\n" @@ -9905,7 +9218,7 @@ msgstr "" "Formatierungsoperatoren. Beachten Sie insbesondere, wie Sie mit verschiedenen auffüllen können\n" "Zeichen (hier ein `'/'`) und wie Sie die Ausrichtung steuern können:" -#: src/exercises/day-3/simple-gui.md:140 +#: src/exercises/day-3/simple-gui.md:147 msgid "" "```rust,editable\n" "fn main() {\n" @@ -9917,12 +9230,12 @@ msgid "" "```" msgstr "" -#: src/exercises/day-3/simple-gui.md:149 +#: src/exercises/day-3/simple-gui.md:156 #, fuzzy msgid "Using such alignment tricks, you can for example produce output like this:" msgstr "Mit solchen Ausrichtungstricks können Sie beispielsweise eine Ausgabe wie diese erzeugen:" -#: src/exercises/day-3/simple-gui.md:151 +#: src/exercises/day-3/simple-gui.md:158 msgid "" "```text\n" "+--------------------------------+\n" @@ -10001,19 +9314,13 @@ msgstr "" #: src/error-handling/panic-unwind.md:5 msgid "" "```rust\n" -"use std::panic;" -msgstr "" - -#: src/error-handling/panic-unwind.md:8 -msgid "" +"use std::panic;\n" +"\n" "let result = panic::catch_unwind(|| {\n" " println!(\"hello!\");\n" "});\n" -"assert!(result.is_ok());" -msgstr "" - -#: src/error-handling/panic-unwind.md:13 -msgid "" +"assert!(result.is_ok());\n" +"\n" "let result = panic::catch_unwind(|| {\n" " panic!(\"oh no!\");\n" "});\n" @@ -10051,11 +9358,8 @@ msgstr "" msgid "" "```rust\n" "use std::fs::File;\n" -"use std::io::Read;" -msgstr "" - -#: src/error-handling/result.md:10 -msgid "" +"use std::io::Read;\n" +"\n" "fn main() {\n" " let file = File::open(\"diary.txt\");\n" " match file {\n" @@ -10083,8 +9387,7 @@ msgid "" "mentioning. \n" " It contains a lot of convenience methods and functions that help functional-style " "programming. \n" -" \n" -"
" +" " msgstr "" " * Wie bei `Option` befindet sich der erfolgreiche Wert innerhalb von `Result`, was den " "Entwickler dazu zwingt\n" @@ -10145,44 +9448,24 @@ msgstr "Wir können dies verwenden, um unseren Fehlerbehandlungscode zu vereinfa msgid "" "```rust,editable\n" "use std::fs;\n" -"use std::io::{self, Read};" -msgstr "" - -#: src/error-handling/try-operator.md:25 -msgid "" +"use std::io::{self, Read};\n" +"\n" "fn read_username(path: &str) -> Result {\n" -" let username_file_result = fs::File::open(path);" -msgstr "" - -#: src/error-handling/try-operator.md:28 -msgid "" +" 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" -" };" -msgstr "" - -#: src/error-handling/try-operator.md:33 -msgid " let mut username = String::new();" -msgstr "" - -#: src/error-handling/try-operator.md:35 -#, fuzzy -msgid "" +" };\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" " }\n" -"}" -msgstr "" -" match username_file.read_to_string(&mut username) {\n" -" Ok(_) => Ok(Benutzername),\n" -" Fehler(e) => Fehler(e),\n" -" }\n" -"}" - -#: src/error-handling/try-operator.md:41 -msgid "" +"}\n" +"\n" "fn main() {\n" " //fs::write(\"config.dat\", \"alice\").unwrap();\n" " let username = read_username(\"config.dat\");\n" @@ -10191,7 +9474,7 @@ msgid "" "```" msgstr "" -#: src/error-handling/try-operator.md:52 src/error-handling/converting-error-types.md:70 +#: src/error-handling/try-operator.md:52 src/error-handling/converting-error-types-example.md:52 #, fuzzy msgid "" "* The `username` variable can be either `Ok(string)` or `Err(error)`.\n" @@ -10203,6 +9486,7 @@ msgstr "" "leere Datei, Datei mit Benutzername." #: src/error-handling/converting-error-types.md:1 +#: src/error-handling/converting-error-types-example.md:1 #, fuzzy msgid "# Converting Error Types" msgstr "# Konvertieren von Fehlertypen" @@ -10243,86 +9527,46 @@ msgstr "" "Der `From::from`-Aufruf hier bedeutet, dass wir versuchen, den Fehlertyp in den zu konvertieren\n" "Typ, der von der Funktion zurückgegeben wird:" -#: src/error-handling/converting-error-types.md:21 +#: src/error-handling/converting-error-types-example.md:3 msgid "" "```rust,editable\n" "use std::error::Error;\n" -"use std::{fs, io};\n" -"use std::io::Read;\n" -"use std::fmt::{self, Display, Formatter};" -msgstr "" - -#: src/error-handling/converting-error-types.md:27 -#, fuzzy -msgid "" +"use std::fmt::{self, Display, Formatter};\n" +"use std::fs::{self, File};\n" +"use std::io::{self, Read};\n" +"\n" "#[derive(Debug)]\n" "enum ReadUsernameError {\n" " IoError(io::Error),\n" " EmptyUsername(String),\n" -"}" -msgstr "" -"#[ableiten(Debuggen)]\n" -"enum ReadUsernameError {\n" -" IoError(io::Fehler),\n" -" LeererBenutzername(String),\n" -"}" - -#: src/error-handling/converting-error-types.md:33 -#, fuzzy -msgid "impl Error for ReadUsernameError {}" -msgstr "impl-Fehler für ReadUsernameError {}" - -#: src/error-handling/converting-error-types.md:35 -#, fuzzy -msgid "" +"}\n" +"\n" +"impl Error for ReadUsernameError {}\n" +"\n" "impl Display for ReadUsernameError {\n" " fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" " match self {\n" -" Self::IoError(e) => write!(f, \"IO error: {}\", e),\n" -" Self::EmptyUsername(filename) => write!(f, \"Found no username in {}\", filename),\n" -" }\n" -" }\n" -"}" -msgstr "" -"impl Anzeige für ReadUsernameError {\n" -" fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" -" mit sich selbst übereinstimmen {\n" -" Self::IoError(e) => write!(f, \"IO error: {}\", e),\n" -" Self::EmptyUsername(filename) => write!(f, \"Keinen Benutzernamen gefunden in {}\", " -"filename),\n" +" Self::IoError(e) => write!(f, \"IO error: {e}\"),\n" +" Self::EmptyUsername(filename) => write!(f, \"Found no username in {filename}\"),\n" " }\n" " }\n" -"}" - -#: src/error-handling/converting-error-types.md:44 -#, fuzzy -msgid "" +"}\n" +"\n" "impl From for ReadUsernameError {\n" " fn from(err: io::Error) -> ReadUsernameError {\n" " ReadUsernameError::IoError(err)\n" " }\n" -"}" -msgstr "" -"impl From für ReadUsernameError {\n" -" fn from(err: io::Error) -> ReadUsernameError {\n" -" ReadUsernameError::IoError(err)\n" -" }\n" -"}" - -#: src/error-handling/converting-error-types.md:50 src/error-handling/deriving-error-enums.md:19 -msgid "" +"}\n" +"\n" "fn read_username(path: &str) -> Result {\n" " let mut username = String::with_capacity(100);\n" -" fs::File::open(path)?.read_to_string(&mut username)?;\n" +" File::open(path)?.read_to_string(&mut username)?;\n" " if username.is_empty() {\n" " return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" " }\n" " Ok(username)\n" -"}" -msgstr "" - -#: src/error-handling/converting-error-types.md:59 -msgid "" +"}\n" +"\n" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" " let username = read_username(\"config.dat\");\n" @@ -10331,7 +9575,7 @@ msgid "" "```" msgstr "" -#: src/error-handling/converting-error-types.md:73 +#: src/error-handling/converting-error-types-example.md:55 #, fuzzy msgid "" "It is good practice for all error types to implement `std::error::Error`, which requires `Debug` " @@ -10368,30 +9612,25 @@ msgid "" "```rust,editable,compile_fail\n" "use std::{fs, io};\n" "use std::io::Read;\n" -"use thiserror::Error;" -msgstr "" - -#: src/error-handling/deriving-error-enums.md:11 -#, fuzzy -msgid "" +"use thiserror::Error;\n" +"\n" "#[derive(Debug, Error)]\n" "enum ReadUsernameError {\n" " #[error(\"Could not read: {0}\")]\n" " IoError(#[from] io::Error),\n" " #[error(\"Found no username in {0}\")]\n" " EmptyUsername(String),\n" -"}" -msgstr "" -"#[ableiten(Debug, Fehler)]\n" -"enum ReadUsernameError {\n" -" #[error(\"Konnte nicht gelesen werden: {0}\")]\n" -" IoError(#[von] io::Fehler),\n" -" #[error(\"Keinen Benutzernamen in {0} gefunden\")]\n" -" LeererBenutzername(String),\n" -"}" - -#: src/error-handling/deriving-error-enums.md:28 src/error-handling/dynamic-errors.md:25 -msgid "" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" " match read_username(\"config.dat\") {\n" @@ -10442,18 +9681,12 @@ msgid "" "use std::fs::{self, File};\n" "use std::io::Read;\n" "use thiserror::Error;\n" -"use std::error::Error;" -msgstr "" - -#: src/error-handling/dynamic-errors.md:12 -msgid "" +"use std::error::Error;\n" +"\n" "#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" "#[error(\"Found no username in {0}\")]\n" -"struct EmptyUsernameError(String);" -msgstr "" - -#: src/error-handling/dynamic-errors.md:16 -msgid "" +"struct EmptyUsernameError(String);\n" +"\n" "fn read_username(path: &str) -> Result> {\n" " let mut username = String::with_capacity(100);\n" " File::open(path)?.read_to_string(&mut username)?;\n" @@ -10461,7 +9694,16 @@ msgid "" " return Err(EmptyUsernameError(String::from(path)).into());\n" " }\n" " Ok(username)\n" -"}" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" msgstr "" #: src/error-handling/dynamic-errors.md:36 @@ -10504,26 +9746,20 @@ msgid "" "```rust,editable,compile_fail\n" "use std::{fs, io};\n" "use std::io::Read;\n" -"use anyhow::{Context, Result, bail};" -msgstr "" - -#: src/error-handling/error-contexts.md:12 -msgid "" +"use anyhow::{Context, Result, bail};\n" +"\n" "fn read_username(path: &str) -> Result {\n" " let mut username = String::with_capacity(100);\n" " fs::File::open(path)\n" -" .context(format!(\"Failed to open {path}\"))?\n" +" .with_context(|| format!(\"Failed to open {path}\"))?\n" " .read_to_string(&mut username)\n" " .context(\"Failed to read\")?;\n" " if username.is_empty() {\n" " bail!(\"Found no username in {path}\");\n" " }\n" " Ok(username)\n" -"}" -msgstr "" - -#: src/error-handling/error-contexts.md:24 -msgid "" +"}\n" +"\n" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" " match read_username(\"config.dat\") {\n" @@ -10567,12 +9803,10 @@ msgstr "Rust und Cargo verfügen über ein einfaches Unit-Test-Framework:" #: src/testing.md:5 #, fuzzy -msgid "* Unit tests are supported throughout your code." -msgstr "* Komponententests werden im gesamten Code unterstützt." - -#: src/testing.md:7 -#, fuzzy -msgid "* Integration tests are supported via the `tests/` directory." +msgid "" +"* Unit tests are supported throughout your code.\n" +"\n" +"* Integration tests are supported via the `tests/` directory." msgstr "* Integrationstests werden über das Verzeichnis „tests/“ unterstützt." #: src/testing/unit-tests.md:1 @@ -10587,33 +9821,24 @@ msgstr "Unit-Tests mit `#[test]` markieren:" #: src/testing/unit-tests.md:5 msgid "" -"```rust,editable\n" +"```rust,ignore\n" "fn first_word(text: &str) -> &str {\n" " match text.find(' ') {\n" " Some(idx) => &text[..idx],\n" " None => &text,\n" " }\n" -"}" -msgstr "" - -#: src/testing/unit-tests.md:13 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_empty() {\n" " assert_eq!(first_word(\"\"), \"\");\n" -"}" -msgstr "" - -#: src/testing/unit-tests.md:18 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_single_word() {\n" " assert_eq!(first_word(\"Hello\"), \"Hello\");\n" -"}" -msgstr "" - -#: src/testing/unit-tests.md:23 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_multiple_words() {\n" " assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" @@ -10645,18 +9870,16 @@ msgid "" "```rust,editable\n" "fn helper(a: &str, b: &str) -> String {\n" " format!(\"{a} {b}\")\n" -"}" -msgstr "" - -#: src/testing/test-modules.md:11 -msgid "" +"}\n" +"\n" "pub fn main() {\n" " println!(\"{}\", helper(\"Hello\", \"World\"));\n" -"}" -msgstr "" - -#: src/testing/test-modules.md:19 -msgid "" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" " #[test]\n" " fn test_helper() {\n" " assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" @@ -10731,11 +9954,8 @@ msgstr "Erstellen Sie eine `.rs`-Datei unter `tests/`:" #: src/testing/integration-tests.md:7 msgid "" "```rust,ignore\n" -"use my_library::init;" -msgstr "" - -#: src/testing/integration-tests.md:10 -msgid "" +"use my_library::init;\n" +"\n" "#[test]\n" "fn test_init() {\n" " assert!(init().is_ok());\n" @@ -10843,17 +10063,11 @@ msgstr "Das Erstellen von Zeigern ist sicher, aber das Dereferenzieren erfordert msgid "" "```rust,editable\n" "fn main() {\n" -" let mut num = 5;" -msgstr "" - -#: src/unsafe/raw-pointers.md:9 -msgid "" +" let mut num = 5;\n" +"\n" " let r1 = &mut num as *mut i32;\n" -" let r2 = &num as *const i32;" -msgstr "" - -#: src/unsafe/raw-pointers.md:12 -msgid "" +" 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" @@ -10927,13 +10141,10 @@ msgstr "Es ist sicher, eine unveränderliche statische Variable zu lesen:" #: src/unsafe/mutable-static-variables.md:5 msgid "" "```rust,editable\n" -"static HELLO_WORLD: &str = \"Hello, world!\";" -msgstr "" - -#: src/unsafe/mutable-static-variables.md:8 -msgid "" +"static HELLO_WORLD: &str = \"Hello, world!\";\n" +"\n" "fn main() {\n" -" println!(\"HELLO_WORLD: {}\", HELLO_WORLD);\n" +" println!(\"HELLO_WORLD: {HELLO_WORLD}\");\n" "}\n" "```" msgstr "" @@ -10950,25 +10161,16 @@ msgstr "" #: src/unsafe/mutable-static-variables.md:16 msgid "" "```rust,editable\n" -"static mut COUNTER: u32 = 0;" -msgstr "" - -#: src/unsafe/mutable-static-variables.md:19 -msgid "" +"static mut COUNTER: u32 = 0;\n" +"\n" "fn add_to_counter(inc: u32) {\n" " unsafe { COUNTER += inc; } // Potential data race!\n" -"}" -msgstr "" - -#: src/unsafe/mutable-static-variables.md:23 -msgid "" +"}\n" +"\n" "fn main() {\n" -" add_to_counter(42);" -msgstr "" - -#: src/unsafe/mutable-static-variables.md:26 -msgid "" -" unsafe { println!(\"COUNTER: {}\", COUNTER); } // Potential data race!\n" +" add_to_counter(42);\n" +"\n" +" unsafe { println!(\"COUNTER: {COUNTER}\"); } // Potential data race!\n" "}\n" "```" msgstr "" @@ -11002,11 +10204,8 @@ msgid "" "union MyUnion {\n" " i: u8,\n" " b: bool,\n" -"}" -msgstr "" - -#: src/unsafe/unions.md:12 -msgid "" +"}\n" +"\n" "fn main() {\n" " let u = MyUnion { i: 42 };\n" " println!(\"int: {}\", unsafe { u.i });\n" @@ -11058,18 +10257,25 @@ msgstr "" msgid "" "```rust,editable\n" "fn main() {\n" -" let emojis = \"🗻∈🌏\";" -msgstr "" - -#: src/unsafe/calling-unsafe-functions.md:10 -msgid "" +" let emojis = \"🗻∈🌏\";\n" +"\n" " // Safe because the indices are in the correct order, within the bounds of\n" " // the string slice, and lie on UTF-8 sequence boundaries.\n" " unsafe {\n" -" println!(\"{}\", emojis.get_unchecked(0..4));\n" -" println!(\"{}\", emojis.get_unchecked(4..7));\n" -" println!(\"{}\", emojis.get_unchecked(7..11));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(0..4));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(4..7));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(7..11));\n" " }\n" +"\n" +" println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..7) }));\n" +"\n" +" // Not upholding the UTF-8 encoding requirement breaks memory safety!\n" +" // println!(\"emoji: {}\", unsafe { emojis.get_unchecked(0..3) });\n" +" // println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..3) }));\n" +"}\n" +"\n" +"fn count_chars(s: &str) -> usize {\n" +" s.chars().map(|_| 1).sum()\n" "}\n" "```" msgstr "" @@ -11102,26 +10308,17 @@ msgid "" " let temp = *a;\n" " *a = *b;\n" " *b = temp;\n" -"}" -msgstr "" - -#: src/unsafe/writing-unsafe-functions.md:18 -msgid "" +"}\n" +"\n" "fn main() {\n" " let mut a = 42;\n" -" let mut b = 66;" -msgstr "" - -#: src/unsafe/writing-unsafe-functions.md:22 -msgid "" +" let mut b = 66;\n" +"\n" " // Safe because ...\n" " unsafe {\n" " swap(&mut a, &mut b);\n" -" }" -msgstr "" - -#: src/unsafe/writing-unsafe-functions.md:27 -msgid "" +" }\n" +"\n" " println!(\"a = {}, b = {}\", a, b);\n" "}\n" "```" @@ -11163,11 +10360,8 @@ msgid "" "```rust,editable\n" "extern \"C\" {\n" " fn abs(input: i32) -> i32;\n" -"}" -msgstr "" - -#: src/unsafe/extern-functions.md:11 -msgid "" +"}\n" +"\n" "fn main() {\n" " unsafe {\n" " // Undefined behavior if abs misbehaves.\n" @@ -11222,15 +10416,12 @@ msgstr "" "[etwas in der Art](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" #: src/unsafe/unsafe-traits.md:9 +#, fuzzy msgid "" "```rust,editable\n" "use std::mem::size_of_val;\n" -"use std::slice;" -msgstr "" - -#: src/unsafe/unsafe-traits.md:13 -#, fuzzy -msgid "" +"use std::slice;\n" +"\n" "/// ...\n" "/// # Safety\n" "/// The type must have a defined representation and no padding.\n" @@ -11240,7 +10431,11 @@ msgid "" " slice::from_raw_parts(self as *const Self as *const u8, size_of_val(self))\n" " }\n" " }\n" -"}" +"}\n" +"\n" +"// Safe because u32 has a defined representation and no padding.\n" +"unsafe impl AsBytes for u32 {}\n" +"```" msgstr "" "/// ...\n" "/// # Sicherheit\n" @@ -11253,13 +10448,6 @@ msgstr "" " }\n" "}" -#: src/unsafe/unsafe-traits.md:24 -msgid "" -"// Safe because u32 has a defined representation and no padding.\n" -"unsafe impl AsBytes for u32 {}\n" -"```" -msgstr "" - #: src/unsafe/unsafe-traits.md:30 #, fuzzy msgid "" @@ -11296,11 +10484,6 @@ msgid "After looking at the exercise, you can look at the [solution] provided." msgstr "" "Nachdem Sie sich die Übung angesehen haben, können Sie sich die bereitgestellte [Lösung] ansehen." -#: src/exercises/day-3/afternoon.md:9 -#, fuzzy -msgid "[solution]: solutions-afternoon.md" -msgstr "[Lösung]: Lösungen-Nachmittag.md" - #: src/exercises/day-3/safe-ffi-wrapper.md:1 #, fuzzy msgid "# Safe FFI Wrapper" @@ -11346,19 +10529,6 @@ msgstr "" "kommen\n" "C. Das [Nomicon] hat auch ein sehr nützliches Kapitel über FFI." -#: src/exercises/day-3/safe-ffi-wrapper.md:17 -#, fuzzy -msgid "" -"[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" -"[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" -"[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" -"[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" -msgstr "" -"[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" -"[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" -"[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" -"[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" - #: src/exercises/day-3/safe-ffi-wrapper.md:22 #, fuzzy msgid "" @@ -11369,25 +10539,26 @@ msgstr "" "aus\n" "Funktionen und Methoden:" -#: src/exercises/day-3/safe-ffi-wrapper.md:29 +#: src/exercises/day-3/safe-ffi-wrapper.md:25 msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" "mod ffi {\n" -" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:32 src/exercises/day-3/solutions-afternoon.md:26 -msgid "" +" use std::os::raw::{c_char, c_int};\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" use std::os::raw::{c_long, c_ulong, c_ushort};\n" +"\n" " // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" " #[repr(C)]\n" " pub struct DIR {\n" " _data: [u8; 0],\n" " _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" -" }" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:39 src/exercises/day-3/solutions-afternoon.md:33 -msgid "" +" }\n" +"\n" " // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" +" #[cfg(not(target_os = \"macos\"))]\n" " #[repr(C)]\n" " pub struct dirent {\n" " pub d_ino: c_long,\n" @@ -11395,89 +10566,59 @@ msgid "" " pub d_reclen: c_ushort,\n" " pub d_type: c_char,\n" " pub d_name: [c_char; 256],\n" -" }" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:49 src/exercises/day-3/solutions-afternoon.md:43 -msgid "" +" }\n" +"\n" +" // Layout as per man entry for dirent\n" +" #[cfg(target_os = \"macos\")]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: u64,\n" +" pub d_seekoff: u64,\n" +" pub d_reclen: u16,\n" +" pub d_namlen: u16,\n" +" pub d_type: u8,\n" +" pub d_name: [c_char; 1024],\n" +" }\n" +"\n" " extern \"C\" {\n" " pub fn opendir(s: *const c_char) -> *mut DIR;\n" " pub fn readdir(s: *mut DIR) -> *const dirent;\n" " pub fn closedir(s: *mut DIR) -> c_int;\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:56 src/exercises/day-3/solutions-afternoon.md:50 -msgid "" +"}\n" +"\n" "use std::ffi::{CStr, CString, OsStr, OsString};\n" -"use std::os::unix::ffi::OsStrExt;" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:59 -#, fuzzy -msgid "" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" "#[derive(Debug)]\n" "struct DirectoryIterator {\n" " path: CString,\n" " dir: *mut ffi::DIR,\n" -"}" -msgstr "" -"#[ableiten(Debuggen)]\n" -"struct DirectoryIterator {\n" -" Pfad: CString,\n" -" dir: *mut ffi::DIR,\n" -"}" - -#: src/exercises/day-3/safe-ffi-wrapper.md:65 -#, fuzzy -msgid "" +"}\n" +"\n" "impl DirectoryIterator {\n" " fn new(path: &str) -> Result {\n" " // Call opendir and return a Ok value if that worked,\n" " // otherwise return Err with a message.\n" " unimplemented!()\n" " }\n" -"}" -msgstr "" -"impl DirectoryIterator {\n" -" fn new(path: &str) -> Ergebnis {\n" -" // Opendir aufrufen und einen Ok-Wert zurückgeben, wenn das funktioniert hat,\n" -" // andernfalls Err mit einer Nachricht zurückgeben.\n" -" nicht implementiert!()\n" -" }\n" -"}" - -#: src/exercises/day-3/safe-ffi-wrapper.md:73 -msgid "" +"}\n" +"\n" "impl Iterator for DirectoryIterator {\n" " type Item = OsString;\n" " fn next(&mut self) -> Option {\n" " // Keep calling readdir until we get a NULL pointer back.\n" " unimplemented!()\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:81 -#, fuzzy -msgid "" +"}\n" +"\n" "impl Drop for DirectoryIterator {\n" " fn drop(&mut self) {\n" " // Call closedir as needed.\n" " unimplemented!()\n" " }\n" -"}" -msgstr "" -"impl Drop für DirectoryIterator {\n" -" fn drop(&mut self) {\n" -" // Gegebenenfalls closedir aufrufen.\n" -" nicht implementiert!()\n" -" }\n" -"}" - -#: src/exercises/day-3/safe-ffi-wrapper.md:88 -msgid "" +"}\n" +"\n" "fn main() -> Result<(), String> {\n" " let iter = DirectoryIterator::new(\".\")?;\n" " println!(\"files: {:#?}\", iter.collect::>());\n" @@ -11492,37 +10633,16 @@ msgid "# Welcome to Day 4" msgstr "# Willkommen zu Tag 4" #: src/welcome-day-4.md:3 -#, fuzzy -msgid "Today we will look at two main topics:" -msgstr "Heute werden wir uns mit zwei Hauptthemen befassen:" - -#: src/welcome-day-4.md:5 -#, fuzzy -msgid "* Concurrency: threads, channels, shared state, `Send` and `Sync`." -msgstr "* Gleichzeitigkeit: Threads, Kanäle, gemeinsamer Status, „Senden“ und „Synchronisieren“." - -#: src/welcome-day-4.md:7 -#, fuzzy msgid "" -"* Android: building binaries and libraries, using AIDL, logging, and\n" -" interoperability with C, C++, and Java." +"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 "" -"* Android: Erstellung von Binärdateien und Bibliotheken, Verwendung von AIDL, Protokollierung und\n" -" Interoperabilität mit C, C++ und Java." -#: src/welcome-day-4.md:10 -#, fuzzy +#: src/welcome-day-4.md:8 msgid "" -"> We will attempt to call Rust from one of your own projects today. So try to\n" -"> find a little corner of your code base where we can move some lines of code to\n" -"> Rust. The fewer dependencies and \"exotic\" types the better. Something that\n" -"> parses some raw bytes would be ideal." +"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 "" -"> Wir werden heute versuchen, Rust aus einem Ihrer eigenen Projekte anzurufen. Versuchen Sie es " -"also\n" -"> Finden Sie eine kleine Ecke Ihrer Codebasis, in die wir einige Codezeilen verschieben können\n" -"> Rost. Je weniger Abhängigkeiten und \"exotische\" Typen, desto besser. Etwas das\n" -"> parst einige rohe Bytes wäre ideal." #: src/concurrency.md:1 #, fuzzy @@ -11564,22 +10684,16 @@ msgstr "Rust-Threads funktionieren ähnlich wie Threads in anderen Sprachen:" msgid "" "```rust,editable\n" "use std::thread;\n" -"use std::time::Duration;" -msgstr "" - -#: src/concurrency/threads.md:9 -msgid "" +"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" -" });" -msgstr "" - -#: src/concurrency/threads.md:17 -msgid "" +" });\n" +"\n" " for i in 1..5 {\n" " println!(\"Main thread: {i}\");\n" " thread::sleep(Duration::from_millis(5));\n" @@ -11600,42 +10714,18 @@ msgstr "" " * Paniken können eine Nutzlast tragen, die mit `downcast_ref` entpackt werden kann." #: src/concurrency/threads.md:32 -#, fuzzy msgid "" "* Notice that the thread is stopped before it reaches 10 — the main thread is\n" -" not waiting." -msgstr "" -"* Beachten Sie, dass der Thread gestoppt wird, bevor er 10 erreicht – der Haupt-Thread ist es\n" -" nicht warten." - -#: src/concurrency/threads.md:35 -#, fuzzy -msgid "" +" not waiting.\n" +"\n" "* Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for\n" -" the thread to finish." -msgstr "" -"* Verwenden Sie `let handle = thread::spawn(...)` und später `handle.join()`, um darauf zu warten\n" -" den Thread zu beenden." - -#: src/concurrency/threads.md:38 -#, fuzzy -msgid "* Trigger a panic in the thread, notice how this doesn't affect `main`." -msgstr "* Lösen Sie eine Panik im Thread aus, beachten Sie, dass dies `main` nicht betrifft." - -#: src/concurrency/threads.md:40 -#, fuzzy -msgid "" +" 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 "" -"* Verwenden Sie den `Result`-Rückgabewert von `handle.join()`, um Zugriff auf die Panik zu " -"erhalten\n" -" Nutzlast. Dies ist ein guter Zeitpunkt, um über [`Any`] zu sprechen." - -#: src/concurrency/threads.md:43 -#, fuzzy -msgid "[`Any`]: https://doc.rust-lang.org/std/any/index.html" -msgstr "[`Any`]: https://doc.rust-lang.org/std/any/index.html" #: src/concurrency/scoped-threads.md:1 #, fuzzy @@ -11650,17 +10740,11 @@ 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;" -msgstr "" - -#: src/concurrency/scoped-threads.md:8 src/concurrency/scoped-threads.md:22 -msgid "" +"use std::thread;\n" +"\n" "fn main() {\n" -" let s = String::from(\"Hello\");" -msgstr "" - -#: src/concurrency/scoped-threads.md:11 -msgid "" +" let s = String::from(\"Hello\");\n" +"\n" " thread::spawn(|| {\n" " println!(\"Length: {}\", s.len());\n" " });\n" @@ -11676,11 +10760,11 @@ 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;" -msgstr "" - -#: src/concurrency/scoped-threads.md:25 -msgid "" +"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" @@ -11690,25 +10774,15 @@ msgid "" "```" msgstr "" -#: src/concurrency/scoped-threads.md:33 -#, fuzzy -msgid "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html" -msgstr "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html" - -#: src/concurrency/scoped-threads.md:35 +#: src/concurrency/scoped-threads.md:37 #, fuzzy msgid "" -"
\n" -" \n" "* 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" -" \n" -"
" +" " msgstr "" -"
\n" -" \n" "* 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 " @@ -11734,29 +10808,17 @@ msgstr "" msgid "" "```rust,editable\n" "use std::sync::mpsc;\n" -"use std::thread;" -msgstr "" - -#: src/concurrency/channels.md:10 src/concurrency/channels/unbounded.md:10 -msgid "" +"use std::thread;\n" +"\n" "fn main() {\n" -" let (tx, rx) = mpsc::channel();" -msgstr "" - -#: src/concurrency/channels.md:13 -msgid "" +" let (tx, rx) = mpsc::channel();\n" +"\n" " tx.send(10).unwrap();\n" -" tx.send(20).unwrap();" -msgstr "" - -#: src/concurrency/channels.md:16 -msgid "" +" tx.send(20).unwrap();\n" +"\n" " println!(\"Received: {:?}\", rx.recv());\n" -" println!(\"Received: {:?}\", rx.recv());" -msgstr "" - -#: src/concurrency/channels.md:19 -msgid "" +" println!(\"Received: {:?}\", rx.recv());\n" +"\n" " let tx2 = tx.clone();\n" " tx2.send(30).unwrap();\n" " println!(\"Received: {:?}\", rx.recv());\n" @@ -11791,16 +10853,16 @@ msgstr "# Unbegrenzte Kanäle" 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 src/concurrency/channels/bounded.md:5 +#: src/concurrency/channels/unbounded.md:5 msgid "" "```rust,editable\n" "use std::sync::mpsc;\n" "use std::thread;\n" -"use std::time::Duration;" -msgstr "" - -#: src/concurrency/channels/unbounded.md:13 src/concurrency/channels/bounded.md:13 -msgid "" +"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" @@ -11809,11 +10871,8 @@ msgid "" " }\n" " println!(\"{thread_id:?}: done\");\n" " });\n" -" thread::sleep(Duration::from_millis(100));" -msgstr "" - -#: src/concurrency/channels/unbounded.md:23 src/concurrency/channels/bounded.md:23 -msgid "" +" thread::sleep(Duration::from_millis(100));\n" +"\n" " for msg in rx.iter() {\n" " println!(\"Main: got {}\", msg);\n" " }\n" @@ -11833,10 +10892,31 @@ msgstr "" "Gebundene und synchrone Kanäle sorgen dafür, dass der aktuelle Thread durch „Senden“ blockiert " "wird:" -#: src/concurrency/channels/bounded.md:10 +#: 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);" +" 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 @@ -11866,15 +10946,6 @@ msgstr "" " 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.md:10 -#, fuzzy -msgid "" -"[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" -"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" -msgstr "" -"[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" -"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" - #: src/concurrency/shared_state/arc.md:1 #, fuzzy msgid "# `Arc`" @@ -11889,11 +10960,8 @@ msgstr "[`Arc`][1] ermöglicht den gemeinsamen Nur-Lese-Zugriff über seine ` msgid "" "```rust,editable\n" "use std::thread;\n" -"use std::sync::Arc;" -msgstr "" - -#: src/concurrency/shared_state/arc.md:9 -msgid "" +"use std::sync::Arc;\n" +"\n" "fn main() {\n" " let v = Arc::new(vec![10, 20, 30]);\n" " let mut handles = Vec::new();\n" @@ -11903,22 +10971,14 @@ msgid "" " let thread_id = thread::current().id();\n" " println!(\"{thread_id:?}: {v:?}\");\n" " }));\n" -" }" -msgstr "" - -#: src/concurrency/shared_state/arc.md:20 -msgid "" +" }\n" +"\n" " handles.into_iter().for_each(|h| h.join().unwrap());\n" " println!(\"v: {v:?}\");\n" "}\n" "```" msgstr "" -#: src/concurrency/shared_state/arc.md:25 -#, fuzzy -msgid "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" -msgstr "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" - #: src/concurrency/shared_state/arc.md:29 #, fuzzy msgid "" @@ -11962,33 +11022,23 @@ msgstr "" #: src/concurrency/shared_state/mutex.md:6 msgid "" "```rust,editable\n" -"use std::sync::Mutex;" -msgstr "" - -#: src/concurrency/shared_state/mutex.md:9 -msgid "" +"use std::sync::Mutex;\n" +"\n" "fn main() {\n" -" let v: Mutex> = Mutex::new(vec![10, 20, 30]);\n" -" println!(\"v: {:?}\", v.lock().unwrap());" -msgstr "" - -#: src/concurrency/shared_state/mutex.md:13 -msgid "" +" let v = Mutex::new(vec![10, 20, 30]);\n" +" println!(\"v: {:?}\", v.lock().unwrap());\n" +"\n" " {\n" -" let v: &Mutex> = &v;\n" " let mut guard = v.lock().unwrap();\n" " guard.push(40);\n" -" }" -msgstr "" - -#: src/concurrency/shared_state/mutex.md:19 -msgid "" +" }\n" +"\n" " println!(\"v: {:?}\", v.lock().unwrap());\n" "}\n" "```" msgstr "" -#: src/concurrency/shared_state/mutex.md:23 +#: src/concurrency/shared_state/mutex.md:22 #, fuzzy msgid "" "Notice how we have a [`impl Sync for Mutex`][2] blanket\n" @@ -11997,22 +11047,9 @@ msgstr "" "Beachten Sie, wie wir eine [`impl Sync for Mutex`][2] Blanket haben\n" "Implementierung." -#: src/concurrency/shared_state/mutex.md:26 -#, fuzzy -msgid "" -"[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" -"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-Mutex%3CT%3E\n" -"[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" -msgstr "" -"[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" -"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-Mutex%3CT%3E\n" -"[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" - -#: src/concurrency/shared_state/mutex.md:30 +#: src/concurrency/shared_state/mutex.md:31 #, fuzzy msgid "" -"
\n" -" \n" "* `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 " @@ -12028,8 +11065,6 @@ msgid "" " fails with a [`PoisonError`]. You can call `into_inner()` on the error to recover the data\n" " regardless." msgstr "" -"
\n" -" \n" "* `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" @@ -12047,17 +11082,6 @@ msgstr "" "um die Daten wiederherzustellen\n" " trotzdem." -#: src/concurrency/shared_state/mutex.md:44 -#, fuzzy -msgid "" -"[`PoisonError`]: https://doc.rust-lang.org/std/sync/struct.PoisonError.html \n" -" \n" -"
" -msgstr "" -"[`PoisonError`]: https://doc.rust-lang.org/std/sync/struct.PoisonError.html\n" -" \n" -"
" - #: src/concurrency/shared_state/example.md:3 #, fuzzy msgid "Let us see `Arc` and `Mutex` in action:" @@ -12067,21 +11091,15 @@ msgstr "Sehen wir uns `Arc` und `Mutex` in Aktion an:" msgid "" "```rust,editable,compile_fail\n" "use std::thread;\n" -"// use std::sync::{Arc, Mutex};" -msgstr "" - -#: src/concurrency/shared_state/example.md:9 -msgid "" +"// 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);" -msgstr "" - -#: src/concurrency/shared_state/example.md:16 -msgid "" +" v.push(1000);\n" +"\n" " handle.join().unwrap();\n" " println!(\"v: {v:?}\");\n" "}\n" @@ -12089,62 +11107,48 @@ msgid "" msgstr "" #: src/concurrency/shared_state/example.md:23 -msgid "" -"Possible solution:\n" -" \n" -"```rust,editable\n" -"use std::sync::{Arc, Mutex};\n" -"use std::thread;" +msgid "Possible solution:" msgstr "" -#: src/concurrency/shared_state/example.md:29 +#: 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]));" -msgstr "" - -#: src/concurrency/shared_state/example.md:32 -msgid "" +" 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" -" });" -msgstr "" - -#: src/concurrency/shared_state/example.md:38 -msgid "" +" });\n" +"\n" " {\n" " let mut v = v.lock().unwrap();\n" " v.push(1000);\n" -" }" -msgstr "" - -#: src/concurrency/shared_state/example.md:43 -msgid " handle.join().unwrap();" -msgstr "" - -#: src/concurrency/shared_state/example.md:45 -msgid "" -" {\n" -" let v = v.lock().unwrap();\n" -" println!(\"v: {v:?}\");\n" " }\n" +"\n" +" handle.join().unwrap();\n" +"\n" +" println!(\"v: {v:?}\");\n" "}\n" -"```\n" -" \n" -"Notable parts:" +"```" +msgstr "" + +#: src/concurrency/shared_state/example.md:49 +msgid "Notable parts:" msgstr "" -#: src/concurrency/shared_state/example.md:54 +#: 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.\n" -"* We still need to acquire the `Mutex` to print our `Vec`." +"* 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 " @@ -12196,24 +11200,12 @@ msgstr "" "wenn Sie\n" "wissen, dass es gültig ist." -#: src/concurrency/send-sync.md:14 -#, fuzzy -msgid "" -"[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" -"[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html\n" -"[3]: ../unsafe/unsafe-traits.md" -msgstr "" -"[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" -"[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html\n" -"[3]: ../unsafe/unsafe-traits.md" - #: 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" -" \n" -"
" +" " msgstr "" "* Man kann sich diese Eigenschaften als Markierungen dafür vorstellen, dass der Typ bestimmte " "Thread-Sicherheitseigenschaften hat.\n" @@ -12245,11 +11237,6 @@ msgstr "" "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:9 -#, fuzzy -msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" -msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" - #: src/concurrency/send-sync/sync.md:1 #, fuzzy msgid "# `Sync`" @@ -12274,11 +11261,6 @@ msgstr "Genauer gesagt lautet die Definition:" 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:10 -#, fuzzy -msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Sync.html" -msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Sync.html" - #: src/concurrency/send-sync/sync.md:14 #, fuzzy msgid "" @@ -12407,7 +11389,8 @@ msgstr "" "* `*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/afternoon.md:1 +#: 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" @@ -12419,12 +11402,9 @@ 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." -msgstr "* Speisephilosophen: ein klassisches Problem der Nebenläufigkeit." - -#: src/exercises/day-4/morning.md:7 -#, 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 "" @@ -12466,93 +11446,82 @@ msgstr "" #, fuzzy msgid "" "You will need a local [Cargo installation](../../cargo/running-locally.md) for\n" -"this exercise. Copy the code below to `src/main.rs` file, fill out the blanks,\n" -"and test that `cargo run` does not deadlock:" +"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 -msgid "" -"```rust,compile_fail\n" -"use std::sync::mpsc;\n" -"use std::sync::{Arc, Mutex};\n" -"use std::thread;\n" -"use std::time::Duration;" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:23 src/exercises/day-4/solutions-morning.md:28 -msgid "struct Fork;" +#: 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:25 -#, fuzzy +#: 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" -"}" -msgstr "" -"struct Philosoph {\n" -" Name: Zeichenfolge,\n" -" // left_fork: ...\n" -" // right_fork: ...\n" -" // Gedanken: ...\n" -"}" - -#: src/exercises/day-4/dining-philosophers.md:32 -msgid "" +"}\n" +"\n" "impl Philosopher {\n" " fn think(&self) {\n" " self.thoughts\n" " .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" " .unwrap();\n" -" }" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:39 -msgid "" +" }\n" +"\n" " fn eat(&self) {\n" " // Pick up forks...\n" " println!(\"{} is eating...\", &self.name);\n" " thread::sleep(Duration::from_millis(10));\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:46 src/exercises/day-4/solutions-morning.md:60 -msgid "" +"}\n" +"\n" "static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:49 -#, fuzzy -msgid "" +" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" +"\n" "fn main() {\n" -" // Create forks" +" // Create forks\n" +"\n" +" // Create philosophers\n" +"\n" +" // Make them think and eat\n" +"\n" +" // Output their thoughts\n" +"}\n" +"```" msgstr "" -"fn Haupt() {\n" -" // Gabeln erstellen" -#: src/exercises/day-4/dining-philosophers.md:52 -#, fuzzy -msgid " // Create philosophers" -msgstr " // Philosophen erstellen" +#: src/exercises/day-4/dining-philosophers.md:61 +msgid "You can use the following `Cargo.toml`:" +msgstr "" -#: src/exercises/day-4/dining-philosophers.md:54 -#, fuzzy -msgid " // Make them think and eat" -msgstr " // Lass sie denken und essen" +#: 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:56 +#: src/exercises/day-4/dining-philosophers.md:65 msgid "" -" // Output their thoughts\n" -"}\n" +"```toml\n" +"[package]\n" +"name = \"dining-philosophers\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" "```" msgstr "" @@ -12638,9 +11607,15 @@ 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:35 +#: 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" @@ -12648,7 +11623,7 @@ msgid "" "```" msgstr "" -#: src/exercises/day-4/link-checker.md:42 +#: 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" @@ -12657,46 +11632,31 @@ 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:45 +#: 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:47 +#: 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;" -msgstr "" - -#: src/exercises/day-4/link-checker.md:53 -#, fuzzy -msgid "" +"use thiserror::Error;\n" +"\n" "#[derive(Error, Debug)]\n" "enum Error {\n" " #[error(\"request error: {0}\")]\n" " ReqwestError(#[from] reqwest::Error),\n" -"}" -msgstr "" -"#[ableiten(Fehler, Debug)]\n" -"Aufzählungsfehler {\n" -" #[error(\"Anforderungsfehler: {0}\")]\n" -" ReqwestError(#[from]reqwest::Error),\n" -"}" - -#: src/exercises/day-4/link-checker.md:59 -msgid "" +"}\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();" -msgstr "" - -#: src/exercises/day-4/link-checker.md:65 -msgid "" +" 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" @@ -12707,20 +11667,11 @@ msgid "" " }\n" " }\n" " }\n" -" }" -msgstr "" - -#: src/exercises/day-4/link-checker.md:77 -#, fuzzy -msgid "" +" }\n" +"\n" " Ok(valid_urls)\n" -"}" -msgstr "" -" Okay (valid_urls)\n" -"}" - -#: src/exercises/day-4/link-checker.md:80 -msgid "" +"}\n" +"\n" "fn main() {\n" " let start_url = Url::parse(\"https://www.google.org\").unwrap();\n" " let response = get(start_url).unwrap();\n" @@ -12732,24 +11683,24 @@ msgid "" "```" msgstr "" -#: src/exercises/day-4/link-checker.md:90 +#: 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:92 +#: src/exercises/day-4/link-checker.md:102 msgid "" "```shell\n" "$ cargo run\n" "```" msgstr "" -#: src/exercises/day-4/link-checker.md:96 +#: src/exercises/day-4/link-checker.md:106 #, fuzzy msgid "## Tasks" msgstr "## Aufgaben" -#: src/exercises/day-4/link-checker.md:98 +#: 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" @@ -12764,18 +11715,7 @@ msgstr "" " `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/exercises/day-4/link-checker.md:104 -#, fuzzy -msgid "" -"[1]: https://docs.rs/reqwest/\n" -"[2]: https://docs.rs/scraper/\n" -"[3]: https://docs.rs/thiserror/" -msgstr "" -"[1]: https://docs.rs/reqwest/\n" -"[2]: https://docs.rs/scraper/\n" -"[3]: https://docs.rs/thiserror/" - -#: src/android.md:1 +#: src/android.md:1 src/bare-metal/android.md:1 #, fuzzy msgid "# Android" msgstr "# Android" @@ -12791,6 +11731,20 @@ msgstr "" "Sie können neue Betriebssystemdienste in Rust schreiben und erweitern\n" "bestehende Dienste." +#: src/android.md:7 +#, fuzzy +msgid "" +"> We will attempt to call Rust from one of your own projects today. So try to\n" +"> find a little corner of your code base where we can move some lines of code to\n" +"> Rust. The fewer dependencies and \"exotic\" types the better. Something that\n" +"> parses some raw bytes would be ideal." +msgstr "" +"> Wir werden heute versuchen, Rust aus einem Ihrer eigenen Projekte anzurufen. Versuchen Sie es " +"also\n" +"> Finden Sie eine kleine Ecke Ihrer Codebasis, in die wir einige Codezeilen verschieben können\n" +"> Rost. Je weniger Abhängigkeiten und \"exotische\" Typen, desto besser. Etwas das\n" +"> parst einige rohe Bytes wäre ideal." + #: src/android/setup.md:1 #, fuzzy msgid "# Setup" @@ -12920,11 +11874,8 @@ msgstr "_hello_rust/src/main.rs_:" #: src/android/build-rules/binary.md:18 msgid "" "```rust\n" -"//! Rust demo." -msgstr "" - -#: src/android/build-rules/binary.md:21 -msgid "" +"//! Rust demo.\n" +"\n" "/// Prints a greeting to standard output.\n" "fn main() {\n" " println!(\"Hello from Rust!\");\n" @@ -12973,12 +11924,6 @@ msgstr "" "* `libtextwrap`, das ist eine Kiste, in der bereits verkauft wird\n" " [`extern/rust/crates/`][crates]." -#: src/android/build-rules/library.md:11 -#, fuzzy -msgid "[crates]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/" -msgstr "" -"[Kisten]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/" - #: src/android/build-rules/library.md:15 msgid "" "```javascript\n" @@ -12991,11 +11936,8 @@ msgid "" " \"libtextwrap\",\n" " ],\n" " prefer_rlib: true,\n" -"}" -msgstr "" - -#: src/android/build-rules/library.md:27 -msgid "" +"}\n" +"\n" "rust_library {\n" " name: \"libgreetings\",\n" " crate_name: \"greetings\",\n" @@ -13007,17 +11949,11 @@ msgstr "" #: src/android/build-rules/library.md:36 msgid "" "```rust,ignore\n" -"//! Rust demo." -msgstr "" - -#: src/android/build-rules/library.md:39 -msgid "" +"//! Rust demo.\n" +"\n" "use greetings::greeting;\n" -"use textwrap::fill;" -msgstr "" - -#: src/android/build-rules/library.md:42 -msgid "" +"use textwrap::fill;\n" +"\n" "/// Prints a greeting to standard output.\n" "fn main() {\n" " println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" @@ -13033,11 +11969,8 @@ msgstr "_hello_rust/src/lib.rs_:" #: src/android/build-rules/library.md:50 msgid "" "```rust,ignore\n" -"//! Greeting library." -msgstr "" - -#: src/android/build-rules/library.md:53 -msgid "" +"//! Greeting library.\n" +"\n" "/// Greet `name`.\n" "pub fn greeting(name: &str) -> String {\n" " format!(\"Hello {name}, it is very nice to meet you!\")\n" @@ -13099,14 +12032,11 @@ msgstr "Sie deklarieren die API Ihres Dienstes über eine AIDL-Schnittstelle:" msgid "*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" msgstr "*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" -#: src/android/aidl/interface.md:7 src/android/aidl/changing.md:6 +#: src/android/aidl/interface.md:7 msgid "" "```java\n" -"package com.example.birthdayservice;" -msgstr "" - -#: src/android/aidl/interface.md:10 -msgid "" +"package com.example.birthdayservice;\n" +"\n" "/** Birthday service interface. */\n" "interface IBirthdayService {\n" " /** Generate a Happy Birthday message. */\n" @@ -13167,22 +12097,13 @@ msgid "" "//! Implementation of the `IBirthdayService` AIDL interface.\n" "use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::" "IBirthdayService;\n" -"use com_example_birthdayservice::binder;" -msgstr "" - -#: src/android/aidl/implementation.md:12 -msgid "" +"use com_example_birthdayservice::binder;\n" +"\n" "/// The `IBirthdayService` implementation.\n" -"pub struct BirthdayService;" -msgstr "" - -#: src/android/aidl/implementation.md:15 -#, fuzzy -msgid "impl binder::Interface for BirthdayService {}" -msgstr "impl binder::Interface für BirthdayService {}" - -#: src/android/aidl/implementation.md:17 -msgid "" +"pub struct BirthdayService;\n" +"\n" +"impl binder::Interface for BirthdayService {}\n" +"\n" "impl IBirthdayService for BirthdayService {\n" " fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result {\n" " Ok(format!(\n" @@ -13235,15 +12156,10 @@ msgid "" "use birthdayservice::BirthdayService;\n" "use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::" "BnBirthdayService;\n" -"use com_example_birthdayservice::binder;" -msgstr "" - -#: src/android/aidl/server.md:13 src/android/aidl/client.md:12 -msgid "const SERVICE_IDENTIFIER: &str = \"birthdayservice\";" -msgstr "" - -#: src/android/aidl/server.md:15 -msgid "" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" "/// Entry point for birthday service.\n" "fn main() {\n" " let birthday_service = BirthdayService;\n" @@ -13349,24 +12265,15 @@ msgid "" "//! Birthday service.\n" "use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::" "IBirthdayService;\n" -"use com_example_birthdayservice::binder;" -msgstr "" - -#: src/android/aidl/client.md:14 -#, fuzzy -msgid "" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" "/// Connect to the BirthdayService.\n" "pub fn connect() -> Result, binder::StatusCode> {\n" " binder::get_interface(SERVICE_IDENTIFIER)\n" -"}" -msgstr "" -"/// Mit dem Geburtstagsdienst verbinden.\n" -"pub fn connect() -> Ergebnis, binder::StatusCode> {\n" -" binder::get_interface(SERVICE_IDENTIFIER)\n" -"}" - -#: src/android/aidl/client.md:19 -msgid "" +"}\n" +"\n" "/// Call the birthday service.\n" "fn main() -> Result<(), binder::Status> {\n" " let name = std::env::args()\n" @@ -13375,11 +12282,8 @@ msgid "" " let years = std::env::args()\n" " .nth(2)\n" " .and_then(|arg| arg.parse::().ok())\n" -" .unwrap_or(42);" -msgstr "" - -#: src/android/aidl/client.md:29 -msgid "" +" .unwrap_or(42);\n" +"\n" " binder::ProcessState::start_thread_pool();\n" " let service = connect().expect(\"Failed to connect to BirthdayService\");\n" " let msg = service.wishHappyBirthday(&name, years)?;\n" @@ -13439,8 +12343,11 @@ msgstr "" "Lassen Sie uns die API um mehr Funktionalität erweitern: Wir möchten, dass Kunden a angeben\n" "Liste der Zeilen für die Geburtstagskarte:" -#: src/android/aidl/changing.md:9 +#: src/android/aidl/changing.md:6 msgid "" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" "/** Birthday service interface. */\n" "interface IBirthdayService {\n" " /** Generate a Happy Birthday message. */\n" @@ -13449,7 +12356,7 @@ msgid "" "```" msgstr "" -#: src/android/logging.md:1 +#: src/android/logging.md:1 src/bare-metal/aps/logging.md:1 #, fuzzy msgid "# Logging" msgstr "# Protokollierung" @@ -13494,15 +12401,10 @@ msgstr "_hello_rust_logs/src/main.rs_:" #: src/android/logging.md:24 msgid "" "```rust,ignore\n" -"//! Rust logging demo." -msgstr "" - -#: src/android/logging.md:27 -msgid "use log::{debug, error, info};" -msgstr "" - -#: src/android/logging.md:29 -msgid "" +"//! Rust logging demo.\n" +"\n" +"use log::{debug, error, info};\n" +"\n" "/// Logs a greeting.\n" "fn main() {\n" " logger::init(\n" @@ -13604,11 +12506,8 @@ msgid "" "```rust\n" "extern \"C\" {\n" " fn abs(x: i32) -> i32;\n" -"}" -msgstr "" - -#: src/android/interoperability/with-c.md:13 -msgid "" +"}\n" +"\n" "fn main() {\n" " let x = -42;\n" " let abs_x = unsafe { abs(x) };\n" @@ -13670,11 +12569,8 @@ msgid "" "typedef struct card {\n" " const char* name;\n" " int years;\n" -"} card;" -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:16 -msgid "" +"} card;\n" +"\n" "void print_card(const card* card);\n" "```" msgstr "" @@ -13688,11 +12584,8 @@ msgstr "_interoperability/bindgen/libbirthday.c_:" msgid "" "```c\n" "#include \n" -"#include \"libbirthday.h\"" -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:25 -msgid "" +"#include \"libbirthday.h\"\n" +"\n" "void print_card(const card* card) {\n" " printf(\"+--------------\\n\");\n" " printf(\"| Happy Birthday %s!\\n\", card->name);\n" @@ -13788,15 +12681,10 @@ msgstr "_interoperability/bindgen/main.rs_:" #: src/android/interoperability/with-c/bindgen.md:81 msgid "" "```rust,compile_fail\n" -"//! Bindgen demo." -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:84 -msgid "use birthday_bindgen::{card, print_card};" -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:86 -msgid "" +"//! Bindgen demo.\n" +"\n" +"use birthday_bindgen::{card, print_card};\n" +"\n" "fn main() {\n" " let name = std::ffi::CString::new(\"Peter\").unwrap();\n" " let card = card {\n" @@ -13867,15 +12755,10 @@ msgstr "_interoperability/rust/libanalyze/analyze.rs_" msgid "" "```rust,editable\n" "//! Rust FFI demo.\n" -"#![deny(improper_ctypes_definitions)]" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:11 -msgid "use std::os::raw::c_int;" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:13 -msgid "" +"#![deny(improper_ctypes_definitions)]\n" +"\n" +"use std::os::raw::c_int;\n" +"\n" "/// Analyze the numbers.\n" "#[no_mangle]\n" "pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" @@ -13897,18 +12780,12 @@ msgstr "_interoperability/rust/libanalyze/analyze.h_" msgid "" "```c\n" "#ifndef ANALYSE_H\n" -"#define ANALYSE_H" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:30 -msgid "" +"#define ANALYSE_H\n" +"\n" "extern \"C\" {\n" "void analyze_numbers(int x, int y);\n" -"}" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:34 -msgid "" +"}\n" +"\n" "#endif\n" "```" msgstr "" @@ -13943,11 +12820,8 @@ msgstr "_interoperability/rust/analyze/main.c_" #: src/android/interoperability/with-c/rust.md:52 msgid "" "```c\n" -"#include \"analyze.h\"" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:55 -msgid "" +"#include \"analyze.h\"\n" +"\n" "int main() {\n" " analyze_numbers(10, 20);\n" " analyze_numbers(123, 123);\n" @@ -14022,15 +12896,6 @@ msgstr "" msgid "See the [CXX tutorial][2] for an full example of using this." msgstr "Ein vollständiges Beispiel für die Verwendung finden Sie im [CXX-Tutorial] [2]." -#: src/android/interoperability/cpp.md:12 -#, fuzzy -msgid "" -"[1]: https://cxx.rs/\n" -"[2]: https://cxx.rs/tutorial.html" -msgstr "" -"[1]: https://cxx.rs/\n" -"[2]: https://cxx.rs/tutorial.html" - #: src/android/interoperability/java.md:1 #, fuzzy msgid "# Interoperability with Java" @@ -14060,18 +12925,12 @@ msgstr "_interoperability/java/src/lib.rs_:" #: src/android/interoperability/java.md:11 msgid "" "```rust,compile_fail\n" -"//! Rust <-> Java FFI demo." -msgstr "" - -#: src/android/interoperability/java.md:14 -msgid "" +"//! Rust <-> Java FFI demo.\n" +"\n" "use jni::objects::{JClass, JString};\n" "use jni::sys::jstring;\n" -"use jni::JNIEnv;" -msgstr "" - -#: src/android/interoperability/java.md:18 -msgid "" +"use jni::JNIEnv;\n" +"\n" "/// HelloWorld::hello method implementation.\n" "#[no_mangle]\n" "pub extern \"system\" fn Java_HelloWorld_hello(\n" @@ -14118,18 +12977,12 @@ msgstr "_interoperability/java/HelloWorld.java_:" msgid "" "```java\n" "class HelloWorld {\n" -" private static native String hello(String name);" -msgstr "" - -#: src/android/interoperability/java.md:51 -msgid "" +" private static native String hello(String name);\n" +"\n" " static {\n" " System.loadLibrary(\"hello_jni\");\n" -" }" -msgstr "" - -#: src/android/interoperability/java.md:55 -msgid "" +" }\n" +"\n" " public static void main(String[] args) {\n" " String output = HelloWorld.hello(\"Alice\");\n" " System.out.println(output);\n" @@ -14164,7 +13017,7 @@ msgid "" "```" msgstr "" -#: src/exercises/day-4/afternoon.md:3 +#: src/exercises/day-4/android.md:3 #, fuzzy msgid "" "For the last exercise, we will look at one of the projects you work with. Let us\n" @@ -14174,17 +13027,15 @@ msgstr "" "uns\n" "gruppiert euch und macht das gemeinsam. Einige Vorschläge:" -#: src/exercises/day-4/afternoon.md:6 +#: src/exercises/day-4/android.md:6 #, fuzzy -msgid "* Call your AIDL service with a client written in Rust." -msgstr "* Rufen Sie Ihren AIDL-Service mit einem in Rust geschriebenen Client an." - -#: src/exercises/day-4/afternoon.md:8 -#, fuzzy -msgid "* Move a function from your project to Rust and call it." +msgid "" +"* Call your AIDL service with a client written in Rust.\n" +"\n" +"* 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/afternoon.md:12 +#: src/exercises/day-4/android.md:12 #, fuzzy msgid "" "No solution is provided here since this is open-ended: it relies on someone in\n" @@ -14193,1618 +13044,8971 @@ 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/thanks.md:1 +#: src/async.md:1 #, fuzzy -msgid "# Thanks!" -msgstr "# Danke!" +msgid "# Async Rust" +msgstr "# Warum Rost?" -#: src/thanks.md:3 -#, fuzzy +#: src/async.md:3 msgid "" -"_Thank you for taking Comprehensive Rust 🦀!_ We hope you enjoyed it and that it\n" -"was useful." +"\"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 "" -"_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 +#: src/async.md:10 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." +"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 "" -"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/async.md:14 +msgid "" +"Futures are polled by an async runtime, and several different runtimes are\n" +"available." +msgstr "" -#: src/other-resources.md:3 +#: src/async.md:17 #, fuzzy +msgid "## Comparisons" +msgstr "# Vergleich" + +#: src/async.md:19 msgid "" -"The Rust community has created a wealth of high-quality and free resources\n" -"online." +" * 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 "" -"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/async/async-await.md:1 +msgid "# `async`/`await`" +msgstr "" -#: 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/async/async-await.md:3 +msgid "At a high level, async Rust code looks very much like \"normal\" sequential code:" +msgstr "" -#: src/other-resources.md:10 -#, fuzzy +#: src/async/async-await.md:5 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." +"```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 "" -"* [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/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/other-resources.md:24 -#, fuzzy +#: src/async/futures.md:3 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." +"[`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 "" -"* [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/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/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/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/other-resources.md:37 -#, fuzzy +#: src/async/futures.md:27 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." +"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 "" -"* [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:59 -#, fuzzy +#: src/async/futures.md:32 msgid "" -"Please see the [Little Book of Rust Books](https://lborb.github.io/book/) for\n" -"even more Rust books." +"* 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 "" -"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 +#: src/async/runtimes.md:1 #, fuzzy -msgid "# Credits" -msgstr "# Credits" +msgid "# Runtimes and Tasks" +msgstr "# Laufzeitgarantien" -#: src/credits.md:3 -#, fuzzy +#: src/async/runtimes.md:3 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." +"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 "" -"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 +#: src/async/runtimes.md:7 msgid "" -"The material of Comprehensive Rust is licensed under the terms of the Apache 2.0\n" -"license, please see [`LICENSE`](../LICENSE) for details." +" * [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 "" -"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 +#: src/async/runtimes.md:14 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." +"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 "" -"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 +#: src/async/runtimes.md:20 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." +"* 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 "" -"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/async/runtimes/tokio.md:1 +msgid "# Tokio" +msgstr "" -#: 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." +#: src/async/runtimes/tokio.md:4 +msgid "Tokio provides: " 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" -msgstr "# Lösungen" +#: 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/exercises/solutions.md:3 -#, fuzzy -msgid "You will find solutions to the exercises on the following pages." -msgstr "Auf den folgenden Seiten finden Sie Lösungen zu den Aufgaben." +#: 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/exercises/solutions.md:5 -#, fuzzy +#: src/async/runtimes/tokio.md:33 msgid "" -"Feel free to ask questions about the solutions [on\n" -"GitHub](https://github.com/google/comprehensive-rust/discussions). Let us know\n" -"if you have a different or better solution than what is presented here." +"* 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 "" -"Fühlen Sie sich frei, Fragen zu den Lösungen zu stellen [on\n" -"GitHub](https://github.com/google/comprehensive-rust/discussions). Lass uns wissen\n" -"wenn Sie eine andere oder bessere Lösung als die hier vorgestellte haben." -#: src/exercises/solutions.md:10 -#, fuzzy +#: src/async/runtimes/tokio.md:39 +msgid "**Further exploration:**" +msgstr "" + +#: src/async/runtimes/tokio.md:41 msgid "" -"> **Note:** Please ignore the `// ANCHOR: label` and `// ANCHOR_END: label`\n" -"> comments you see in the solutions. They are there to make it possible to\n" -"> re-use parts of the solutions as the exercises." +"* 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 "" -"> **Hinweis:** Bitte ignorieren Sie `// ANCHOR: label` und `// ANCHOR_END: label`\n" -"> Kommentare, die Sie in den Lösungen sehen. Sie sind da, um es zu ermöglichen\n" -"> Teile der Lösungen als Aufgaben wiederverwenden." -#: src/exercises/day-1/solutions-morning.md:1 +#: src/async/tasks.md:1 #, fuzzy -msgid "# Day 1 Morning Exercises" -msgstr "# Tag 1 Morgengymnastik" +msgid "# Tasks" +msgstr "## Aufgaben" -#: src/exercises/day-1/solutions-morning.md:3 -#, fuzzy -msgid "## Arrays and `for` Loops" -msgstr "## Arrays und „for“-Schleifen" +#: 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/exercises/day-1/solutions-morning.md:5 -#, fuzzy -msgid "([back to exercise](for-loops.md))" -msgstr "([zurück zur Übung](for-loops.md))" +#: 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/exercises/day-1/solutions-morning.md:7 src/exercises/day-1/solutions-afternoon.md:7 -#: src/exercises/day-2/solutions-morning.md:7 src/exercises/day-2/solutions-afternoon.md:7 -#: src/exercises/day-2/solutions-afternoon.md:102 src/exercises/day-3/solutions-morning.md:7 -#: src/exercises/day-3/solutions-afternoon.md:7 src/exercises/day-4/solutions-morning.md:7 +#: src/async/tasks.md:11 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." -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:22 -msgid "" -"// ANCHOR: transpose\n" -"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" -" // ANCHOR_END: transpose\n" -" let mut result = [[0; 3]; 3];\n" -" for i in 0..3 {\n" -" for j in 0..3 {\n" -" result[j][i] = matrix[i][j];\n" -" }\n" +"```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" -" return result;\n" -"}" +"}\n" +"```" msgstr "" -#: src/exercises/day-1/solutions-morning.md:34 -msgid "" -"// ANCHOR: pretty_print\n" -"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" -" // ANCHOR_END: pretty_print\n" -" for row in matrix {\n" -" println!(\"{row:?}\");\n" -" }\n" -"}" +#: 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/exercises/day-1/solutions-morning.md:42 +#: src/async/tasks.md:55 msgid "" -"// ANCHOR: tests\n" -"#[test]\n" -"fn test_transpose() {\n" -" let matrix = [\n" -" [101, 102, 103], //\n" -" [201, 202, 203],\n" -" [301, 302, 303],\n" -" ];\n" -" let transposed = transpose(matrix);\n" -" assert_eq!(\n" -" transposed,\n" -" [\n" -" [101, 201, 301], //\n" -" [102, 202, 302],\n" -" [103, 203, 303],\n" -" ]\n" -" );\n" -"}\n" -"// ANCHOR_END: tests" +"* 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/exercises/day-1/solutions-morning.md:62 -msgid "" -"// ANCHOR: main\n" -"fn main() {\n" -" let matrix = [\n" -" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" -" [201, 202, 203],\n" -" [301, 302, 303],\n" -" ];" +#: 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/exercises/day-1/solutions-morning.md:73 +#: src/async/channels.md:5 msgid "" -" let transposed = transpose(matrix);\n" -" println!(\"transposed:\");\n" -" pretty_print(&transposed);\n" +"```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" -"```\n" -"### Bonus question" +"```" msgstr "" -#: src/exercises/day-1/solutions-morning.md:80 -#, fuzzy +#: src/async/channels.md:35 msgid "" -"It honestly doesn't work so well. It might seem that we could use a slice-of-slices (`&[&[i32]]`) " -"as the input type to transpose and thus make our function handle any size of matrix. However, this " -"quickly breaks down: the return type cannot be `&[&[i32]]` since it needs to own the data you " -"return." +"* 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 "" -"Es funktioniert ehrlich gesagt nicht so gut. Es scheint, als könnten wir ein Slice-of-Slices " -"(`&[&[i32]]`) als Eingabetyp für die Transponierung verwenden und unsere Funktion so dazu bringen, " -"jede Matrixgröße zu handhaben. Dies bricht jedoch schnell zusammen: Der Rückgabetyp kann nicht " -"`&[&[i32]]` sein, da er die von Ihnen zurückgegebenen Daten besitzen muss." -#: src/exercises/day-1/solutions-morning.md:82 +#: src/async/control-flow.md:1 #, fuzzy +msgid "# Futures Control Flow" +msgstr "# Kontrollfluss" + +#: src/async/control-flow.md:3 msgid "" -"You can attempt to use something like `Vec>`, but this doesn't work very well either: " -"it's hard to convert from `Vec>` to `&[&[i32]]` so now you cannot easily use " -"`pretty_print` either." +"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 "" -"Sie können versuchen, so etwas wie `Vec>` zu verwenden, aber das funktioniert auch nicht " -"sehr gut: Es ist schwierig, `Vec>` in `&[&[i32]] umzuwandeln. ` also kannst du jetzt auch " -"`pretty_print` nicht einfach verwenden." -#: src/exercises/day-1/solutions-morning.md:84 -#, fuzzy +#: src/async/control-flow.md:6 msgid "" -"In addition, the type itself would not enforce that the child slices are of the same length, so " -"such variable could contain an invalid matrix." +"- [Join](control-flow/join.md)\n" +"- [Select](control-flow/select.md)" msgstr "" -"Außerdem würde der Typ selbst nicht erzwingen, dass die untergeordneten Slices dieselbe Länge " -"haben, sodass eine solche Variable eine ungültige Matrix enthalten könnte." - -#: src/exercises/day-1/solutions-afternoon.md:1 -#, fuzzy -msgid "# Day 1 Afternoon Exercises" -msgstr "# Tag 1 Nachmittagsübungen" -#: src/exercises/day-1/solutions-afternoon.md:3 -#, fuzzy -msgid "## Designing a Library" -msgstr "## Entwerfen einer Bibliothek" - -#: src/exercises/day-1/solutions-afternoon.md:5 -#, fuzzy -msgid "([back to exercise](book-library.md))" -msgstr "([zurück zur Übung](book-library.md))" +#: src/async/control-flow/join.md:1 +msgid "# Join" +msgstr "" -#: src/exercises/day-1/solutions-afternoon.md:22 -#, fuzzy +#: src/async/control-flow/join.md:3 msgid "" -"// ANCHOR: setup\n" -"struct Library {\n" -" books: Vec,\n" -"}" +"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 "" -"// ANKER: einrichten\n" -"Struktur Bibliothek {\n" -" Bücher: Vec,\n" -"}" -#: src/exercises/day-1/solutions-afternoon.md:42 -#, fuzzy +#: src/async/control-flow/join.md:7 msgid "" -"// 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" +"```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" -"// ANCHOR_END: setup" -msgstr "" -"// Dadurch ist es möglich, Buchwerte mit {} zu drucken.\n" -"impl std::fmt::Anzeige für Buch {\n" -" fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n" -" schreibe!(f, \"{} ({})\", self.title, self.year)\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" -"// ANCHOR_END: Einrichtung" +"```" +msgstr "" -#: src/exercises/day-1/solutions-afternoon.md:50 -#, fuzzy +#: src/async/control-flow/join.md:38 msgid "" -"// ANCHOR: Library_new\n" -"impl Library {\n" -" fn new() -> Library {\n" -" // ANCHOR_END: Library_new\n" -" Library { books: Vec::new() }\n" -" }" +"* 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 "" -"// ANKER: Bibliothek_neu\n" -"impl-Bibliothek {\n" -" fn new() -> Bibliothek {\n" -" // ANCHOR_END: Bibliothek_neu\n" -" Bibliothek { Bücher: Vec::new() }\n" -" }" -#: src/exercises/day-1/solutions-afternoon.md:57 +#: src/async/control-flow/select.md:1 #, fuzzy +msgid "# Select" +msgstr "# Aufstellen" + +#: src/async/control-flow/select.md:3 msgid "" -" // ANCHOR: Library_len\n" -" //fn len(self) -> usize {\n" -" // unimplemented!()\n" -" //}\n" -" // ANCHOR_END: Library_len\n" -" fn len(&self) -> usize {\n" -" self.books.len()\n" -" }" +"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 "" -" // ANKER: Library_len\n" -" //fn len(self) -> verwenden {\n" -" // nicht implementiert!()\n" -" //}\n" -" // ANCHOR_END: Library_len\n" -" fn len(&self) -> verwenden {\n" -" self.books.len()\n" -" }" -#: src/exercises/day-1/solutions-afternoon.md:66 -#, fuzzy +#: src/async/control-flow/select.md:8 msgid "" -" // ANCHOR: Library_is_empty\n" -" //fn is_empty(self) -> bool {\n" -" // unimplemented!()\n" -" //}\n" -" // ANCHOR_END: Library_is_empty\n" -" fn is_empty(&self) -> bool {\n" -" self.books.is_empty()\n" -" }" +"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 "" -" // ANKER: Bibliothek_ist_leer\n" -" //fn is_empty(self) -> bool {\n" -" // nicht implementiert!()\n" -" //}\n" -" // ANCHOR_END: Bibliothek_ist_leer\n" -" fn is_empty(&self) -> bool {\n" -" self.books.is_empty()\n" -" }" -#: src/exercises/day-1/solutions-afternoon.md:75 -#, fuzzy +#: src/async/control-flow/select.md:12 msgid "" -" // ANCHOR: Library_add_book\n" -" //fn add_book(self, book: Book) {\n" -" // unimplemented!()\n" -" //}\n" -" // ANCHOR_END: Library_add_book\n" -" fn add_book(&mut self, book: Book) {\n" -" self.books.push(book)\n" -" }" +"```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 "" -" // ANKER: Library_add_book\n" -" //fn add_book(selbst, Buch: Buch) {\n" -" // nicht implementiert!()\n" -" //}\n" -" // ANCHOR_END: Library_add_book\n" -" fn add_book(&mut self, book: Buch) {\n" -" self.books.push(Buch)\n" -" }" -#: src/exercises/day-1/solutions-afternoon.md:84 +#: src/async/control-flow/select.md:61 msgid "" -" // ANCHOR: Library_print_books\n" -" //fn print_books(self) {\n" -" // unimplemented!()\n" -" //}\n" -" // ANCHOR_END: Library_print_books\n" -" fn print_books(&self) {\n" -" for book in &self.books {\n" -" println!(\"{}\", book);\n" -" }\n" -" }" +"* 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/exercises/day-1/solutions-afternoon.md:95 -#, fuzzy -msgid "" -" // ANCHOR: Library_oldest_book\n" -" //fn oldest_book(self) -> Option<&Book> {\n" -" // unimplemented!()\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" -" }\n" -"}" +#: src/async/pitfalls.md:1 +msgid "# Pitfalls of async/await" msgstr "" -" // ANKER: Library_oldest_book\n" -" //fn ältestes_buch(selbst) -> Option<&Buch> {\n" -" // nicht implementiert!()\n" -" //}\n" -" // ANCHOR_END: Bibliothek_ältestes_Buch\n" -" fn ältestes_buch(&self) -> Option<&Buch> {\n" -" self.books.iter().min_by_key(|Buch| Buch.Jahr)\n" -" }\n" -"}" -#: src/exercises/day-1/solutions-afternoon.md:105 +#: src/async/pitfalls.md:3 msgid "" -"// ANCHOR: main\n" -"// This shows the desired behavior. Uncomment the code below and\n" -"// implement the missing methods. You will need to update the\n" -"// method signatures, including the \"self\" parameter! You may\n" -"// also need to update the variable bindings within main.\n" -"fn main() {\n" -" let library = Library::new();" +"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/exercises/day-1/solutions-afternoon.md:113 +#: src/async/pitfalls.md:5 msgid "" -" //println!(\"Our 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" -" //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" -" //}\n" -" //\n" -" //println!(\"Our library has {} books\", library.len());\n" -"}\n" -"// ANCHOR_END: main" +"- [Blocking the Executor](pitfalls/blocking-executor.md)\n" +"- [Pin](pitfalls/pin.md)\n" +"- [Async Traits](pitfall/async-traits.md)" msgstr "" -#: src/exercises/day-1/solutions-afternoon.md:129 -msgid "" -"#[test]\n" -"fn test_library_len() {\n" -" let mut library = Library::new();\n" -" assert_eq!(library.len(), 0);\n" -" assert!(library.is_empty());" +#: src/async/pitfalls/blocking-executor.md:1 +msgid "# Blocking the executor" msgstr "" -#: src/exercises/day-1/solutions-afternoon.md:135 +#: src/async/pitfalls/blocking-executor.md:3 msgid "" -" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" -" assert_eq!(library.len(), 2);\n" -" assert!(!library.is_empty());\n" -"}" +"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/exercises/day-1/solutions-afternoon.md:141 +#: src/async/pitfalls/blocking-executor.md:7 msgid "" -"#[test]\n" -"fn test_library_is_empty() {\n" -" let mut library = Library::new();\n" -" assert!(library.is_empty());" +"```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/exercises/day-1/solutions-afternoon.md:146 +#: src/async/pitfalls/blocking-executor.md:29 msgid "" -" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" assert!(!library.is_empty());\n" -"}" +"* 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/exercises/day-1/solutions-afternoon.md:150 +#: src/async/pitfalls/pin.md:3 msgid "" -"#[test]\n" -"fn test_library_print_books() {\n" -" let mut library = Library::new();\n" -" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" -" // We could try and capture stdout, but let us just call the\n" -" // method to start with.\n" -" library.print_books();\n" -"}" +"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/exercises/day-1/solutions-afternoon.md:160 +#: src/async/pitfalls/pin.md:8 msgid "" -"#[test]\n" -"fn test_library_oldest_book() {\n" -" let mut library = Library::new();\n" -" assert!(library.oldest_book().is_none());" +"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/exercises/day-1/solutions-afternoon.md:165 +#: src/async/pitfalls/pin.md:12 msgid "" -" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" assert_eq!(\n" -" library.oldest_book().map(|b| b.title.as_str()),\n" -" Some(\"Lord of the Rings\")\n" -" );" +"```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/exercises/day-1/solutions-afternoon.md:171 +#: 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 "" -" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" -" assert_eq!(\n" -" library.oldest_book().map(|b| b.title.as_str()),\n" -" Some(\"Alice's Adventures in Wonderland\")\n" -" );\n" +"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/exercises/day-2/solutions-morning.md:1 +#: src/async/pitfalls/async-traits.md:49 #, fuzzy -msgid "# Day 2 Morning Exercises" -msgstr "# Tag 2 Morgengymnastik" +msgid "
" +msgstr "
" -#: src/exercises/day-2/solutions-morning.md:3 -#, fuzzy -msgid "## Points and Polygons" -msgstr "## Punkte und Polygone" +#: 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-2/solutions-morning.md:5 -#, fuzzy -msgid "([back to exercise](points-polygons.md))" -msgstr "([zurück zur Übung](points-polygons.md))" +#: src/exercises/day-4/elevator.md:1 +msgid "# Elevator Operation" +msgstr "" -#: src/exercises/day-2/solutions-morning.md:22 -#, fuzzy +#: src/exercises/day-4/elevator.md:3 msgid "" -"#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" -"// ANCHOR: Point\n" -"pub struct Point {\n" -" // ANCHOR_END: Point\n" -" x: i32,\n" -" y: i32,\n" -"}" +"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 "" -"#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" -"// Ankerpunkt\n" -"pub struct Punkt {\n" -" // ANCHOR_END: Punkt\n" -" x: i32,\n" -" y: i32,\n" -"}" -#: src/exercises/day-2/solutions-morning.md:30 -#, fuzzy +#: src/exercises/day-4/elevator.md:8 msgid "" -"// ANCHOR: Point-impl\n" -"impl Point {\n" -" // ANCHOR_END: Point-impl\n" -" pub fn new(x: i32, y: i32) -> Point {\n" -" Point { x, y }\n" -" }" +"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 "" -"// ANCHOR: Punkt-impl\n" -"impl Punkt {\n" -" // ANCHOR_END: Punkt-impl\n" -" pub fn neu(x: i32, y: i32) -> Punkt {\n" -" Punkt { x, y }\n" -" }" -#: src/exercises/day-2/solutions-morning.md:37 +#: src/exercises/day-4/elevator.md:12 #, fuzzy +msgid "## Getting Started" +msgstr "# Destrukturierende Strukturen" + +#: src/exercises/day-4/elevator.md:14 msgid "" -" pub fn magnitude(self) -> f64 {\n" -" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" -" }" +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the " +"`elevator`\n" +"directory for the following files." msgstr "" -" Pub fn Magnitude (selbst) -> f64 {\n" -" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" -" }" -#: src/exercises/day-2/solutions-morning.md:41 +#: 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 "" -" pub fn dist(self, other: Point) -> f64 {\n" -" (self - other).magnitude()\n" +"```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 "" -" pub fn dist(self, other: Point) -> f64 {\n" -" (selbst - andere).magnitude()\n" -" }\n" -"}" -#: src/exercises/day-2/solutions-morning.md:49 +#: 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 "" -" fn add(self, other: Self) -> Self::Output {\n" -" Self {\n" -" x: self.x + other.x,\n" -" y: self.y + other.y,\n" +"```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" -"}" -msgstr "" -" fn add(self, other: Self) -> Self::Output {\n" -" Selbst {\n" -" x: selbst.x + andere.x,\n" -" y: self.y + other.y,\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" -"}" - -#: src/exercises/day-2/solutions-morning.md:57 -msgid "" -"impl std::ops::Sub for Point {\n" -" type Output = Self;" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:60 -#, fuzzy -msgid "" -" fn sub(self, other: Self) -> Self::Output {\n" -" Self {\n" -" x: self.x - other.x,\n" -" y: self.y - other.y,\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" -"}" -msgstr "" -" fn sub(self, other: Self) -> Self::Output {\n" -" Selbst {\n" -" x: self.x - other.x,\n" -" y: self.y - other.y,\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" -"}" - -#: src/exercises/day-2/solutions-morning.md:68 -#, fuzzy -msgid "" -"// ANCHOR: Polygon\n" -"pub struct Polygon {\n" -" // ANCHOR_END: Polygon\n" -" points: Vec,\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 "" -"// ANKER: Vieleck\n" -"pub struct Polygon {\n" -" // ANCHOR_END: Vieleck\n" -" Punkte: Vec,\n" -"}" -#: src/exercises/day-2/solutions-morning.md:74 +#: src/exercises/day-4/elevator.md:288 #, fuzzy -msgid "" -"// ANCHOR: Polygon-impl\n" -"impl Polygon {\n" -" // ANCHOR_END: Polygon-impl\n" -" pub fn new() -> Polygon {\n" -" Polygon { points: Vec::new() }\n" -" }" -msgstr "" -"// ANCHOR: Polygon-Impl\n" -"impl Polygon {\n" -" // ANCHOR_END: Polygon-Impl\n" -" pub fn new() -> Polygon {\n" -" Vieleck { Punkte: Vec::new() }\n" -" }" +msgid "`src/driver.rs`:" +msgstr "_hello_rust/src/main.rs_:" -#: src/exercises/day-2/solutions-morning.md:81 -msgid "" -" pub fn add_point(&mut self, point: Point) {\n" -" self.points.push(point);\n" -" }" +#: src/exercises/day-4/elevator.md:290 +msgid "" msgstr "" -#: src/exercises/day-2/solutions-morning.md:85 -#, fuzzy +#: src/exercises/day-4/elevator.md:292 msgid "" -" pub fn left_most_point(&self) -> Option {\n" -" self.points.iter().min_by_key(|p| p.x).copied()\n" -" }" +"```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 "" -" pub fn left_most_point(&self) -> Option {\n" -" self.points.iter().min_by_key(|p| p.x).kopiert()\n" -" }" -#: src/exercises/day-2/solutions-morning.md:89 +#: src/exercises/day-4/elevator.md:330 #, fuzzy -msgid "" -" pub fn iter(&self) -> impl Iterator {\n" -" self.points.iter()\n" -" }" -msgstr "" -" pub fn iter(&self) -> impl Iterator {\n" -" self.points.iter()\n" -" }" +msgid "`src/controller.rs`:" +msgstr "_hello_rust/src/main.rs_:" -#: src/exercises/day-2/solutions-morning.md:93 -msgid "" -" pub fn length(&self) -> f64 {\n" -" if self.points.is_empty() {\n" -" return 0.0;\n" -" }" +#: src/exercises/day-4/elevator.md:332 +msgid "" msgstr "" -#: src/exercises/day-2/solutions-morning.md:98 +#: src/exercises/day-4/elevator.md:334 msgid "" -" let mut result = 0.0;\n" -" let mut last_point = self.points[0];\n" -" for point in &self.points[1..] {\n" -" result += last_point.dist(*point);\n" -" last_point = *point;\n" +"```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" -" result += last_point.dist(self.points[0]);\n" -" result\n" " }\n" -"}" +"}\n" +"```" msgstr "" -#: src/exercises/day-2/solutions-morning.md:109 -#, fuzzy -msgid "" -"// ANCHOR: Circle\n" -"pub struct Circle {\n" -" // ANCHOR_END: Circle\n" -" center: Point,\n" -" radius: i32,\n" -"}" +#: 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 "" -"// ANKER: Kreis\n" -"pub struct Kreis {\n" -" // ANCHOR_END: Kreis\n" -" Mittelpunkt,\n" -" Radius: i32,\n" -"}" -#: src/exercises/day-2/solutions-morning.md:116 -#, fuzzy +#: src/exercises/day-4/elevator.md:369 msgid "" -"// ANCHOR: Circle-impl\n" -"impl Circle {\n" -" // ANCHOR_END: Circle-impl\n" -" pub fn new(center: Point, radius: i32) -> Circle {\n" -" Circle { center, radius }\n" -" }" +"```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 "" -"// ANCHOR: Kreis-Impl\n" -"impl Kreis {\n" -" // ANCHOR_END: Kreis-Impl\n" -" pub fn neu (Zentrum: Punkt, Radius: i32) -> Kreis {\n" -" Kreis { Mittelpunkt, Radius }\n" -" }" -#: src/exercises/day-2/solutions-morning.md:123 +#: src/exercises/day-4/elevator.md:381 #, fuzzy -msgid "" -" pub fn circumference(&self) -> f64 {\n" -" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" -" }" -msgstr "" -" pub fn Umfang(&self) -> f64 {\n" -" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" -" }" +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-2/solutions-morning.md:127 +#: src/exercises/day-4/elevator.md:383 #, fuzzy -msgid "" -" pub fn dist(&self, other: &Self) -> f64 {\n" -" self.center.dist(other.center)\n" -" }\n" -"}" -msgstr "" -" pub fn dist(&selbst, andere: &selbst) -> f64 {\n" -" self.center.dist(anderes.center)\n" -" }\n" -"}" +msgid "## Exercises" +msgstr "# Übungen" -#: src/exercises/day-2/solutions-morning.md:132 -#, fuzzy -msgid "" -"// ANCHOR: Shape\n" -"pub enum Shape {\n" -" Polygon(Polygon),\n" -" Circle(Circle),\n" -"}\n" -"// ANCHOR_END: Shape" +#: 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 "" -"// ANKER: Form\n" -"Pub-Aufzählung Form {\n" -" Vieleck(Vieleck),\n" -" Kreis (Kreis),\n" -"}\n" -"// ANCHOR_END: Form" -#: src/exercises/day-2/solutions-morning.md:139 +#: 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 +#, fuzzy +msgid "# Welcome to Bare Metal Rust" +msgstr "# Willkommen bei Comprehensive Rust 🦀" + +#: src/welcome-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" +"basics of Rust (perhaps from completing the Comprehensive Rust course), and ideally also have " +"some\n" +"experience with bare-metal programming in some other language such as C." +msgstr "" + +#: src/welcome-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 +msgid "" +"- What is `no_std` Rust?\n" +"- Writing firmware for microcontrollers.\n" +"- Writing bootloader / kernel code for application processors.\n" +"- Some useful crates for bare-metal Rust development." +msgstr "" + +#: src/welcome-bare-metal.md:15 +msgid "" +"For the microcontroller part of the course we will use the [BBC micro:bit](https://microbit.org/) " +"v2\n" +"as an example. It's a [development board](https://tech.microbit.org/hardware/) based on the " +"Nordic\n" +"nRF51822 microcontroller with some LEDs and buttons, an I2C-connected accelerometer and compass, " +"and\n" +"an on-board SWD debugger." +msgstr "" + +#: src/welcome-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 +msgid "" +"```bash\n" +"sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom pkg-config qemu-system-" +"arm\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" +msgstr "" + +#: src/welcome-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 +msgid "" +"```bash\n" +"echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", GROUP=\"plugdev\"' |\\\n" +" sudo tee /etc/udev/rules.d/50-microbit.rules\n" +"sudo udevadm control --reload-rules\n" +"```" +msgstr "" + +#: src/welcome-bare-metal.md:38 +msgid "On MacOS:" +msgstr "" + +#: src/welcome-bare-metal.md:40 +msgid "" +"```bash\n" +"xcode-select --install\n" +"brew install gdb picocom qemu\n" +"brew install --cask gcc-aarch64-embedded\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" +msgstr "" + +#: src/bare-metal/no_std.md:1 +msgid "# `no_std`" +msgstr "" + +#: src/bare-metal/no_std.md:3 +msgid "" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"
" +msgstr "" + +#: src/bare-metal/no_std.md:7 +msgid "`core`" +msgstr "" + +#: src/bare-metal/no_std.md:9 src/bare-metal/no_std.md:14 +msgid "" +"" +msgstr "" + +#: src/bare-metal/no_std.md:12 +msgid "`alloc`" +msgstr "" + +#: src/bare-metal/no_std.md:17 +msgid "`std`" +msgstr "" + +#: src/bare-metal/no_std.md:19 +msgid "" +"
" +msgstr "" + +#: src/bare-metal/no_std.md:24 +msgid "" +"* Slices, `&str`, `CStr`\n" +"* `NonZeroU8`...\n" +"* `Option`, `Result`\n" +"* `Display`, `Debug`, `write!`...\n" +"* `Iterator`\n" +"* `panic!`, `assert_eq!`...\n" +"* `NonNull` and all the usual pointer-related functions\n" +"* `Future` and `async`/`await`\n" +"* `fence`, `AtomicBool`, `AtomicPtr`, `AtomicU32`...\n" +"* `Duration`" +msgstr "" + +#: src/bare-metal/no_std.md:35 src/bare-metal/no_std.md:42 +msgid "" +"" +msgstr "" + +#: src/bare-metal/no_std.md:38 +msgid "" +"* `Box`, `Cow`, `Arc`, `Rc`\n" +"* `Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque`\n" +"* `String`, `CString`, `format!`" +msgstr "" + +#: src/bare-metal/no_std.md:45 +msgid "" +"* `Error`\n" +"* `HashMap`\n" +"* `Mutex`, `Condvar`, `Barrier`, `Once`, `RwLock`, `mpsc`\n" +"* `File` and the rest of `fs`\n" +"* `println!`, `Read`, `Write`, `Stdin`, `Stdout` and the rest of `io`\n" +"* `Path`, `OsString`\n" +"* `net`\n" +"* `Command`, `Child`, `ExitCode`\n" +"* `spawn`, `sleep` and the rest of `thread`\n" +"* `SystemTime`, `Instant`" +msgstr "" + +#: src/bare-metal/no_std.md:56 +msgid "" +"
\n" +"\n" +"
" +msgstr "" + +#: src/bare-metal/no_std.md:62 +msgid "" +"* `HashMap` depends on RNG.\n" +"* `std` re-exports the contents of both `core` and `alloc`." +msgstr "" + +#: src/bare-metal/minimal.md:1 +msgid "# A minimal `no_std` program" +msgstr "" + +#: src/bare-metal/minimal.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::panic::PanicInfo;\n" +"\n" +"#[panic_handler]\n" +"fn panic(_panic: &PanicInfo) -> ! {\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/minimal.md:17 +msgid "" +"* This will compile to an empty binary.\n" +"* `std` provides a panic handler; without it we must provide our own.\n" +"* It can also be provided by another crate, such as `panic-halt`.\n" +"* Depending on the target, you may need to compile with `panic = \"abort\"` to avoid an error " +"about\n" +" `eh_personality`.\n" +"* Note that there is no `main` or any other entry point; it's up to you to define your own entry\n" +" point. This will typically involve a linker script and some assembly code to set things up " +"ready\n" +" for Rust code to run." +msgstr "" + +#: src/bare-metal/alloc.md:1 +msgid "# `alloc`" +msgstr "" + +#: src/bare-metal/alloc.md:3 +msgid "" +"To use `alloc` you must implement a\n" +"[global (heap) allocator](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html)." +msgstr "" + +#: src/bare-metal/alloc.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate alloc;\n" +"extern crate panic_halt as _;\n" +"\n" +"use alloc::string::ToString;\n" +"use alloc::vec::Vec;\n" +"use buddy_system_allocator::LockedHeap;\n" +"\n" +"#[global_allocator]\n" +"static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();\n" +"\n" +"static mut HEAP: [u8; 65536] = [0; 65536];\n" +"\n" +"pub fn entry() {\n" +" // Safe because `HEAP` is only used here and `entry` is only called once.\n" +" unsafe {\n" +" // Give the allocator some memory to allocate.\n" +" HEAP_ALLOCATOR\n" +" .lock()\n" +" .init(HEAP.as_mut_ptr() as usize, HEAP.len());\n" +" }\n" +"\n" +" // Now we can do things that require heap allocation.\n" +" let mut v = Vec::new();\n" +" v.push(\"A string\".to_string());\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/alloc.md:39 +msgid "" +"* `buddy_system_allocator` is a third-party crate implementing a basic buddy system allocator. " +"Other\n" +" crates are available, or you can write your own or hook into your existing allocator.\n" +"* The const parameter of `LockedHeap` is the max order of the allocator; i.e. in this case it can\n" +" allocate regions of up to 2**32 bytes.\n" +"* If any crate in your dependency tree depends on `alloc` then you must have exactly one global\n" +" allocator defined in your binary. Usually this is done in the top-level binary crate.\n" +"* `extern crate panic_halt as _` is necessary to ensure that the `panic_halt` crate is linked in " +"so\n" +" we get its panic handler.\n" +"* This example will build but not run, as it doesn't have an entry point." +msgstr "" + +#: src/bare-metal/microcontrollers.md:1 +msgid "# Microcontrollers" +msgstr "" + +#: src/bare-metal/microcontrollers.md:3 +msgid "" +"The `cortex_m_rt` crate provides (among other things) a reset handler for Cortex M " +"microcontrollers." +msgstr "" + +#: src/bare-metal/microcontrollers.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use cortex_m_rt::entry;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers.md:21 +msgid "Next we'll look at how to access peripherals, with increasing levels of abstraction." +msgstr "" + +#: src/bare-metal/microcontrollers.md:25 +msgid "" +"* The `cortex_m_rt::entry` macro requires that the function have type `fn() -> !`, because " +"returning\n" +" to the reset handler doesn't make sense.\n" +"* Run the example with `cargo embed --bin minimal`" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:1 +msgid "# Raw MMIO" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:3 +msgid "" +"Most microcontrollers access peripherals via memory-mapped IO. Let's try turning on an LED on our\n" +"micro:bit:" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use core::mem::size_of;\n" +"use cortex_m_rt::entry;\n" +"\n" +"/// GPIO port 0 peripheral address\n" +"const GPIO_P0: usize = 0x5000_0000;\n" +"\n" +"// GPIO peripheral offsets\n" +"const PIN_CNF: usize = 0x700;\n" +"const OUTSET: usize = 0x508;\n" +"const OUTCLR: usize = 0x50c;\n" +"\n" +"// PIN_CNF fields\n" +"const DIR_OUTPUT: u32 = 0x1;\n" +"const INPUT_DISCONNECT: u32 = 0x1 << 1;\n" +"const PULL_DISABLED: u32 = 0x0 << 2;\n" +"const DRIVE_S0S1: u32 = 0x0 << 8;\n" +"const SENSE_DISABLED: u32 = 0x0 << 16;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let pin_cnf_21 = (GPIO_P0 + PIN_CNF + 21 * size_of::()) as *mut u32;\n" +" let pin_cnf_28 = (GPIO_P0 + PIN_CNF + 28 * size_of::()) as *mut u32;\n" +" // Safe because the pointers are to valid peripheral control registers, and\n" +" // no aliases exist.\n" +" unsafe {\n" +" pin_cnf_21.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED,\n" +" );\n" +" pin_cnf_28.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED,\n" +" );\n" +" }\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" let gpio0_outset = (GPIO_P0 + OUTSET) as *mut u32;\n" +" let gpio0_outclr = (GPIO_P0 + OUTCLR) as *mut u32;\n" +" // Safe because the pointers are to valid peripheral control registers, and\n" +" // no aliases exist.\n" +" unsafe {\n" +" gpio0_outclr.write_volatile(1 << 28);\n" +" gpio0_outset.write_volatile(1 << 21);\n" +" }\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:64 +msgid "" +"* GPIO 0 pin 21 is connected to the first column of the LED matrix, and pin 28 to the first row." +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:66 src/bare-metal/microcontrollers/pacs.md:59 +#: src/bare-metal/microcontrollers/hals.md:43 src/bare-metal/microcontrollers/board-support.md:34 +msgid "Run the example with:" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:68 +msgid "" +"```sh\n" +"cargo embed --bin mmio\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:1 +msgid "# Peripheral Access Crates" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:3 +msgid "" +"[`svd2rust`](https://crates.io/crates/svd2rust) generates mostly-safe Rust wrappers for\n" +"memory-mapped peripherals from [CMSIS-SVD](https://www.keil.com/pack/doc/CMSIS/SVD/html/index." +"html)\n" +"files." +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_pac::Peripherals;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p.P0;\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" gpio0.pin_cnf[21].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +" gpio0.pin_cnf[28].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" gpio0.outclr.write(|w| w.pin28().clear());\n" +" gpio0.outset.write(|w| w.pin21().set());\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:49 +msgid "" +"* SVD (System View Description) files are XML files typically provided by silicon vendors which\n" +" describe the memory map of the device.\n" +" * They are organised by peripheral, register, field and value, with names, descriptions, " +"addresses\n" +" and so on.\n" +" * SVD files are often buggy and incomplete, so there are various projects which patch the\n" +" mistakes, add missing details, and publish the generated crates.\n" +"* `cortex-m-rt` provides the vector table, among other things.\n" +"* If you `cargo install cargo-binutils` then you can run\n" +" `cargo objdump --bin pac -- -d --no-show-raw-insn` to see the resulting binary." +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:61 +msgid "" +"```sh\n" +"cargo embed --bin pac\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:1 +msgid "# HAL crates" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:3 +msgid "" +"[HAL crates](https://github.com/rust-embedded/awesome-embedded-rust#hal-implementation-crates) " +"for\n" +"many microcontrollers provide wrappers around various peripherals. These generally implement " +"traits\n" +"from [`embedded-hal`](https://crates.io/crates/embedded-hal)." +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_hal::gpio::{p0, Level};\n" +"use nrf52833_hal::pac::Peripherals;\n" +"use nrf52833_hal::prelude::*;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +"\n" +" // Create HAL wrapper for GPIO port 0.\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let mut col1 = gpio0.p0_28.into_push_pull_output(Level::High);\n" +" let mut row1 = gpio0.p0_21.into_push_pull_output(Level::Low);\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" col1.set_low().unwrap();\n" +" row1.set_high().unwrap();\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:39 +msgid "" +" * `set_low` and `set_high` are methods on the `embedded_hal` `OutputPin` trait.\n" +" * HAL crates exist for many Cortex-M and RISC-V devices, including various STM32, GD32, nRF, " +"NXP,\n" +" MSP430, AVR and PIC microcontrollers." +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:45 +msgid "" +"```sh\n" +"cargo embed --bin hal\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:1 +#, fuzzy +msgid "# Board support crates" +msgstr "# Tastaturkürzel" + +#: src/bare-metal/microcontrollers/board-support.md:3 +msgid "" +"Board support crates provide a further level of wrapping for a specific board for convenience." +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use microbit::hal::prelude::*;\n" +"use microbit::Board;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let mut board = Board::take().unwrap();\n" +"\n" +" board.display_pins.col1.set_low().unwrap();\n" +" board.display_pins.row1.set_high().unwrap();\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:28 +msgid "" +" * In this case the board support crate is just providing more useful names, and a bit of\n" +" initialisation.\n" +" * The crate may also include drivers for some on-board devices outside of the microcontroller\n" +" itself.\n" +" * `microbit-v2` includes a simple driver for the LED matrix." +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:36 +msgid "" +"```sh\n" +"cargo embed --bin board_support\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:1 +msgid "# The type state pattern" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" let pin: P0_01 = gpio0.p0_01;\n" +"\n" +" // let gpio0_01_again = gpio0.p0_01; // Error, moved.\n" +" let pin_input: P0_01> = pin.into_floating_input();\n" +" if pin_input.is_high().unwrap() {\n" +" // ...\n" +" }\n" +" let mut pin_output: P0_01> = pin_input\n" +" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);\n" +" pin_output.set_high().unwrap();\n" +" // pin_input.is_high(); // Error, moved.\n" +"\n" +" let _pin2: P0_02> = gpio0\n" +" .p0_02\n" +" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);\n" +" let _pin3: P0_03> = gpio0.p0_03.into_push_pull_output(Level::Low);\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:32 +msgid "" +" * Pins don't implement `Copy` or `Clone`, so only one instance of each can exist. Once a pin is\n" +" moved out of the port struct nobody else can take it.\n" +" * Changing the configuration of a pin consumes the old pin instance, so you can’t keep use the " +"old\n" +" instance afterwards.\n" +" * The type of a value indicates the state that it is in: e.g. in this case, the configuration " +"state\n" +" of a GPIO pin. This encodes the state machine into the type system, and ensures that you don't\n" +" try to use a pin in a certain way without properly configuring it first. Illegal state\n" +" transitions are caught at compile time.\n" +" * You can call `is_high` on an input pin and `set_high` on an output pin, but not vice-versa.\n" +" * Many HAL crates follow this pattern." +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:1 +msgid "# `embedded-hal`" +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:3 +msgid "" +"The [`embedded-hal`](https://crates.io/crates/embedded-hal) crate provides a number of traits\n" +"covering common microcontroller peripherals." +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:6 +msgid "" +" * GPIO\n" +" * ADC\n" +" * I2C, SPI, UART, CAN\n" +" * RNG\n" +" * Timers\n" +" * Watchdogs" +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:13 +msgid "" +"Other crates then implement\n" +"[drivers](https://github.com/rust-embedded/awesome-embedded-rust#driver-crates) in terms of these\n" +"traits, e.g. an accelerometer driver might need an I2C or SPI bus implementation." +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:19 +msgid "" +" * There are implementations for many microcontrollers, as well as other platforms such as Linux " +"on\n" +"Raspberry Pi.\n" +" * There is work in progress on an `async` version of `embedded-hal`, but it isn't stable yet." +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:1 +msgid "# `probe-rs`, `cargo-embed`" +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:3 +msgid "" +"[probe-rs](https://probe.rs/) is a handy toolset for embedded debugging, like OpenOCD but better\n" +"integrated." +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:6 +msgid "" +"* SWD and JTAG via CMSIS-DAP, ST-Link and J-Link probes\n" +"* GDB stub and Microsoft DAP server\n" +"* Cargo integration" +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:10 +msgid "" +"`cargo-embed` is a cargo subcommand to build and flash binaries, log\n" +"RTT output and connect GDB. It's configured by an\n" +"`Embed.toml` file in your project directory." +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:16 +msgid "" +"* [CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) is an Arm standard\n" +" protocol over USB for an in-circuit debugger to access the CoreSight Debug Access Port of " +"various\n" +" Arm Cortex processors. It's what the on-board debugger on the BBC micro:bit uses.\n" +"* ST-Link is a range of in-circuit debuggers from ST Microelectronics, J-Link is a range from\n" +" SEGGER.\n" +"* The Debug Access Port is usually either a 5-pin JTAG interface or 2-pin Serial Wire Debug.\n" +"* probe-rs is a library which you can integrate into your own tools if you want to.\n" +"* The [Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/) " +"lets\n" +" VSCode and other IDEs debug code running on any supported microcontroller.\n" +"* cargo-embed is a binary built using the probe-rs library.\n" +"* RTT (Real Time Transfers) is a mechanism to transfer data between the debug host and the target\n" +" through a number of ringbuffers." +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:1 +#, fuzzy +msgid "# Debugging" +msgstr "# Protokollierung" + +#: src/bare-metal/microcontrollers/debugging.md:3 +msgid "Embed.toml:" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:5 +msgid "" +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:13 +msgid "In one terminal under `src/bare-metal/microcontrollers/examples/`:" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:15 +msgid "" +"```sh\n" +"cargo embed --bin board_support debug\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:19 +#, fuzzy +msgid "In another terminal in the same directory:" +msgstr "Überprüfen Sie in einem anderen Terminal, ob der Dienst ausgeführt wird:" + +#: src/bare-metal/microcontrollers/debugging.md:21 +msgid "" +"```sh\n" +"gdb-multiarch target/thumbv7em-none-eabihf/debug/board_support --eval-command=\"target " +"remote :1337\"\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:27 +msgid "In GDB, try running:" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:29 +msgid "" +"```gdb\n" +"b src/bin/board_support.rs:29\n" +"b src/bin/board_support.rs:30\n" +"b src/bin/board_support.rs:32\n" +"c\n" +"c\n" +"c\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/other-projects.md:1 src/bare-metal/aps/other-projects.md:1 +msgid "# Other projects" +msgstr "" + +#: src/bare-metal/microcontrollers/other-projects.md:3 +msgid "" +" * [RTIC](https://rtic.rs/)\n" +" * \"Real-Time Interrupt-driven Concurrency\"\n" +" * Shared resource management, message passing, task scheduling, timer queue\n" +" * [Embassy](https://embassy.dev/)\n" +" * `async` executors with priorities, timers, networking, USB\n" +" * [TockOS](https://www.tockos.org/documentation/getting-started)\n" +" * Security-focused RTOS with preemptive scheduling and Memory Protection Unit support\n" +" * [Hubris](https://hubris.oxide.computer/)\n" +" * Microkernel RTOS from Oxide Computer Company with memory protection, unprivileged drivers, " +"IPC\n" +" * [Bindings for FreeRTOS](https://github.com/lobaro/FreeRTOS-rust)\n" +" * Some platforms have `std` implementations, e.g.\n" +" [esp-idf](https://esp-rs.github.io/book/overview/using-the-standard-library.html)." +msgstr "" + +#: src/bare-metal/microcontrollers/other-projects.md:18 +msgid "" +" * RTIC can be considered either an RTOS or a concurrency framework.\n" +" * It doesn't include any HALs.\n" +" * It uses the Cortex-M NVIC (Nested Virtual Interrupt Controller) for scheduling rather than a\n" +" proper kernel.\n" +" * Cortex-M only.\n" +" * Google uses TockOS on the Haven microcontroller for Titan security keys.\n" +" * FreeRTOS is mostly written in C, but there are Rust bindings for writing applications." +msgstr "" + +#: src/exercises/bare-metal/morning.md:3 +msgid "We will read the direction from an I2C compass, and log the readings to a serial port." +msgstr "" + +#: src/exercises/bare-metal/compass.md:1 +#, fuzzy +msgid "# Compass" +msgstr "# Vergleich" + +#: src/exercises/bare-metal/compass.md:3 +msgid "" +"We will read the direction from an I2C compass, and log the readings to a serial port. If you " +"have\n" +"time, try displaying it on the LEDs somehow too, or use the buttons somehow." +msgstr "" + +#: src/exercises/bare-metal/compass.md:6 +msgid "Hints:" +msgstr "" + +#: src/exercises/bare-metal/compass.md:8 +msgid "" +"- Check the documentation for the [`lsm303agr`](https://docs.rs/lsm303agr/latest/lsm303agr/) and\n" +" [`microbit-v2`](https://docs.rs/microbit-v2/latest/microbit/) crates, as well as the\n" +" [micro:bit hardware](https://tech.microbit.org/hardware/).\n" +"- The LSM303AGR Inertial Measurement Unit is connected to the internal I2C bus.\n" +"- TWI is another name for I2C, so the I2C master peripheral is called TWIM.\n" +"- The LSM303AGR driver needs something implementing the `embedded_hal::blocking::i2c::WriteRead`\n" +" trait. The\n" +" [`microbit::hal::Twim`](https://docs.rs/microbit-v2/latest/microbit/hal/struct.Twim.html) " +"struct\n" +" implements this.\n" +"- You have a [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/struct.Board.html)\n" +" struct with fields for the various pins and peripherals.\n" +"- You can also look at the\n" +" [nRF52833 datasheet](https://infocenter.nordicsemi.com/pdf/nRF52833_PS_v1.5.pdf) if you want, " +"but\n" +" it shouldn't be necessary for this exercise." +msgstr "" + +#: src/exercises/bare-metal/compass.md:23 +msgid "" +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the " +"`compass`\n" +"directory for the following files." +msgstr "" + +#: src/exercises/bare-metal/compass.md:30 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"use microbit::{hal::uarte::{Baudrate, Parity, Uarte}, Board};\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // TODO\n" +"\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // TODO\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:68 +msgid "" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"compass\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"cortex-m-rt = \"0.7.3\"\n" +"embedded-hal = \"0.2.6\"\n" +"lsm303agr = \"0.2.2\"\n" +"microbit-v2 = \"0.13.0\"\n" +"panic-halt = \"0.2.0\"\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:85 +msgid "`Embed.toml` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/compass.md:87 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/compass.md:89 +msgid "" +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"\n" +"[debug.reset]\n" +"halt_afterwards = true\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:100 src/exercises/bare-metal/rtc.md:980 +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 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/compass.md:104 +msgid "" +"```toml\n" +"[build]\n" +"target = \"thumbv7em-none-eabihf\" # Cortex-M4F\n" +"\n" +"[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))']\n" +"rustflags = [\"-C\", \"link-arg=-Tlink.x\"]\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:112 +msgid "See the serial output on Linux with:" +msgstr "" + +#: src/exercises/bare-metal/compass.md:114 +msgid "" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/ttyACM0\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:118 +msgid "Or on Mac OS something like (the device name may be slightly different):" +msgstr "" + +#: src/exercises/bare-metal/compass.md:120 +msgid "" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:124 +msgid "Use Ctrl+A Ctrl+Q to quit picocom." +msgstr "" + +#: src/bare-metal/aps.md:1 +msgid "# Application processors" +msgstr "" + +#: src/bare-metal/aps.md:3 +msgid "" +"So far we've talked about microcontrollers, such as the Arm Cortex-M series. Now let's try " +"writing\n" +"something for Cortex-A. For simplicity we'll just work with QEMU's aarch64\n" +"['virt'](https://qemu-project.gitlab.io/qemu/system/arm/virt.html) board." +msgstr "" + +#: src/bare-metal/aps.md:9 +msgid "" +"* Broadly speaking, microcontrollers don't have an MMU or multiple levels of privilege (exception\n" +" levels on Arm CPUs, rings on x86), while application processors do.\n" +"* QEMU supports emulating various different machines or board models for each architecture. The\n" +" 'virt' board doesn't correspond to any particular real hardware, but is designed purely for\n" +" virtual machines." +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:1 +msgid "# Inline assembly" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:3 +msgid "" +"Sometimes we need to use assembly to do things that aren't possible with Rust code. For example,\n" +"to make an HVC to tell the firmware to power off the system:" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::arch::asm;\n" +"use core::panic::PanicInfo;\n" +"\n" +"mod exceptions;\n" +"\n" +"const PSCI_SYSTEM_OFF: u32 = 0x84000008;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) {\n" +" // Safe because this only uses the declared registers and doesn't do\n" +" // anything with memory.\n" +" unsafe {\n" +" asm!(\"hvc #0\",\n" +" inout(\"w0\") PSCI_SYSTEM_OFF => _,\n" +" inout(\"w1\") 0 => _,\n" +" inout(\"w2\") 0 => _,\n" +" inout(\"w3\") 0 => _,\n" +" inout(\"w4\") 0 => _,\n" +" inout(\"w5\") 0 => _,\n" +" inout(\"w6\") 0 => _,\n" +" inout(\"w7\") 0 => _,\n" +" options(nomem, nostack)\n" +" );\n" +" }\n" +"\n" +" loop {}\n" +"}\n" +"```" +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 " +"functions.)" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:43 +msgid "" +"* PSCI is the Arm Power State Coordination Interface, a standard set of functions to manage " +"system\n" +" and CPU power states, among other things. It is implemented by EL3 firmware and hypervisors on\n" +" many systems.\n" +"* The `0 => _` syntax means initialise the register to 0 before running the inline assembly code,\n" +" and ignore its contents afterwards. We need to use `inout` rather than `in` because the call " +"could\n" +" potentially clobber the contents of the registers.\n" +"* This `main` function needs to be `#[no_mangle]` and `extern \"C\"` because it is called from " +"our\n" +" entry point in `entry.S`.\n" +"* `_x0`–`_x3` are the values of registers `x0`–`x3`, which are conventionally used by the " +"bootloader\n" +" to pass things like a pointer to the device tree. According to the standard aarch64 calling\n" +" convention (which is what `extern \"C\"` specifies to use), registers `x0`–`x7` are used for " +"the\n" +" first 8 arguments passed to a function, so `entry.S` doesn't need to do anything special except\n" +" make sure it doesn't change these registers.\n" +"* Run the example in QEMU with `make qemu_psci` under `src/bare-metal/aps/examples`." +msgstr "" + +#: src/bare-metal/aps/mmio.md:1 +msgid "# Volatile memory access for MMIO" +msgstr "" + +#: src/bare-metal/aps/mmio.md:3 +msgid "" +" * Use `pointer::read_volatile` and `pointer::write_volatile`.\n" +" * Never hold a reference.\n" +" * `addr_of!` lets you get fields of structs without creating an intermediate reference." +msgstr "" + +#: src/bare-metal/aps/mmio.md:9 +msgid "" +" * Volatile access: read or write operations may have side-effects, so prevent the compiler or\n" +" hardware from reordering, duplicating or eliding them.\n" +" * Usually if you write and then read, e.g. via a mutable reference, the compiler may assume " +"that\n" +" the value read is the same as the value just written, and not bother actually reading " +"memory.\n" +" * Some existing crates for volatile access to hardware do hold references, but this is unsound.\n" +" Whenever a reference exist, the compiler may choose to dereference it.\n" +" * Use the `addr_of!` macro to get struct field pointers from a pointer to the struct." +msgstr "" + +#: src/bare-metal/aps/uart.md:1 +msgid "# Let's write a UART driver" +msgstr "" + +#: src/bare-metal/aps/uart.md:3 +msgid "The QEMU 'virt' machine has a [PL011][1] UART, so let's write a driver for that." +msgstr "" + +#: src/bare-metal/aps/uart.md:5 +msgid "" +"```rust,editable\n" +"const FLAG_REGISTER_OFFSET: usize = 0x18;\n" +"const FR_BUSY: u8 = 1 << 3;\n" +"const FR_TXFF: u8 = 1 << 5;\n" +"\n" +"/// Minimal driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" base_address: *mut u8,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of a\n" +" /// PL011 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u8) -> Self {\n" +" Self { base_address }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register() & FR_TXFF != 0 {}\n" +"\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" self.base_address.write_volatile(byte);\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register() & FR_BUSY != 0 {}\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> u8 {\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { self.base_address.add(FLAG_REGISTER_OFFSET).read_volatile() }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/uart.md:55 +msgid "" +"* Note that `Uart::new` is unsafe while the other methods are safe. This is because as long as " +"the\n" +" caller of `Uart::new` guarantees that its safety requirements are met (i.e. that there is only\n" +" ever one instance of the driver for a given UART, and nothing else aliasing its address space),\n" +" then it is always safe to call `write_byte` later because we can assume the necessary\n" +" preconditions.\n" +"* We could have done it the other way around (making `new` safe but `write_byte` unsafe), but " +"that\n" +" would be much less convenient to use as every place that calls `write_byte` would need to " +"reason\n" +" about the safety\n" +"* This is a common pattern for writing safe wrappers of unsafe code: moving the burden of proof " +"for\n" +" soundness from a large number of places to a smaller number of places." +msgstr "" + +#: src/bare-metal/aps/uart.md:66 +#, fuzzy +msgid "" +msgstr "
" + +#: src/bare-metal/aps/uart/traits.md:1 +#, fuzzy +msgid "# More traits" +msgstr "# Züge" + +#: src/bare-metal/aps/uart/traits.md:3 +msgid "We derived the `Debug` trait. It would be useful to implement a few more traits too." +msgstr "" + +#: src/bare-metal/aps/uart/traits.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use core::fmt::{self, Write};\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/uart/traits.md:24 +msgid "" +"* Implementing `Write` lets us use the `write!` and `writeln!` macros with our `Uart` type.\n" +"* Run the example in QEMU with `make qemu_minimal` under `src/bare-metal/aps/examples`." +msgstr "" + +#: src/bare-metal/aps/better-uart.md:1 +msgid "# A better UART driver" +msgstr "" + +#: src/bare-metal/aps/better-uart.md:3 +msgid "" +"The PL011 actually has [a bunch more registers][1], and adding offsets to construct pointers to " +"access\n" +"them is error-prone and hard to read. Plus, some of them are bit fields which would be nice to\n" +"access in a structured way." +msgstr "" + +#: src/bare-metal/aps/better-uart.md:7 +msgid "" +"| Offset | Register name | Width |\n" +"| ------ | ------------- | ----- |\n" +"| 0x00 | DR | 12 |\n" +"| 0x04 | RSR | 4 |\n" +"| 0x18 | FR | 9 |\n" +"| 0x20 | ILPR | 8 |\n" +"| 0x24 | IBRD | 16 |\n" +"| 0x28 | FBRD | 6 |\n" +"| 0x2c | LCR_H | 8 |\n" +"| 0x30 | CR | 16 |\n" +"| 0x34 | IFLS | 6 |\n" +"| 0x38 | IMSC | 11 |\n" +"| 0x3c | RIS | 11 |\n" +"| 0x40 | MIS | 11 |\n" +"| 0x44 | ICR | 11 |\n" +"| 0x48 | DMACR | 3 |" +msgstr "" + +#: src/bare-metal/aps/better-uart.md:26 +msgid "- There are also some ID registers which have been omitted for brevity." +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:1 +msgid "# Bitflags" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:3 +msgid "" +"The [`bitflags`](https://crates.io/crates/bitflags) crate is useful for working with bitflags." +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:37 +msgid "" +"* The `bitflags!` macro creates a newtype something like `Flags(u16)`, along with a bunch of " +"method\n" +" implementations to get and set flags." +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:1 +msgid "# Multiple registers" +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:3 +msgid "We can use a struct to represent the memory layout of the UART's registers." +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:41 +msgid "" +"* [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-representation) tells\n" +" the compiler to lay the struct fields out in order, following the same rules as C. This is\n" +" necessary for our struct to have a predictable layout, as default Rust representation allows " +"the\n" +" compiler to (among other things) reorder fields however it sees fit." +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:1 +msgid "# Driver" +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:3 +msgid "Now let's use the new `Registers` struct in our driver." +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of a\n" +" /// PL011 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr).read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:64 +msgid "" +"* Note the use of `addr_of!` / `addr_of_mut!` to get pointers to individual fields without " +"creating\n" +" an intermediate reference, which would be unsound." +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:1 src/bare-metal/aps/logging/using.md:1 +#, fuzzy +msgid "# Using it" +msgstr "# Verwenden von Bindgen" + +#: src/bare-metal/aps/better-uart/using.md:3 +msgid "" +"Let's write a small program using our driver to write to the serial console, and echo incoming\n" +"bytes." +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use core::panic::PanicInfo;\n" +"use log::error;\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +"\n" +" writeln!(uart, \"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\").unwrap();\n" +"\n" +" loop {\n" +" if let Some(b) = uart.read_byte() {\n" +" uart.write_byte(b);\n" +" match b {\n" +" b'\\r' => {\n" +" uart.write_byte(b'\\n');\n" +" }\n" +" b'q' => break,\n" +" _ => {}\n" +" }\n" +" }\n" +" }\n" +"\n" +" writeln!(uart, \"Bye!\").unwrap();\n" +" system_off().unwrap();\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:50 +msgid "" +"* As in the [inline assembly](../inline-assembly.md) example, this `main` function is called from " +"our\n" +" entry point code in `entry.S`. See the speaker notes there for details.\n" +"* Run the example in QEMU with `make qemu` under `src/bare-metal/aps/examples`." +msgstr "" + +#: src/bare-metal/aps/logging.md:3 +msgid "" +"It would be nice to be able to use the logging macros from the [`log`][1] crate. We can do this " +"by\n" +"implementing the `Log` trait." +msgstr "" + +#: src/bare-metal/aps/logging.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" +" }\n" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/logging.md:50 +msgid "* The unwrap in `log` is safe because we initialise `LOGGER` before calling `set_logger`." +msgstr "" + +#: src/bare-metal/aps/logging/using.md:3 +msgid "We need to initialise the logger before we use it." +msgstr "" + +#: src/bare-metal/aps/logging/using.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, LevelFilter};\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\");\n" +"\n" +" assert_eq!(x1, 42);\n" +"\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off().unwrap();\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/logging/using.md:45 +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`." +msgstr "" + +#: src/bare-metal/aps/other-projects.md:3 +msgid "" +" * [oreboot](https://github.com/oreboot/oreboot)\n" +" * \"coreboot without the C\"\n" +" * Supports x86, aarch64 and RISC-V.\n" +" * Relies on LinuxBoot rather than having many drivers itself.\n" +" * [Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials)\n" +" * Initialisation, UART driver, simple bootloader, JTAG, exception levels, exception handling, " +"page tables\n" +" * Not all very well written, so beware.\n" +" * [`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)\n" +" * Static analysis to determine maximum stack usage." +msgstr "" + +#: src/bare-metal/useful-crates.md:1 +msgid "# Useful crates" +msgstr "" + +#: src/bare-metal/useful-crates.md:3 +msgid "We'll go over a few crates which solve some common problems in bare-metal programming." +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:1 +msgid "# `zerocopy`" +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:3 +msgid "" +"The [`zerocopy`][1] crate (from Fuchsia) provides traits and macros for safely converting between\n" +"byte sequences and other types." +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use zerocopy::AsBytes;\n" +"\n" +"#[repr(u32)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"enum RequestType {\n" +" #[default]\n" +" In = 0,\n" +" Out = 1,\n" +" Flush = 4,\n" +"}\n" +"\n" +"#[repr(C)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"struct VirtioBlockRequest {\n" +" request_type: RequestType,\n" +" reserved: u32,\n" +" sector: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let request = VirtioBlockRequest {\n" +" request_type: RequestType::Flush,\n" +" sector: 42,\n" +" ..Default::default()\n" +" };\n" +"\n" +" assert_eq!(\n" +" request.as_bytes(),\n" +" &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0]\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:40 +msgid "" +"This is not suitable for MMIO (as it doesn't use volatile reads and writes), but can be useful " +"for\n" +"working with structures shared with hardware e.g. by DMA, or sent over some external interface." +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:45 +msgid "" +"* `FromBytes` can be implemented for types for which any byte pattern is valid, and so can safely " +"be\n" +" converted from an untrusted sequence of bytes.\n" +"* Attempting to derive `FromBytes` for these types would fail, because `RequestType` doesn't use " +"all\n" +" possible u32 values as discriminants, so not all byte patterns are valid.\n" +"* `zerocopy::byteorder` has types for byte-order aware numeric primitives.\n" +"* Run the example with `cargo run` under `src/bare-metal/useful-crates/zerocopy-example/`. (It " +"won't\n" +" run in the Playground because of the crate dependency.)" +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:1 +msgid "# `aarch64-paging`" +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:3 +msgid "" +"The [`aarch64-paging`][1] crate lets you create page tables according to the AArch64 Virtual " +"Memory\n" +"System Architecture." +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use aarch64_paging::{\n" +" idmap::IdMap,\n" +" paging::{Attributes, MemoryRegion},\n" +"};\n" +"\n" +"const ASID: usize = 1;\n" +"const ROOT_LEVEL: usize = 1;\n" +"\n" +"// Create a new page table with identity mapping.\n" +"let mut idmap = IdMap::new(ASID, ROOT_LEVEL);\n" +"// Map a 2 MiB region of memory as read-only.\n" +"idmap.map_range(\n" +" &MemoryRegion::new(0x80200000, 0x80400000),\n" +" Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,\n" +").unwrap();\n" +"// Set `TTBR0_EL1` to activate the page table.\n" +"idmap.activate();\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:28 +msgid "" +"* For now it only supports EL1, but support for other exception levels should be straightforward " +"to\n" +" add.\n" +"* This is used in Android for the [Protected VM Firmware][2].\n" +"* There's no easy way to run this example, as it needs to run on real hardware or under QEMU." +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:1 +msgid "# `buddy_system_allocator`" +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:3 +msgid "" +"[`buddy_system_allocator`][1] is a third-party crate implementing a basic buddy system allocator.\n" +"It can be used both for [`LockedHeap`][2] implementing [`GlobalAlloc`][3] so you can use the\n" +"standard `alloc` crate (as we saw [before][4]), or for allocating other address space. For " +"example,\n" +"we might want to allocate MMIO space for PCI BARs:" +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use buddy_system_allocator::FrameAllocator;\n" +"use core::alloc::Layout;\n" +"\n" +"fn main() {\n" +" let mut allocator = FrameAllocator::<32>::new();\n" +" allocator.add_frame(0x200_0000, 0x400_0000);\n" +"\n" +" let layout = Layout::from_size_align(0x100, 0x100).unwrap();\n" +" let bar = allocator\n" +" .alloc_aligned(layout)\n" +" .expect(\"Failed to allocate 0x100 byte MMIO region\");\n" +" println!(\"Allocated 0x100 byte MMIO region at {:#x}\", bar);\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:26 +msgid "" +"* PCI BARs always have alignment equal to their size.\n" +"* Run the example with `cargo run` under `src/bare-metal/useful-crates/allocator-example/`. (It " +"won't\n" +" run in the Playground because of the crate dependency.)" +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:1 +msgid "# `tinyvec`" +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:3 +msgid "" +"Sometimes you want something which can be resized like a `Vec`, but without heap allocation.\n" +"[`tinyvec`][1] provides this: a vector backed by an array or slice, which could be statically\n" +"allocated or on the stack, which keeps track of how many elements are used and panics if you try " +"to\n" +"use more than are allocated." +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use tinyvec::{array_vec, ArrayVec};\n" +"\n" +"fn main() {\n" +" let mut numbers: ArrayVec<[u32; 5]> = array_vec!(42, 66);\n" +" println!(\"{numbers:?}\");\n" +" numbers.push(7);\n" +" println!(\"{numbers:?}\");\n" +" numbers.remove(1);\n" +" println!(\"{numbers:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:23 +msgid "" +"* `tinyvec` requires that the element type implement `Default` for initialisation.\n" +"* The Rust Playground includes `tinyvec`, so this example will run fine inline." +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:1 +#, fuzzy +msgid "# `spin`" +msgstr "## `statisch`" + +#: src/bare-metal/useful-crates/spin.md:3 +msgid "" +"`std::sync::Mutex` and the other synchronisation primitives from `std::sync` are not available in\n" +"`core` or `alloc`. How can we manage synchronisation or interior mutability, such as for sharing\n" +"state between different CPUs?" +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:7 +msgid "The [`spin`][1] crate provides spinlock-based equivalents of many of these primitives." +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:9 +msgid "" +"```rust,editable,compile_fail\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static counter: SpinMutex = SpinMutex::new(0);\n" +"\n" +"fn main() {\n" +" println!(\"count: {}\", counter.lock());\n" +" *counter.lock() += 2;\n" +" println!(\"count: {}\", counter.lock());\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:23 +msgid "" +"* Be careful to avoid deadlock if you take locks in interrupt handlers.\n" +"* `spin` also has a ticket lock mutex implementation; equivalents of `RwLock`, `Barrier` and " +"`Once`\n" +" from `std::sync`; and `Lazy` for lazy initialisation.\n" +"* The [`once_cell`][2] crate also has some useful types for late initialisation with a slightly\n" +" different approach to `spin::once::Once`.\n" +"* The Rust Playground includes `spin`, so this example will run fine inline." +msgstr "" + +#: 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 " +"build\n" +"your Rust code, then a `cc_binary` with a linker script to produce the binary itself, and then a\n" +"`raw_binary` to convert the ELF to a raw binary ready to be run." +msgstr "" + +#: src/bare-metal/android.md:7 +msgid "" +"```soong\n" +"rust_ffi_static {\n" +" name: \"libvmbase_example\",\n" +" defaults: [\"vmbase_ffi_defaults\"],\n" +" crate_name: \"vmbase_example\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libvmbase\",\n" +" ],\n" +"}\n" +"\n" +"cc_binary {\n" +" name: \"vmbase_example\",\n" +" defaults: [\"vmbase_elf_defaults\"],\n" +" srcs: [\n" +" \"idmap.S\",\n" +" ],\n" +" static_libs: [\n" +" \"libvmbase_example\",\n" +" ],\n" +" linker_scripts: [\n" +" \"image.ld\",\n" +" \":vmbase_sections\",\n" +" ],\n" +"}\n" +"\n" +"raw_binary {\n" +" name: \"vmbase_example_bin\",\n" +" stem: \"vmbase_example.bin\",\n" +" src: \":vmbase_example\",\n" +" enabled: false,\n" +" target: {\n" +" android_arm64: {\n" +" enabled: true,\n" +" },\n" +" },\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/android/vmbase.md:1 +msgid "# vmbase" +msgstr "" + +#: src/bare-metal/android/vmbase.md:3 +msgid "" +"For VMs running under crosvm on aarch64, the [vmbase][1] library provides a linker script and " +"useful\n" +"defaults for the build rules, along with an entry point, UART console logging and more." +msgstr "" + +#: src/bare-metal/android/vmbase.md:6 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use vmbase::{main, println};\n" +"\n" +"main!(main);\n" +"\n" +"pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {\n" +" println!(\"Hello world\");\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/android/vmbase.md:21 +msgid "" +"* The `main!` macro marks your main function, to be called from the `vmbase` entry point.\n" +"* The `vmbase` entry point handles console initialisation, and issues a PSCI_SYSTEM_OFF to " +"shutdown\n" +" the VM if your main function returns." +msgstr "" + +#: src/exercises/bare-metal/afternoon.md:3 +msgid "We will write a driver for the PL031 real-time clock device." +msgstr "" + +#: src/exercises/bare-metal/rtc.md:1 +msgid "# RTC driver" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:3 +msgid "" +"The QEMU aarch64 virt machine has a [PL031][1] real-time clock at 0x9010000. For this exercise, " +"you\n" +"should write a driver for it." +msgstr "" + +#: src/exercises/bare-metal/rtc.md:6 +msgid "" +"1. Use it to print the current time to the serial console. You can use the [`chrono`][2] crate " +"for\n" +" date/time formatting.\n" +"2. Use the match register and raw interrupt status to busy-wait until a given time, e.g. 3 " +"seconds\n" +" 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." +msgstr "" + +#: src/exercises/bare-metal/rtc.md:13 +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 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use arm_gic::gicv3::GicV3;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, trace, LevelFilter};\n" +"use psci::system_off;\n" +"\n" +"/// Base addresses of the GICv3.\n" +"const GICD_BASE_ADDRESS: *mut u64 = 0x800_0000 as _;\n" +"const GICR_BASE_ADDRESS: *mut u64 = 0x80A_0000 as _;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +"\n" +" // Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base\n" +" // addresses of a GICv3 distributor and redistributor respectively, and\n" +" // nothing else accesses those address ranges.\n" +" let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, GICR_BASE_ADDRESS) };\n" +" gic.setup();\n" +"\n" +" // TODO: Initialise RTC and print value.\n" +"\n" +" // TODO: Wait for 3 seconds.\n" +"\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off().unwrap();\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:71 +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 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:75 +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" +"use arm_gic::gicv3::GicV3;\n" +"use log::{error, info, trace};\n" +"use psci::system_off;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_exception_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" +" trace!(\"irq_current\");\n" +" let intid = GicV3::get_and_acknowledge_interrupt().expect(\"No pending interrupt\");\n" +" info!(\"IRQ {intid:?}\");\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:144 +msgid "`src/logger.rs` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:146 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:148 +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: main\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" +" }\n" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:205 +msgid "`src/pl011.rs` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:207 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:209 +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" +"#![allow(unused)]\n" +"\n" +"use core::fmt::{self, Write};\n" +"use core::ptr::{addr_of, addr_of_mut};\n" +"\n" +"// ANCHOR: Flags\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"// ANCHOR_END: Flags\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART Receive Status Register / Error Clear Register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct ReceiveStatus: u16 {\n" +" /// Framing error.\n" +" const FE = 1 << 0;\n" +" /// Parity error.\n" +" const PE = 1 << 1;\n" +" /// Break error.\n" +" const BE = 1 << 2;\n" +" /// Overrun error.\n" +" const OE = 1 << 3;\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Registers\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"// ANCHOR_END: Registers\n" +"\n" +"// ANCHOR: Uart\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of a\n" +" /// PL011 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr).read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" +"}\n" +"// ANCHOR_END: Uart\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:384 +msgid "" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"rtc\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"arm-gic = \"0.1.0\"\n" +"bitflags = \"2.0.0\"\n" +"chrono = { version = \"0.4.24\", default-features = false }\n" +"log = \"0.4.17\"\n" +"psci = \"0.1.1\"\n" +"spin = \"0.9.8\"\n" +"\n" +"[build-dependencies]\n" +"cc = \"1.0.73\"\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:405 +msgid "`build.rs` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:407 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:409 +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" +"use cc::Build;\n" +"use std::env;\n" +"\n" +"fn main() {\n" +" #[cfg(target_os = \"linux\")]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-linux-gnu\");\n" +" #[cfg(not(target_os = \"linux\"))]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-none-elf\");\n" +"\n" +" Build::new()\n" +" .file(\"entry.S\")\n" +" .file(\"exceptions.S\")\n" +" .file(\"idmap.S\")\n" +" .compile(\"empty\")\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:441 +msgid "`entry.S` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:443 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:445 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".macro adr_l, reg:req, sym:req\n" +"\tadrp \\reg, \\sym\n" +"\tadd \\reg, \\reg, :lo12:\\sym\n" +".endm\n" +"\n" +".macro mov_i, reg:req, imm:req\n" +"\tmovz \\reg, :abs_g3:\\imm\n" +"\tmovk \\reg, :abs_g2_nc:\\imm\n" +"\tmovk \\reg, :abs_g1_nc:\\imm\n" +"\tmovk \\reg, :abs_g0_nc:\\imm\n" +".endm\n" +"\n" +".set .L_MAIR_DEV_nGnRE,\t0x04\n" +".set .L_MAIR_MEM_WBWA,\t0xff\n" +".set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8)\n" +"\n" +"/* 4 KiB granule size for TTBR0_EL1. */\n" +".set .L_TCR_TG0_4KB, 0x0 << 14\n" +"/* 4 KiB granule size for TTBR1_EL1. */\n" +".set .L_TCR_TG1_4KB, 0x2 << 30\n" +"/* Disable translation table walk for TTBR1_EL1, generating a translation fault instead. */\n" +".set .L_TCR_EPD1, 0x1 << 23\n" +"/* Translation table walks for TTBR0_EL1 are inner sharable. */\n" +".set .L_TCR_SH_INNER, 0x3 << 12\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are outer write-back read-allocate write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_OWB, 0x1 << 10\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are inner write-back read-allocate write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_IWB, 0x1 << 8\n" +"/* Size offset for TTBR0_EL1 is 2**39 bytes (512 GiB). */\n" +".set .L_TCR_T0SZ_512, 64 - 39\n" +".set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_TG1_4KB | .L_TCR_EPD1 | .L_TCR_RGN_OWB\n" +".set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | .L_TCR_T0SZ_512\n" +"\n" +"/* Stage 1 instruction access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_I, 0x1 << 12\n" +"/* SP alignment fault if SP is not aligned to a 16 byte boundary. */\n" +".set .L_SCTLR_ELx_SA, 0x1 << 3\n" +"/* Stage 1 data access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_C, 0x1 << 2\n" +"/* EL0 and EL1 stage 1 MMU enabled. */\n" +".set .L_SCTLR_ELx_M, 0x1 << 0\n" +"/* Privileged Access Never is unchanged on taking an exception to EL1. */\n" +".set .L_SCTLR_EL1_SPAN, 0x1 << 23\n" +"/* SETEND instruction disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_SED, 0x1 << 8\n" +"/* Various IT instructions are disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_ITD, 0x1 << 7\n" +".set .L_SCTLR_EL1_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29)\n" +".set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | .L_SCTLR_EL1_ITD | ." +"L_SCTLR_EL1_SED\n" +".set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL1_SPAN | .L_SCTLR_EL1_RES1\n" +"\n" +"/**\n" +" * This is a generic entry point for an image. It carries out the operations required to prepare " +"the\n" +" * loaded image to be run. Specifically, it zeroes the bss section using registers x25 and above,\n" +" * prepares the stack, enables floating point, and sets up the exception vector. It preserves x0-" +"x3\n" +" * for the Rust entry point, as these may contain boot parameters.\n" +" */\n" +".section .init.entry, \"ax\"\n" +".global entry\n" +"entry:\n" +"\t/* Load and apply the memory management configuration, ready to enable MMU and caches. */\n" +"\tadrp x30, idmap\n" +"\tmsr ttbr0_el1, x30\n" +"\n" +"\tmov_i x30, .Lmairval\n" +"\tmsr mair_el1, x30\n" +"\n" +"\tmov_i x30, .Ltcrval\n" +"\t/* Copy the supported PA range into TCR_EL1.IPS. */\n" +"\tmrs x29, id_aa64mmfr0_el1\n" +"\tbfi x30, x29, #32, #4\n" +"\n" +"\tmsr tcr_el1, x30\n" +"\n" +"\tmov_i x30, .Lsctlrval\n" +"\n" +"\t/*\n" +"\t * Ensure everything before this point has completed, then invalidate any potentially stale\n" +"\t * local TLB entries before they start being used.\n" +"\t */\n" +"\tisb\n" +"\ttlbi vmalle1\n" +"\tic iallu\n" +"\tdsb nsh\n" +"\tisb\n" +"\n" +"\t/*\n" +"\t * Configure sctlr_el1 to enable MMU and cache and don't proceed until this has completed.\n" +"\t */\n" +"\tmsr sctlr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Disable trapping floating point access in EL1. */\n" +"\tmrs x30, cpacr_el1\n" +"\torr x30, x30, #(0x3 << 20)\n" +"\tmsr cpacr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Zero out the bss section. */\n" +"\tadr_l x29, bss_begin\n" +"\tadr_l x30, bss_end\n" +"0:\tcmp x29, x30\n" +"\tb.hs 1f\n" +"\tstp xzr, xzr, [x29], #16\n" +"\tb 0b\n" +"\n" +"1:\t/* Prepare the stack. */\n" +"\tadr_l x30, boot_stack_end\n" +"\tmov sp, x30\n" +"\n" +"\t/* Set up exception vector. */\n" +"\tadr x30, vector_table_el1\n" +"\tmsr vbar_el1, x30\n" +"\n" +"\t/* Call into Rust code. */\n" +"\tbl main\n" +"\n" +"\t/* Loop forever waiting for interrupts. */\n" +"2:\twfi\n" +"\tb 2b\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:590 +msgid "`exceptions.S` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:592 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:594 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +"/**\n" +" * Saves the volatile registers onto the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers with 18 instructions\n" +" * left.\n" +" *\n" +" * On return, x0 and x1 are initialised to elr_el2 and spsr_el2 respectively,\n" +" * which can be used as the first and second arguments of a subsequent call.\n" +" */\n" +".macro save_volatile_to_stack\n" +"\t/* Reserve stack space and save registers x0-x18, x29 & x30. */\n" +"\tstp x0, x1, [sp, #-(8 * 24)]!\n" +"\tstp x2, x3, [sp, #8 * 2]\n" +"\tstp x4, x5, [sp, #8 * 4]\n" +"\tstp x6, x7, [sp, #8 * 6]\n" +"\tstp x8, x9, [sp, #8 * 8]\n" +"\tstp x10, x11, [sp, #8 * 10]\n" +"\tstp x12, x13, [sp, #8 * 12]\n" +"\tstp x14, x15, [sp, #8 * 14]\n" +"\tstp x16, x17, [sp, #8 * 16]\n" +"\tstr x18, [sp, #8 * 18]\n" +"\tstp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/*\n" +"\t * Save elr_el1 & spsr_el1. This such that we can take nested exception\n" +"\t * and still be able to unwind.\n" +"\t */\n" +"\tmrs x0, elr_el1\n" +"\tmrs x1, spsr_el1\n" +"\tstp x0, x1, [sp, #8 * 22]\n" +".endm\n" +"\n" +"/**\n" +" * Restores the volatile registers from the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers while still leaving 18\n" +" * instructions left; if paired with save_volatile_to_stack, there are 4\n" +" * instructions to spare.\n" +" */\n" +".macro restore_volatile_from_stack\n" +"\t/* Restore registers x2-x18, x29 & x30. */\n" +"\tldp x2, x3, [sp, #8 * 2]\n" +"\tldp x4, x5, [sp, #8 * 4]\n" +"\tldp x6, x7, [sp, #8 * 6]\n" +"\tldp x8, x9, [sp, #8 * 8]\n" +"\tldp x10, x11, [sp, #8 * 10]\n" +"\tldp x12, x13, [sp, #8 * 12]\n" +"\tldp x14, x15, [sp, #8 * 14]\n" +"\tldp x16, x17, [sp, #8 * 16]\n" +"\tldr x18, [sp, #8 * 18]\n" +"\tldp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/* Restore registers elr_el1 & spsr_el1, using x0 & x1 as scratch. */\n" +"\tldp x0, x1, [sp, #8 * 22]\n" +"\tmsr elr_el1, x0\n" +"\tmsr spsr_el1, x1\n" +"\n" +"\t/* Restore x0 & x1, and release stack space. */\n" +"\tldp x0, x1, [sp], #8 * 24\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while using\n" +" * SP0. It behaves similarly to the SPx case by first switching to SPx, doing\n" +" * the work, then switching back to SP0 before returning.\n" +" *\n" +" * Switching to SPx and calling the Rust handler takes 16 instructions. To\n" +" * restore and return we need an additional 16 instructions, so we can implement\n" +" * the whole handler within the allotted 32 instructions.\n" +" */\n" +".macro current_exception_sp0 handler:req\n" +"\tmsr spsel, #1\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\tmsr spsel, #0\n" +"\teret\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while using\n" +" * SPx. It saves volatile registers, calls the Rust handler, restores volatile\n" +" * registers, then returns.\n" +" *\n" +" * This also works for exceptions taken from EL0, if we don't care about\n" +" * non-volatile registers.\n" +" *\n" +" * Saving state and jumping to the Rust handler takes 15 instructions, and\n" +" * restoring and returning also takes 15 instructions, so we can fit the whole\n" +" * handler in 30 instructions, under the limit of 32.\n" +" */\n" +".macro current_exception_spx handler:req\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\teret\n" +".endm\n" +"\n" +".section .text.vector_table_el1, \"ax\"\n" +".global vector_table_el1\n" +".balign 0x800\n" +"vector_table_el1:\n" +"sync_cur_sp0:\n" +"\tcurrent_exception_sp0 sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_sp0:\n" +"\tcurrent_exception_sp0 irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_sp0:\n" +"\tcurrent_exception_sp0 fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_sp0:\n" +"\tcurrent_exception_sp0 serr_current\n" +"\n" +".balign 0x80\n" +"sync_cur_spx:\n" +"\tcurrent_exception_spx sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_spx:\n" +"\tcurrent_exception_spx irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_spx:\n" +"\tcurrent_exception_spx fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_spx:\n" +"\tcurrent_exception_spx serr_current\n" +"\n" +".balign 0x80\n" +"sync_lower_64:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_64:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_64:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_64:\n" +"\tcurrent_exception_spx serr_lower\n" +"\n" +".balign 0x80\n" +"sync_lower_32:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_32:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_32:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_32:\n" +"\tcurrent_exception_spx serr_lower\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:775 +msgid "`idmap.S` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:777 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:779 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".set .L_TT_TYPE_BLOCK, 0x1\n" +".set .L_TT_TYPE_PAGE, 0x3\n" +".set .L_TT_TYPE_TABLE, 0x3\n" +"\n" +"/* Access flag. */\n" +".set .L_TT_AF, 0x1 << 10\n" +"/* Not global. */\n" +".set .L_TT_NG, 0x1 << 11\n" +".set .L_TT_XN, 0x3 << 53\n" +"\n" +".set .L_TT_MT_DEV, 0x0 << 2\t\t\t// MAIR #0 (DEV_nGnRE)\n" +".set .L_TT_MT_MEM, (0x1 << 2) | (0x3 << 8)\t// MAIR #1 (MEM_WBWA), inner shareable\n" +"\n" +".set .L_BLOCK_DEV, .L_TT_TYPE_BLOCK | .L_TT_MT_DEV | .L_TT_AF | .L_TT_XN\n" +".set .L_BLOCK_MEM, .L_TT_TYPE_BLOCK | .L_TT_MT_MEM | .L_TT_AF | .L_TT_NG\n" +"\n" +".section \".rodata.idmap\", \"a\", %progbits\n" +".global idmap\n" +".align 12\n" +"idmap:\n" +"\t/* level 1 */\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x0\t\t // 1 GiB of device mappings\n" +"\t.quad\t\t.L_BLOCK_MEM | 0x40000000\t// 1 GiB of DRAM\n" +"\t.fill\t\t254, 8, 0x0\t\t\t// 254 GiB of unmapped VA space\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x4000000000 // 1 GiB of device mappings\n" +"\t.fill\t\t255, 8, 0x0\t\t\t// 255 GiB of remaining VA space\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:824 +msgid "`image.ld` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:826 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:828 +msgid "" +"```ld\n" +"/*\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" +" * https://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" +"\n" +"/*\n" +" * Code will start running at this symbol which is placed at the start of the\n" +" * image.\n" +" */\n" +"ENTRY(entry)\n" +"\n" +"MEMORY\n" +"{\n" +"\timage : ORIGIN = 0x40080000, LENGTH = 2M\n" +"}\n" +"\n" +"SECTIONS\n" +"{\n" +"\t/*\n" +"\t * Collect together the code.\n" +"\t */\n" +"\t.init : ALIGN(4096) {\n" +"\t\ttext_begin = .;\n" +"\t\t*(.init.entry)\n" +"\t\t*(.init.*)\n" +"\t} >image\n" +"\t.text : {\n" +"\t\t*(.text.*)\n" +"\t} >image\n" +"\ttext_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together read-only data.\n" +"\t */\n" +"\t.rodata : ALIGN(4096) {\n" +"\t\trodata_begin = .;\n" +"\t\t*(.rodata.*)\n" +"\t} >image\n" +"\t.got : {\n" +"\t\t*(.got)\n" +"\t} >image\n" +"\trodata_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together the read-write data including .bss at the end which\n" +"\t * will be zero'd by the entry code.\n" +"\t */\n" +"\t.data : ALIGN(4096) {\n" +"\t\tdata_begin = .;\n" +"\t\t*(.data.*)\n" +"\t\t/*\n" +"\t\t * The entry point code assumes that .data is a multiple of 32\n" +"\t\t * bytes long.\n" +"\t\t */\n" +"\t\t. = ALIGN(32);\n" +"\t\tdata_end = .;\n" +"\t} >image\n" +"\n" +"\t/* Everything beyond this point will not be included in the binary. */\n" +"\tbin_end = .;\n" +"\n" +"\t/* The entry point code assumes that .bss is 16-byte aligned. */\n" +"\t.bss : ALIGN(16) {\n" +"\t\tbss_begin = .;\n" +"\t\t*(.bss.*)\n" +"\t\t*(COMMON)\n" +"\t\t. = ALIGN(16);\n" +"\t\tbss_end = .;\n" +"\t} >image\n" +"\n" +"\t.stack (NOLOAD) : ALIGN(4096) {\n" +"\t\tboot_stack_begin = .;\n" +"\t\t. += 40 * 4096;\n" +"\t\t. = ALIGN(4096);\n" +"\t\tboot_stack_end = .;\n" +"\t} >image\n" +"\n" +"\t. = ALIGN(4K);\n" +"\tPROVIDE(dma_region = .);\n" +"\n" +"\t/*\n" +"\t * Remove unused sections from the image.\n" +"\t */\n" +"\t/DISCARD/ : {\n" +"\t\t/* The image loads itself so doesn't need these sections. */\n" +"\t\t*(.gnu.hash)\n" +"\t\t*(.hash)\n" +"\t\t*(.interp)\n" +"\t\t*(.eh_frame_hdr)\n" +"\t\t*(.eh_frame)\n" +"\t\t*(.note.gnu.build-id)\n" +"\t}\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:935 +msgid "`Makefile` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:937 +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:939 +msgid "" +"```makefile\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" +"UNAME := $(shell uname -s)\n" +"ifeq ($(UNAME),Linux)\n" +"\tTARGET = aarch64-linux-gnu\n" +"else\n" +"\tTARGET = aarch64-none-elf\n" +"endif\n" +"OBJCOPY = $(TARGET)-objcopy\n" +"\n" +".PHONY: build qemu_minimal qemu qemu_logger\n" +"\n" +"all: rtc.bin\n" +"\n" +"build:\n" +"\tcargo build\n" +"\n" +"rtc.bin: build\n" +"\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 " +"$< -s\n" +"\n" +"clean:\n" +"\tcargo clean\n" +"\trm -f *.bin\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:984 +msgid "" +"```toml\n" +"[build]\n" +"target = \"aarch64-unknown-none\"\n" +"rustflags = [\"-C\", \"link-arg=-Timage.ld\"]\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:990 +msgid "Run the code in QEMU with `make qemu`." +msgstr "" + +#: src/exercises/solutions.md:1 +#, fuzzy +msgid "# Solutions" +msgstr "# Lösungen" + +#: src/exercises/solutions.md:3 +#, fuzzy +msgid "You will find solutions to the exercises on the following pages." +msgstr "Auf den folgenden Seiten finden Sie Lösungen zu den Aufgaben." + +#: src/exercises/solutions.md:5 +#, fuzzy +msgid "" +"Feel free to ask questions about the solutions [on\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Let us know\n" +"if you have a different or better solution than what is presented here." +msgstr "" +"Fühlen Sie sich frei, Fragen zu den Lösungen zu stellen [on\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Lass uns wissen\n" +"wenn Sie eine andere oder bessere Lösung als die hier vorgestellte haben." + +#: src/exercises/solutions.md:10 +#, fuzzy +msgid "" +"> **Note:** Please ignore the `// ANCHOR: label` and `// ANCHOR_END: label`\n" +"> comments you see in the solutions. They are there to make it possible to\n" +"> re-use parts of the solutions as the exercises." +msgstr "" +"> **Hinweis:** Bitte ignorieren Sie `// ANCHOR: label` und `// ANCHOR_END: label`\n" +"> Kommentare, die Sie in den Lösungen sehen. Sie sind da, um es zu ermöglichen\n" +"> Teile der Lösungen als Aufgaben wiederverwenden." + +#: src/exercises/day-1/solutions-morning.md:1 +#, fuzzy +msgid "# Day 1 Morning Exercises" +msgstr "# Tag 1 Morgengymnastik" + +#: src/exercises/day-1/solutions-morning.md:3 +#, fuzzy +msgid "## Arrays and `for` Loops" +msgstr "## Arrays und „for“-Schleifen" + +#: src/exercises/day-1/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](for-loops.md))" +msgstr "([zurück zur Übung](for-loops.md))" + +#: src/exercises/day-1/solutions-morning.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: transpose\n" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" // ANCHOR_END: transpose\n" +" let mut result = [[0; 3]; 3];\n" +" for i in 0..3 {\n" +" for j in 0..3 {\n" +" result[j][i] = matrix[i][j];\n" +" }\n" +" }\n" +" return result;\n" +"}\n" +"\n" +"// ANCHOR: pretty_print\n" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" // ANCHOR_END: pretty_print\n" +" for row in matrix {\n" +" println!(\"{row:?}\");\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: tests\n" +"#[test]\n" +"fn test_transpose() {\n" +" let matrix = [\n" +" [101, 102, 103], //\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +" let transposed = transpose(matrix);\n" +" assert_eq!(\n" +" transposed,\n" +" [\n" +" [101, 201, 301], //\n" +" [102, 202, 302],\n" +" [103, 203, 303],\n" +" ]\n" +" );\n" +"}\n" +"// ANCHOR_END: tests\n" +"\n" +"// ANCHOR: main\n" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:78 +msgid "### Bonus question" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:80 +#, fuzzy +msgid "" +"It requires more advanced concepts. It might seem that we could use a slice-of-slices " +"(`&[&[i32]]`) as the input type to transpose and thus make our function handle any size of matrix. " +"However, this quickly breaks down: the return type cannot be `&[&[i32]]` since it needs to own the " +"data you return." +msgstr "" +"Es funktioniert ehrlich gesagt nicht so gut. Es scheint, als könnten wir ein Slice-of-Slices " +"(`&[&[i32]]`) als Eingabetyp für die Transponierung verwenden und unsere Funktion so dazu bringen, " +"jede Matrixgröße zu handhaben. Dies bricht jedoch schnell zusammen: Der Rückgabetyp kann nicht " +"`&[&[i32]]` sein, da er die von Ihnen zurückgegebenen Daten besitzen muss." + +#: src/exercises/day-1/solutions-morning.md:82 +#, fuzzy +msgid "" +"You can attempt to use something like `Vec>`, but this doesn't work out-of-the-box " +"either: it's hard to convert from `Vec>` to `&[&[i32]]` so now you cannot easily use " +"`pretty_print` either." +msgstr "" +"Sie können versuchen, so etwas wie `Vec>` zu verwenden, aber das funktioniert auch nicht " +"sehr gut: Es ist schwierig, `Vec>` in `&[&[i32]] umzuwandeln. ` also kannst du jetzt auch " +"`pretty_print` nicht einfach verwenden." + +#: src/exercises/day-1/solutions-morning.md:84 +msgid "" +"Once we get to traits and generics, we'll be able to use the [`std::convert::AsRef`][1] trait to " +"abstract over anything that can be referenced as a slice." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:86 +msgid "" +"```rust\n" +"use std::convert::AsRef;\n" +"use std::fmt::Debug;\n" +"\n" +"fn pretty_print(matrix: Matrix)\n" +"where\n" +" T: Debug,\n" +" // A line references a slice of items\n" +" Line: AsRef<[T]>,\n" +" // A matrix references a slice of lines\n" +" Matrix: AsRef<[Line]>\n" +"{\n" +" for row in matrix.as_ref() {\n" +" println!(\"{:?}\", row.as_ref());\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" // &[&[i32]]\n" +" pretty_print(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" +" // [[&str; 2]; 2]\n" +" pretty_print([[\"a\", \"b\"], [\"c\", \"d\"]]);\n" +" // Vec>\n" +" pretty_print(vec![vec![1, 2], vec![3, 4]]);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:113 +#, fuzzy +msgid "" +"In addition, the type itself would not enforce that the child slices are of the same length, so " +"such variable could contain an invalid matrix." +msgstr "" +"Außerdem würde der Typ selbst nicht erzwingen, dass die untergeordneten Slices dieselbe Länge " +"haben, sodass eine solche Variable eine ungültige Matrix enthalten könnte." + +#: src/exercises/day-1/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 1 Afternoon Exercises" +msgstr "# Tag 1 Nachmittagsübungen" + +#: src/exercises/day-1/solutions-afternoon.md:3 +#, fuzzy +msgid "## Designing a Library" +msgstr "## Entwerfen einer Bibliothek" + +#: src/exercises/day-1/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](book-library.md))" +msgstr "([zurück zur Übung](book-library.md))" + +#: src/exercises/day-1/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: setup\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// 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" +"impl Library {\n" +" fn new() -> Library {\n" +" // ANCHOR_END: Library_new\n" +" Library { books: Vec::new() }\n" +" }\n" +"\n" +" // ANCHOR: Library_len\n" +" //fn len(self) -> usize {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_len\n" +" fn len(&self) -> usize {\n" +" self.books.len()\n" +" }\n" +"\n" +" // ANCHOR: Library_is_empty\n" +" //fn is_empty(self) -> bool {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_is_empty\n" +" fn is_empty(&self) -> bool {\n" +" self.books.is_empty()\n" +" }\n" +"\n" +" // ANCHOR: Library_add_book\n" +" //fn add_book(self, book: Book) {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_add_book\n" +" fn add_book(&mut self, book: Book) {\n" +" self.books.push(book)\n" +" }\n" +"\n" +" // ANCHOR: Library_print_books\n" +" //fn print_books(self) {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_print_books\n" +" fn print_books(&self) {\n" +" for book in &self.books {\n" +" println!(\"{}\", book);\n" +" }\n" +" }\n" +"\n" +" // ANCHOR: Library_oldest_book\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // unimplemented!()\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" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();\n" +"\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" +" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\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" +" //}\n" +" //\n" +" //println!(\"Our library has {} books\", library.len());\n" +" for book in library.books {\n" +" println!(\"{book}\");\n" +" }\n" +"}\n" +"// ANCHOR_END: main\n" +"\n" +"#[test]\n" +"fn test_library_len() {\n" +" let mut library = Library::new();\n" +" assert_eq!(library.len(), 0);\n" +" assert!(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" +" assert_eq!(library.len(), 2);\n" +" assert!(!library.is_empty());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_is_empty() {\n" +" let mut library = Library::new();\n" +" assert!(library.is_empty());\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert!(!library.is_empty());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_print_books() {\n" +" let mut library = Library::new();\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" // We could try and capture stdout, but let us just call the\n" +" // method to start with.\n" +" library.print_books();\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_oldest_book() {\n" +" let mut library = Library::new();\n" +" assert!(library.oldest_book().is_none());\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Lord of the Rings\")\n" +" );\n" +"\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Alice's Adventures in Wonderland\")\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:1 +#, fuzzy +msgid "# Day 2 Morning Exercises" +msgstr "# Tag 2 Morgengymnastik" + +#: src/exercises/day-2/solutions-morning.md:3 +#, fuzzy +msgid "## Points and Polygons" +msgstr "## Punkte und Polygone" + +#: src/exercises/day-2/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](points-polygons.md))" +msgstr "([zurück zur Übung](points-polygons.md))" + +#: src/exercises/day-2/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" +"#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" +"// ANCHOR: Point\n" +"pub struct Point {\n" +" // ANCHOR_END: Point\n" +" x: i32,\n" +" y: i32,\n" +"}\n" +"\n" +"// ANCHOR: Point-impl\n" +"impl Point {\n" +" // ANCHOR_END: Point-impl\n" +" pub fn new(x: i32, y: i32) -> Point {\n" +" Point { x, y }\n" +" }\n" +"\n" +" pub fn magnitude(self) -> f64 {\n" +" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +" }\n" +"\n" +" pub fn dist(self, other: Point) -> f64 {\n" +" (self - other).magnitude()\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x + other.x,\n" +" y: self.y + other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Sub for Point {\n" +" type Output = Self;\n" +"\n" +" fn sub(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x - other.x,\n" +" y: self.y - other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Polygon\n" +"pub struct Polygon {\n" +" // ANCHOR_END: Polygon\n" +" points: Vec,\n" +"}\n" +"\n" +"// ANCHOR: Polygon-impl\n" +"impl Polygon {\n" +" // ANCHOR_END: Polygon-impl\n" +" pub fn new() -> Polygon {\n" +" Polygon { points: Vec::new() }\n" +" }\n" +"\n" +" pub fn add_point(&mut self, point: Point) {\n" +" self.points.push(point);\n" +" }\n" +"\n" +" pub fn left_most_point(&self) -> Option {\n" +" self.points.iter().min_by_key(|p| p.x).copied()\n" +" }\n" +"\n" +" pub fn iter(&self) -> impl Iterator {\n" +" self.points.iter()\n" +" }\n" +"\n" +" pub fn length(&self) -> f64 {\n" +" if self.points.is_empty() {\n" +" return 0.0;\n" +" }\n" +"\n" +" let mut result = 0.0;\n" +" let mut last_point = self.points[0];\n" +" for point in &self.points[1..] {\n" +" result += last_point.dist(*point);\n" +" last_point = *point;\n" +" }\n" +" result += last_point.dist(self.points[0]);\n" +" result\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Circle\n" +"pub struct Circle {\n" +" // ANCHOR_END: Circle\n" +" center: Point,\n" +" radius: i32,\n" +"}\n" +"\n" +"// ANCHOR: Circle-impl\n" +"impl Circle {\n" +" // ANCHOR_END: Circle-impl\n" +" pub fn new(center: Point, radius: i32) -> Circle {\n" +" Circle { center, radius }\n" +" }\n" +"\n" +" pub fn circumference(&self) -> f64 {\n" +" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +" }\n" +"\n" +" pub fn dist(&self, other: &Self) -> f64 {\n" +" self.center.dist(other.center)\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Shape\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"// ANCHOR_END: Shape\n" +"\n" +"impl From for Shape {\n" +" fn from(poly: Polygon) -> Self {\n" +" Shape::Polygon(poly)\n" +" }\n" +"}\n" +"\n" +"impl From for Shape {\n" +" fn from(circle: Circle) -> Self {\n" +" Shape::Circle(circle)\n" +" }\n" +"}\n" +"\n" +"impl Shape {\n" +" pub fn perimeter(&self) -> f64 {\n" +" match self {\n" +" Shape::Polygon(poly) => poly.length(),\n" +" Shape::Circle(circle) => circle.circumference(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 2 Afternoon Exercises" +msgstr "# Tag 2 Nachmittagsübungen" + +#: src/exercises/day-2/solutions-afternoon.md:3 +#, fuzzy +msgid "## Luhn Algorithm" +msgstr "## Luhn-Algorithmus" + +#: src/exercises/day-2/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](luhn.md))" +msgstr "([zurück zur Übung](luhn.md))" + +#: src/exercises/day-2/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: luhn\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" // ANCHOR_END: luhn\n" +" let mut digits_seen = 0;\n" +" let mut sum = 0;\n" +" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ').enumerate() {\n" +" match ch.to_digit(10) {\n" +" Some(d) => {\n" +" sum += if i % 2 == 1 {\n" +" let dd = d * 2;\n" +" dd / 10 + dd % 10\n" +" } else {\n" +" d\n" +" };\n" +" digits_seen += 1;\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +"\n" +" if digits_seen < 2 {\n" +" return false;\n" +" }\n" +"\n" +" sum % 10 == 0\n" +"}\n" +"\n" +"fn main() {\n" +" let cc_number = \"1234 5678 1234 5670\";\n" +" println!(\n" +" \"Is {cc_number} a valid credit card number? {}\",\n" +" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" +" );\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:97 +#, fuzzy +msgid "## Strings and Iterators" +msgstr "## Strings und Iteratoren" + +#: src/exercises/day-2/solutions-afternoon.md:99 +#, fuzzy +msgid "([back to exercise](strings-iterators.md))" +msgstr "([zurück zur Übung](strings-iterators.md))" + +#: src/exercises/day-2/solutions-afternoon.md:101 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: prefix_matches\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" // ANCHOR_END: prefix_matches\n" +" let prefixes = prefix.split('/');\n" +" let request_paths = request_path\n" +" .split('/')\n" +" .map(|p| Some(p))\n" +" .chain(std::iter::once(None));\n" +"\n" +" for (prefix, request_path) in prefixes.zip(request_paths) {\n" +" match request_path {\n" +" Some(request_path) => {\n" +" if (prefix != \"*\") && (prefix != request_path) {\n" +" return false;\n" +" }\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +" true\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:1 +#, fuzzy +msgid "# Day 3 Morning Exercise" +msgstr "# Tag 3 Morgengymnastik" + +#: src/exercises/day-3/solutions-morning.md:3 +#, fuzzy +msgid "## A Simple GUI Library" +msgstr "## Eine einfache GUI-Bibliothek" + +#: src/exercises/day-3/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](simple-gui.md))" +msgstr "([zurück zur Übung](simple-gui.md))" + +#: src/exercises/day-3/solutions-morning.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: setup\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"\n" +" fn inner_width(&self) -> usize {\n" +" std::cmp::max(\n" +" self.title.chars().count(),\n" +" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +" )\n" +" }\n" +"}\n" +"\n" +"// ANCHOR_END: setup\n" +"\n" +"// ANCHOR: Window-width\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" // ANCHOR_END: Window-width\n" +" // Add 4 paddings for borders\n" +" self.inner_width() + 4\n" +" }\n" +"\n" +" // ANCHOR: Window-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Window-draw_into\n" +" let mut inner = String::new();\n" +" for widget in &self.widgets {\n" +" widget.draw_into(&mut inner);\n" +" }\n" +"\n" +" let inner_width = self.inner_width();\n" +"\n" +" // TODO: after learning about error handling, you can change\n" +" // draw_into to return Result<(), std::fmt::Error>. Then use\n" +" // the ?-operator here instead of .unwrap().\n" +" writeln!(buffer, \"+-{:- usize {\n" +" // ANCHOR_END: Button-width\n" +" self.label.width() + 8 // add a bit of padding\n" +" }\n" +"\n" +" // ANCHOR: Button-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Button-draw_into\n" +" let width = self.width();\n" +" let mut label = String::new();\n" +" self.label.draw_into(&mut label);\n" +"\n" +" writeln!(buffer, \"+{:- usize {\n" +" // ANCHOR_END: Label-width\n" +" self.label\n" +" .lines()\n" +" .map(|line| line.chars().count())\n" +" .max()\n" +" .unwrap_or(0)\n" +" }\n" +"\n" +" // ANCHOR: Label-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Label-draw_into\n" +" writeln!(buffer, \"{}\", &self.label).unwrap();\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" +"}\n" +"// ANCHOR_END: main\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 3 Afternoon Exercises" +msgstr "# Tag 3 Nachmittagsübungen" + +#: src/exercises/day-3/solutions-afternoon.md:3 +#, fuzzy +msgid "## Safe FFI Wrapper" +msgstr "## Sicherer FFI-Wrapper" + +#: src/exercises/day-3/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](safe-ffi-wrapper.md))" +msgstr "([zurück zur Übung](safe-ffi-wrapper.md))" + +#: src/exercises/day-3/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: ffi\n" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int};\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" use std::os::raw::{c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" // Layout as per man entry for dirent\n" +" #[cfg(target_os = \"macos\")]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: u64,\n" +" pub d_seekoff: u64,\n" +" pub d_reclen: u16,\n" +" pub d_namlen: u16,\n" +" pub d_type: u8,\n" +" pub d_name: [c_char; 1024],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}\n" +"// ANCHOR_END: ffi\n" +"\n" +"// ANCHOR: DirectoryIterator\n" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" // ANCHOR_END: DirectoryIterator\n" +" let path = CString::new(path).map_err(|err| format!(\"Invalid path: {err}\"))?;\n" +" // SAFETY: path.as_ptr() cannot be NULL.\n" +" let dir = unsafe { ffi::opendir(path.as_ptr()) };\n" +" if dir.is_null() {\n" +" Err(format!(\"Could not open {:?}\", path))\n" +" } else {\n" +" Ok(DirectoryIterator { path, dir })\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Iterator\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" // ANCHOR_END: Iterator\n" +" // SAFETY: self.dir is never NULL.\n" +" let dirent = unsafe { ffi::readdir(self.dir) };\n" +" if dirent.is_null() {\n" +" // We have reached the end of the directory.\n" +" return None;\n" +" }\n" +" // SAFETY: dirent is not NULL and dirent.d_name is NUL\n" +" // terminated.\n" +" let d_name = unsafe { CStr::from_ptr((*dirent).d_name.as_ptr()) };\n" +" let os_str = OsStr::from_bytes(d_name.to_bytes());\n" +" Some(os_str.to_owned())\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Drop\n" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" // ANCHOR_END: Drop\n" +" if !self.dir.is_null() {\n" +" // SAFETY: self.dir is not NULL.\n" +" if unsafe { ffi::closedir(self.dir) } != 0 {\n" +" panic!(\"Could not close {:?}\", self.path);\n" +" }\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"// ANCHOR_END: main\n" +"```" +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 "" -"impl From for Shape {\n" -" fn from(poly: Polygon) -> Self {\n" -" Shape::Polygon(poly)\n" +"```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/bare-metal/solutions-morning.md:1 +#, fuzzy +msgid "# Bare Metal Rust Morning Exercise" +msgstr "# Tag 3 Morgengymnastik" + +#: src/exercises/bare-metal/solutions-morning.md:3 +#, fuzzy +msgid "## Compass" +msgstr "# Vergleich" + +#: src/exercises/bare-metal/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](compass.md))" +msgstr "([zurück zur Übung](for-loops.md))" + +#: src/exercises/bare-metal/solutions-morning.md:7 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"// ANCHOR_END: top\n" +"use core::cmp::{max, min};\n" +"use lsm303agr::{AccelOutputDataRate, Lsm303agr, MagOutputDataRate};\n" +"use microbit::display::blocking::Display;\n" +"use microbit::hal::prelude::*;\n" +"use microbit::hal::twim::Twim;\n" +"use microbit::hal::uarte::{Baudrate, Parity, Uarte};\n" +"use microbit::hal::Timer;\n" +"use microbit::pac::twim0::frequency::FREQUENCY_A;\n" +"use microbit::Board;\n" +"\n" +"const COMPASS_SCALE: i32 = 30000;\n" +"const ACCELEROMETER_SCALE: i32 = 700;\n" +"\n" +"// ANCHOR: main\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // ANCHOR_END: main\n" +" writeln!(serial, \"Setting up IMU...\").unwrap();\n" +" let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100);\n" +" let mut imu = Lsm303agr::new_with_i2c(i2c);\n" +" imu.init().unwrap();\n" +" imu.set_mag_odr(MagOutputDataRate::Hz50).unwrap();\n" +" imu.set_accel_odr(AccelOutputDataRate::Hz50).unwrap();\n" +" let mut imu = imu.into_mag_continuous().ok().unwrap();\n" +"\n" +" // Set up display and timer.\n" +" let mut timer = Timer::new(board.TIMER0);\n" +" let mut display = Display::new(board.display_pins);\n" +"\n" +" let mut mode = Mode::Compass;\n" +" let mut button_pressed = false;\n" +"\n" +" // ANCHOR: loop\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // ANCHOR_END: loop\n" +" while !(imu.mag_status().unwrap().xyz_new_data\n" +" && imu.accel_status().unwrap().xyz_new_data)\n" +" {}\n" +" let compass_reading = imu.mag_data().unwrap();\n" +" let accelerometer_reading = imu.accel_data().unwrap();\n" +" writeln!(\n" +" serial,\n" +" \"{},{},{}\\t{},{},{}\",\n" +" compass_reading.x,\n" +" compass_reading.y,\n" +" compass_reading.z,\n" +" accelerometer_reading.x,\n" +" accelerometer_reading.y,\n" +" accelerometer_reading.z,\n" +" )\n" +" .unwrap();\n" +"\n" +" let mut image = [[0; 5]; 5];\n" +" let (x, y) = match mode {\n" +" Mode::Compass => (\n" +" scale(-compass_reading.x, -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize,\n" +" scale(compass_reading.y, -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize,\n" +" ),\n" +" Mode::Accelerometer => (\n" +" scale(\n" +" accelerometer_reading.x,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" scale(\n" +" -accelerometer_reading.y,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" ),\n" +" };\n" +" image[y][x] = 255;\n" +" display.show(&mut timer, image, 100);\n" +"\n" +" // If button A is pressed, switch to the next mode and briefly blink all LEDs on.\n" +" if board.buttons.button_a.is_low().unwrap() {\n" +" if !button_pressed {\n" +" mode = mode.next();\n" +" display.show(&mut timer, [[255; 5]; 5], 200);\n" +" }\n" +" button_pressed = true;\n" +" } else {\n" +" button_pressed = false;\n" +" }\n" +" }\n" +"}\n" +"\n" +"#[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +"enum Mode {\n" +" Compass,\n" +" Accelerometer,\n" +"}\n" +"\n" +"impl Mode {\n" +" fn next(self) -> Self {\n" +" match self {\n" +" Self::Compass => Self::Accelerometer,\n" +" Self::Accelerometer => Self::Compass,\n" +" }\n" +" }\n" +"}\n" +"\n" +"fn scale(value: i32, min_in: i32, max_in: i32, min_out: i32, max_out: i32) -> i32 {\n" +" let range_in = max_in - min_in;\n" +" let range_out = max_out - min_out;\n" +" cap(\n" +" min_out + range_out * (value - min_in) / range_in,\n" +" min_out,\n" +" max_out,\n" +" )\n" +"}\n" +"\n" +"fn cap(value: i32, min_value: i32, max_value: i32) -> i32 {\n" +" max(min_value, min(value, max_value))\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:1 +msgid "# Bare Metal Rust Afternoon" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:3 +msgid "## RTC driver" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](rtc.md))" +msgstr "([zurück zur Übung](luhn.md))" + +#: src/exercises/bare-metal/solutions-afternoon.md:7 +msgid "`main.rs`:" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:9 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"// ANCHOR_END: top\n" +"mod pl031;\n" +"\n" +"use crate::pl031::Rtc;\n" +"use arm_gic::gicv3::{IntId, Trigger};\n" +"use arm_gic::{irq_enable, wfi};\n" +"use chrono::{TimeZone, Utc};\n" +"use core::hint::spin_loop;\n" +"// ANCHOR: imports\n" +"use crate::pl011::Uart;\n" +"use arm_gic::gicv3::GicV3;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, trace, LevelFilter};\n" +"use psci::system_off;\n" +"\n" +"/// Base addresses of the GICv3.\n" +"const GICD_BASE_ADDRESS: *mut u64 = 0x800_0000 as _;\n" +"const GICR_BASE_ADDRESS: *mut u64 = 0x80A_0000 as _;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"// ANCHOR_END: imports\n" +"\n" +"/// Base address of the PL031 RTC.\n" +"const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;\n" +"/// The IRQ used by the PL031 RTC.\n" +"const PL031_IRQ: IntId = IntId::spi(2);\n" +"\n" +"// ANCHOR: main\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +"\n" +" // Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base\n" +" // addresses of a GICv3 distributor and redistributor respectively, and\n" +" // nothing else accesses those address ranges.\n" +" let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, GICR_BASE_ADDRESS) };\n" +" gic.setup();\n" +" // ANCHOR_END: main\n" +"\n" +" // Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 device,\n" +" // and nothing else accesses that address range.\n" +" let mut rtc = unsafe { Rtc::new(PL031_BASE_ADDRESS) };\n" +" let timestamp = rtc.read();\n" +" let time = Utc.timestamp_opt(timestamp.into(), 0).unwrap();\n" +" info!(\"RTC: {time}\");\n" +"\n" +" GicV3::set_priority_mask(0xff);\n" +" gic.set_interrupt_priority(PL031_IRQ, 0x80);\n" +" gic.set_trigger(PL031_IRQ, Trigger::Level);\n" +" irq_enable();\n" +" gic.enable_interrupt(PL031_IRQ, true);\n" +"\n" +" // Wait for 3 seconds, without interrupts.\n" +" let target = timestamp + 3;\n" +" rtc.set_match(target);\n" +" info!(\n" +" \"Waiting for {}\",\n" +" Utc.timestamp_opt(target.into(), 0).unwrap()\n" +" );\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" while !rtc.matched() {\n" +" spin_loop();\n" +" }\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" info!(\"Finished waiting\");\n" +"\n" +" // Wait another 3 seconds for an interrupt.\n" +" let target = timestamp + 6;\n" +" info!(\n" +" \"Waiting for {}\",\n" +" Utc.timestamp_opt(target.into(), 0).unwrap()\n" +" );\n" +" rtc.set_match(target);\n" +" rtc.clear_interrupt();\n" +" rtc.enable_interrupt(true);\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" while !rtc.interrupt_pending() {\n" +" wfi();\n" +" }\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" info!(\"Finished waiting\");\n" +"\n" +" // ANCHOR: main_end\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off().unwrap();\n" +" loop {}\n" +"}\n" +"// ANCHOR_END: main_end\n" +"```" msgstr "" -"impl From für Form {\n" -" fn from(poly: Polygon) -> Self {\n" -" Form::Polygon (poly)\n" -" }\n" -"}" -#: src/exercises/day-2/solutions-morning.md:145 -#, fuzzy -msgid "" -"impl From for Shape {\n" -" fn from(circle: Circle) -> Self {\n" -" Shape::Circle(circle)\n" -" }\n" -"}" +#: src/exercises/bare-metal/solutions-afternoon.md:148 +msgid "`pl031.rs`:" msgstr "" -"impl Von für Form {\n" -" fn from(Kreis: Kreis) -> Selbst {\n" -" Form :: Kreis (Kreis)\n" -" }\n" -"}" -#: src/exercises/day-2/solutions-morning.md:151 -#, fuzzy +#: src/exercises/bare-metal/solutions-afternoon.md:150 msgid "" -"impl Shape {\n" -" pub fn perimeter(&self) -> f64 {\n" -" match self {\n" -" Shape::Polygon(poly) => poly.length(),\n" -" Shape::Circle(circle) => circle.circumference(),\n" +"```rust\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"use core::ptr::{addr_of, addr_of_mut};\n" +"\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" /// Data register\n" +" dr: u32,\n" +" /// Match register\n" +" mr: u32,\n" +" /// Load register\n" +" lr: u32,\n" +" /// Control register\n" +" cr: u8,\n" +" _reserved0: [u8; 3],\n" +" /// Interrupt Mask Set or Clear register\n" +" imsc: u8,\n" +" _reserved1: [u8; 3],\n" +" /// Raw Interrupt Status\n" +" ris: u8,\n" +" _reserved2: [u8; 3],\n" +" /// Masked Interrupt Status\n" +" mis: u8,\n" +" _reserved3: [u8; 3],\n" +" /// Interrupt Clear Register\n" +" icr: u8,\n" +" _reserved4: [u8; 3],\n" +"}\n" +"\n" +"/// Driver for a PL031 real-time clock.\n" +"#[derive(Debug)]\n" +"pub struct Rtc {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Rtc {\n" +" /// Constructs a new instance of the RTC driver for a PL031 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of a\n" +" /// PL031 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" " }\n" " }\n" -"}" -msgstr "" -"Impl-Form {\n" -" pub fn perimeter(&self) -> f64 {\n" -" mit sich selbst übereinstimmen {\n" -" Shape::Polygon(poly) => poly.length(),\n" -" Form::Kreis(Kreis) => Kreis.Umfang(),\n" -" }\n" +"\n" +" /// Reads the current RTC value.\n" +" pub fn read(&self) -> u32 {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).dr).read_volatile() }\n" " }\n" -"}" - -#: src/exercises/day-2/solutions-morning.md:160 -msgid "" -"// ANCHOR: unit-tests\n" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:213 -msgid "" -" #[test]\n" -" fn test_shape_perimeters() {\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(Point::new(12, 13));\n" -" poly.add_point(Point::new(17, 11));\n" -" poly.add_point(Point::new(16, 16));\n" -" let shapes = vec![\n" -" Shape::from(poly),\n" -" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" -" ];\n" -" let perimeters = shapes\n" -" .iter()\n" -" .map(Shape::perimeter)\n" -" .map(round_two_digits)\n" -" .collect::>();\n" -" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +"\n" +" /// Writes a match value. When the RTC value matches this then an interrupt\n" +" /// will be generated (if it is enabled).\n" +" pub fn set_match(&mut self, value: u32) {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of_mut!((*self.registers).mr).write_volatile(value) }\n" +" }\n" +"\n" +" /// Returns whether the match register matches the RTC value, whether or not\n" +" /// the interrupt is enabled.\n" +" pub fn matched(&self) -> bool {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" let ris = unsafe { addr_of!((*self.registers).ris).read_volatile() };\n" +" (ris & 0x01) != 0\n" +" }\n" +"\n" +" /// Returns whether there is currently an interrupt pending.\n" +" ///\n" +" /// This should be true iff `matched` returns true and the interrupt is\n" +" /// masked.\n" +" pub fn interrupt_pending(&self) -> bool {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" let ris = unsafe { addr_of!((*self.registers).mis).read_volatile() };\n" +" (ris & 0x01) != 0\n" +" }\n" +"\n" +" /// Sets or clears the interrupt mask.\n" +" ///\n" +" /// When the mask is true the interrupt is enabled; when it is false the\n" +" /// interrupt is disabled.\n" +" pub fn enable_interrupt(&mut self, mask: bool) {\n" +" let imsc = if mask { 0x01 } else { 0x00 };\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of_mut!((*self.registers).imsc).write_volatile(imsc) }\n" +" }\n" +"\n" +" /// Clears a pending interrupt, if any.\n" +" pub fn clear_interrupt(&mut self) {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of_mut!((*self.registers).icr).write_volatile(0x01) }\n" " }\n" "}\n" -"// ANCHOR_END: unit-tests" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Rtc {}\n" +"```" msgstr "" -#: src/exercises/day-2/solutions-afternoon.md:1 #, fuzzy -msgid "# Day 2 Afternoon Exercises" -msgstr "# Tag 2 Nachmittagsübungen" +#~ 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" +#~ " * For the similar use case consider demonstrating a newly stabilized [`let else`](https://" +#~ "github.com/rust-lang/rust/pull/93628) feature.\n" +#~ "* A common usage is handling `Some` values when working with `Option`.\n" +#~ "* Unlike `match`, `if let` does not support guard clauses for pattern matching." +#~ msgstr "" +#~ "* `if let` kann prägnanter sein als `match`, z. B. wenn nur ein Fall interessant ist. Im " +#~ "Gegensatz dazu erfordert \"Match\", dass alle Zweige abgedeckt werden.\n" +#~ " * Ziehen Sie für einen ähnlichen Anwendungsfall in Betracht, eine neu stabilisierte [`let " +#~ "else`](https://github.com/rust-lang/rust/pull/93628)-Funktion zu demonstrieren.\n" +#~ "* Eine übliche Verwendung ist die Handhabung von `Some`-Werten bei der Arbeit mit `Option`.\n" +#~ "* Im Gegensatz zu `match` unterstützt `if let` keine Schutzklauseln für den Mustervergleich." + +#, fuzzy +#~ msgid "We've seen how a function can take arguments which implement a trait:" +#~ msgstr "" +#~ "Wir haben gesehen, wie eine Funktion Argumente annehmen kann, die ein Merkmal implementieren:" + +#, fuzzy +#~ msgid "However, how can we store a collection of mixed types which implement `Display`?" +#~ msgstr "" +#~ "Wie können wir jedoch eine Sammlung gemischter Typen speichern, die \"Display\" implementieren?" + +#, fuzzy +#~ msgid "For this, we need _trait objects_:" +#~ msgstr "Dafür brauchen wir _trait objects_:" + +#, fuzzy +#~ msgid "" +#~ "Similarly, you need a trait object if you want to return different types\n" +#~ "implementing a trait:" +#~ msgstr "" +#~ "Ebenso benötigen Sie ein Trait-Objekt, wenn Sie andere Werte zurückgeben möchten\n" +#~ "Implementieren eines Merkmals:" + +#~ msgid "" +#~ "1. Make yourself familiar with the course material. We've included speaker notes\n" +#~ " on some of the pages to help highlight the key points (please help us by\n" +#~ " contributing more speaker notes!). You should make sure to open the speaker\n" +#~ " notes in a popup (click the link with a little arrow next to \"Speaker\n" +#~ " Notes\"). This way you have a clean screen to present to the class." +#~ msgstr "" +#~ "1. Mach dich mit dem Kursmaterial vertraut. Wir haben Sprechernotizen an einigen \n" +#~ " Stellen hinzugefügt, um die wichtigsten Punkte hervorzuheben (du hilfts uns sehr, \n" +#~ " wenn du weitere Sprechernotizen beisteuerst!). Du solltest die Sprechernotizeb in \n" +#~ " einem Popup öffnen (klicke dazu auf dem Link mit einem kleinen Pfeil neben \n" +#~ " \"Sprechernotizen\"). Auf diese Weise präsentierst du den Kursteilnehmern nur \n" +#~ " das Kursmaterial." + +#~ msgid "" +#~ "2. 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" +#~ " they find it helpful to have a gap in the course since it helps them process\n" +#~ " all the information we give them." +#~ msgstr "" +#~ "2. Lege die Termine fest. Da der Kurs recht lang ist, empfehlen wir die 4 Tage \n" +#~ " verteilt über 2 Wochen zu legen. Bisherige Kursteilnehmer fanden es hilfreich, \n" +#~ " eine Lücke zwischen Kurstage zu haben, um das Material zu verinnerlichern." + +#~ msgid "" +#~ "3. 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" +#~ " asking questions --- it's also small enough that one instructor will have\n" +#~ " time to answer the questions." +#~ msgstr "" +#~ "3. Finde einen Raum, der groß genug für alle in Person anwesenden Teilnehmer ist. \n" +#~ " Wir empfehlen eine Kursgröße von 15-20 Personen. Das ist klein genug, dass sich \n" +#~ " die Leute wohlfühlen Fragen stellen --- und es ist auch klein genug, dass der \n" +#~ " Lehrende Zeit hat alle Fragen zu beantworten." + +#~ msgid "" +#~ "4. On the day of your course, show up to the room a little early to set things\n" +#~ " up. We recommend presenting directly using `mdbook serve` running on your\n" +#~ " laptop. This ensures optimal performance with no lag as you change pages.\n" +#~ " Using your laptop will also allow you to fix typos as you or the course\n" +#~ " participants spot them." +#~ msgstr "" +#~ "4. Erscheine am Tag des Kurses etwas früher in dem Raum, um alles vorzubereiten. \n" +#~ " Wir empfehlen, direkt `mdbook serve` auf deinem Laptop laufen zu lassen, und so \n" +#~ " den Kurz zu präsentieren. Das minimiert Verzögerungen beim Seitenwechsel und \n" +#~ " ermöglicht es, Tippfehler, die von Teilnehmern entdeckt werden, gleich währende\n" +#~ " des Kurses zu korrigieren." + +#~ msgid "" +#~ "5. Let people solve the exercises by themselves or in small groups. 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." +#~ msgstr "" +#~ "5. Lass die Teilnehmer die Übungen alleine oder in kleinen Gruppen lösen. Frage ab und zu " +#~ "nach,\n" +#~ " ob jemand nicht weiterkommt und ob es etwas gibt, wo du helfen kannst. Wenn du merkst,\n" +#~ " dass mehrere Personen die gleichen Probleme haben, solltest du dies im Kurs ansprechen\n" +#~ " und Hinweise geben, wo relevante Informationen (wie z.B. Teile der Standardbibliothek) zu \n" +#~ " finden sind." + +#~ msgid "" +#~ "[1]: https://source.android.com/docs/setup/download/downloading\n" +#~ "[2]: https://github.com/google/comprehensive-rust\n" +#~ "[3]: https://github.com/google/comprehensive-rust/discussions/86\n" +#~ "[4]: https://github.com/google/comprehensive-rust/discussions/100" +#~ msgstr "" +#~ "[1]: https://source.android.com/docs/setup/download/downloading\n" +#~ "[2]: https://github.com/google/comprehensive-rust\n" +#~ "[3]: https://github.com/google/comprehensive-rust/discussions/86\n" +#~ "[4]: https://github.com/google/comprehensive-rust/discussions/100" + +#~ msgid "" +#~ "> **Exercise for Day 4:** Do you interface with some C/C++ code in your project\n" +#~ "> which we could attempt to move to Rust? The fewer dependencies the better.\n" +#~ "> Parsing code would be ideal." +#~ msgstr "" +#~ "> **Übung für Tag 4:** Arbeitest du in deinem Projekt mit C/C++-Code,\n" +#~ "> den wir versuchen könnten nach Rust zu verschieben? Je weniger Abhängigkeiten, desto besser.\n" +#~ "> Parser-Code wäre ideal." + +#~ msgid "" +#~ "[1]: https://rust-analyzer.github.io/\n" +#~ "[2]: https://code.visualstudio.com/\n" +#~ "[3]: https://rustup.rs/\n" +#~ "[4]: https://www.jetbrains.com/clion/\n" +#~ "[5]: https://www.jetbrains.com/rust/" +#~ msgstr "" +#~ "[1]: https://rust-analyzer.github.io/\n" +#~ "[2]: https://code.visualstudio.com/\n" +#~ "[3]: https://rustup.rs/\n" +#~ "[4]: https://www.jetbrains.com/clion/\n" +#~ "[5]: https://www.jetbrains.com/rust/" + +#~ msgid "" +#~ "* `rustc`: the Rust compiler which turns `.rs` files into binaries and other\n" +#~ " intermediate formats[^rustc]." +#~ msgstr "" +#~ "* „rustc“: der Rust-Compiler, der „.rs“-Dateien in Binärdateien und andere \n" +#~ " Zwischenformate umwandelt [^rustc]." + +#, fuzzy +#~ msgid "" +#~ "* `cargo`: the Rust dependency manager and build tool. Cargo knows how to\n" +#~ " download dependencies hosted on and it will pass them to\n" +#~ " `rustc` when building your project. Cargo also comes with a built-in test\n" +#~ " runner which is used to execute unit tests[^cargo]." +#~ msgstr "" +#~ "* `cargo`: der Rust-Abhängigkeitsmanager und Build-Tool. Cargo weiß, wie es geht\n" +#~ " Laden Sie Abhängigkeiten herunter, die auf gehostet werden, und es wird " +#~ "sie an sie weitergeben\n" +#~ " `rustc`, wenn Sie Ihr Projekt erstellen. Cargo kommt auch mit einem eingebauten Test\n" +#~ " Runner, der zum Ausführen von Unit-Tests[^cargo] verwendet wird." + +#, fuzzy +#~ msgid "" +#~ "* Rust has a rapid release schedule with a new release coming out\n" +#~ " every six weeks. New releases maintain backwards compatibility with\n" +#~ " old releases --- plus they enable new functionality." +#~ msgstr "" +#~ "* Rust hat einen schnellen Veröffentlichungszeitplan mit einer neuen Veröffentlichung, die " +#~ "herauskommt\n" +#~ " alle sechs Wochen. Neue Releases behalten die Abwärtskompatibilität mit\n" +#~ " alte Versionen --- und sie ermöglichen neue Funktionen." + +#, fuzzy +#~ msgid "* There are three release channels: \"stable\", \"beta\", and \"nightly\"." +#~ msgstr "* Es gibt drei Veröffentlichungskanäle: „Stable“, „Beta“ und „Nightly“." + +#, fuzzy +#~ msgid "" +#~ "* New features are being tested on \"nightly\", \"beta\" is what becomes\n" +#~ " \"stable\" every six weeks." +#~ msgstr "" +#~ "* Neue Funktionen werden auf \"Nightly\" getestet, \"Beta\" ist das, was wird\n" +#~ " \"stabil\" alle sechs Wochen." + +#, fuzzy +#~ msgid "" +#~ "* Rust also has [editions]: the current edition is Rust 2021. Previous\n" +#~ " editions were Rust 2015 and Rust 2018." +#~ msgstr "" +#~ "* Rust hat auch [Editionen]: Die aktuelle Edition ist Rust 2021. Zurück\n" +#~ " Editionen waren Rust 2015 und Rust 2018." + +#, fuzzy +#~ msgid "" +#~ " * The editions are allowed to make backwards incompatible changes to\n" +#~ " the language." +#~ msgstr "" +#~ " * Die Editionen dürfen rückwärtsinkompatible Änderungen vornehmen\n" +#~ " die Sprache." + +#, fuzzy +#~ msgid "" +#~ " * To prevent breaking code, editions are opt-in: you select the\n" +#~ " edition for your crate via the `Cargo.toml` file." +#~ msgstr "" +#~ " * Um das Brechen von Code zu verhindern, sind Editionen Opt-in: Sie wählen die aus\n" +#~ " Edition für Ihre Kiste über die Datei `Cargo.toml`." + +#, fuzzy +#~ msgid "" +#~ " * To avoid splitting the ecosystem, Rust compilers can mix code\n" +#~ " written for different editions." +#~ msgstr "" +#~ " * Um eine Aufspaltung des Ökosystems zu vermeiden, können Rust-Compiler Code mischen\n" +#~ " für verschiedene Editionen geschrieben." + +#, fuzzy +#~ msgid "" +#~ " * Mention that it is quite rare to ever use the compiler directly not through `cargo` (most " +#~ "users never do)." +#~ msgstr "" +#~ " * Erwähnen Sie, dass es ziemlich selten vorkommt, den Compiler jemals direkt zu verwenden, " +#~ "nicht über `cargo` (die meisten Benutzer tun dies nie)." + +#, fuzzy +#~ msgid "" +#~ " * It might be worth alluding that Cargo itself is an extremely powerful and comprehensive " +#~ "tool. It is capable of many advanced features including but not limited to: \n" +#~ " * Project/package structure\n" +#~ " * [workspaces]\n" +#~ " * Dev Dependencies and Runtime Dependency management/caching\n" +#~ " * [build scripting]\n" +#~ " * [global installation]\n" +#~ " * It is also extensible with sub command plugins as well (such as [cargo clippy]).\n" +#~ " * Read more from the [official Cargo Book]" +#~ msgstr "" +#~ " * Es könnte erwähnenswert sein, dass Cargo selbst ein äußerst leistungsfähiges und " +#~ "umfassendes Werkzeug 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" +#~ " * [Skript erstellen]\n" +#~ " * [globale Installation]\n" +#~ " * Es ist auch mit Unterbefehls-Plugins erweiterbar (wie [cargo clippy]).\n" +#~ " * Lesen Sie mehr aus dem [offiziellen Frachtbuch]" -#: src/exercises/day-2/solutions-afternoon.md:3 #, fuzzy -msgid "## Luhn Algorithm" -msgstr "## Luhn-Algorithmus" +#~ msgid "[editions]: https://doc.rust-lang.org/edition-guide/" +#~ msgstr "[Ausgaben]: https://doc.rust-lang.org/edition-guide/" -#: src/exercises/day-2/solutions-afternoon.md:5 #, fuzzy -msgid "([back to exercise](luhn.md))" -msgstr "([zurück zur Übung](luhn.md))" +#~ msgid "[workspaces]: https://doc.rust-lang.org/cargo/reference/workspaces.html" +#~ msgstr "[Arbeitsbereiche]: https://doc.rust-lang.org/cargo/reference/workspaces.html" -#: src/exercises/day-2/solutions-afternoon.md:22 -msgid "" -"// ANCHOR: luhn\n" -"pub fn luhn(cc_number: &str) -> bool {\n" -" // ANCHOR_END: luhn\n" -" let mut digits_seen = 0;\n" -" let mut sum = 0;\n" -" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ').enumerate() {\n" -" match ch.to_digit(10) {\n" -" Some(d) => {\n" -" sum += if i % 2 == 1 {\n" -" let dd = d * 2;\n" -" dd / 10 + dd % 10\n" -" } else {\n" -" d\n" -" };\n" -" digits_seen += 1;\n" -" }\n" -" None => return false,\n" -" }\n" -" }" -msgstr "" +#, fuzzy +#~ msgid "[build scripting]: https://doc.rust-lang.org/cargo/reference/build-scripts.html" +#~ msgstr "[Build-Scripting]: https://doc.rust-lang.org/cargo/reference/build-scripts.html" -#: src/exercises/day-2/solutions-afternoon.md:42 -msgid "" -" if digits_seen < 2 {\n" -" return false;\n" -" }" -msgstr "" +#, fuzzy +#~ msgid "[global installation]: https://doc.rust-lang.org/cargo/commands/cargo-install.html" +#~ msgstr "[globale Installation]: https://doc.rust-lang.org/cargo/commands/cargo-install.html" -#: src/exercises/day-2/solutions-afternoon.md:46 #, fuzzy -msgid "" -" sum % 10 == 0\n" -"}" -msgstr "" -" Summe % 10 == 0\n" -"}" +#~ msgid "[cargo clippy]: https://github.com/rust-lang/rust-clippy" +#~ msgstr "[cargo clippy]: https://github.com/rust-lang/rust-clippy" -#: src/exercises/day-2/solutions-afternoon.md:49 -msgid "" -"fn main() {\n" -" let cc_number = \"1234 5678 1234 5670\";\n" -" println!(\n" -" \"Is {} a valid credit card number? {}\",\n" -" cc_number,\n" -" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" -" );\n" -"}" -msgstr "" +#, fuzzy +#~ msgid "[official Cargo Book]: https://doc.rust-lang.org/cargo/" +#~ msgstr "[offizielles Frachtbuch]: https://doc.rust-lang.org/cargo/" -#: src/exercises/day-2/solutions-afternoon.md:58 -msgid "" -"// ANCHOR: unit-tests\n" -"#[test]\n" -"fn test_non_digit_cc_number() {\n" -" assert!(!luhn(\"foo\"));\n" -"}" -msgstr "" +#, 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." +#~ msgstr "" +#~ "* Die eingebetteten Playgrounds können keine Unit-Tests ausführen. Kopieren Sie die\n" +#~ " code und öffnen Sie ihn im realen Playground, um Unit-Tests zu demonstrieren." -#: src/exercises/day-2/solutions-afternoon.md:89 -msgid "" -"#[test]\n" -"fn test_invalid_cc_number() {\n" -" assert!(!luhn(\"4223 9826 4026 9299\"));\n" -" assert!(!luhn(\"4539 3195 0343 6476\"));\n" -" assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}\n" -"// ANCHOR_END: unit-tests\n" -"```" -msgstr "" +#, fuzzy +#~ msgid "1. Click the \"Copy to clipboard\" button on the example you want to copy." +#~ msgstr "" +#~ "1. Klicken Sie bei dem Beispiel, das Sie kopieren möchten, auf die Schaltfläche \"In die " +#~ "Zwischenablage kopieren\"." -#: src/exercises/day-2/solutions-afternoon.md:98 #, fuzzy -msgid "## Strings and Iterators" -msgstr "## Strings und Iteratoren" +#~ msgid "2. Use `cargo new exercise` to create a new `exercise/` directory for your code:" +#~ msgstr "" +#~ "2. Verwenden Sie `cargo new Exercise`, um ein neues `exercise/`-Verzeichnis für Ihren Code zu " +#~ "erstellen:" -#: src/exercises/day-2/solutions-afternoon.md:100 #, fuzzy -msgid "([back to exercise](strings-iterators.md))" -msgstr "([zurück zur Übung](strings-iterators.md))" +#~ msgid "3. Navigate into `exercise/` and use `cargo run` to build and run your binary:" +#~ msgstr "" +#~ "3. Navigieren Sie zu „exercise/“ und verwenden Sie „cargo run“, um Ihre Binärdatei zu erstellen " +#~ "und auszuführen:" -#: src/exercises/day-2/solutions-afternoon.md:117 -msgid "" -"// ANCHOR: prefix_matches\n" -"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" -" // ANCHOR_END: prefix_matches\n" -" let prefixes = prefix.split('/');\n" -" let request_paths = request_path\n" -" .split('/')\n" -" .map(|p| Some(p))\n" -" .chain(std::iter::once(None));" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "4. Replace the boiler-plate code in `src/main.rs` with your own code. For\n" +#~ " example, using the example on the previous page, make `src/main.rs` look like" +#~ msgstr "" +#~ "4. Ersetzen Sie den Standardcode in `src/main.rs` durch Ihren eigenen Code. Für\n" +#~ " Verwenden Sie beispielsweise das Beispiel auf der vorherigen Seite und lassen Sie `src/main." +#~ "rs` so aussehen" -#: src/exercises/day-2/solutions-afternoon.md:126 -msgid "" -" for (prefix, request_path) in prefixes.zip(request_paths) {\n" -" match request_path {\n" -" Some(request_path) => {\n" -" if (prefix != \"*\") && (prefix != request_path) {\n" -" return false;\n" -" }\n" -" }\n" -" None => return false,\n" -" }\n" -" }\n" -" true\n" -"}" -msgstr "" +#, fuzzy +#~ msgid "5. Use `cargo run` to build and run your updated binary:" +#~ msgstr "" +#~ "5. Verwenden Sie „cargo run“, um Ihre aktualisierte Binärdatei zu erstellen und auszuführen:" -#: src/exercises/day-2/solutions-afternoon.md:139 -msgid "" -"// ANCHOR: unit-tests\n" -"#[test]\n" -"fn test_matches_without_wildcard() {\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "6. Use `cargo check` to quickly check your project for errors, use `cargo build`\n" +#~ " to compile it without running it. You will find the output in `target/debug/`\n" +#~ " for a normal debug build. Use `cargo build --release` to produce an optimized\n" +#~ " release build in `target/release/`." +#~ msgstr "" +#~ "6. Verwenden Sie „Cargo Check“, um Ihr Projekt schnell auf Fehler zu überprüfen, verwenden Sie " +#~ "„Cargo Build“.\n" +#~ " um es zu kompilieren, ohne es auszuführen. Die Ausgabe finden Sie in `target/debug/`\n" +#~ " für einen normalen Debug-Build. Verwenden Sie `cargo build --release`, um eine optimierte\n" +#~ " Release-Build in `target/release/`." -#: src/exercises/day-2/solutions-afternoon.md:166 -msgid "" -" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" -" assert!(!prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/booksByAuthor\"\n" -" ));\n" -"}\n" -"// ANCHOR_END: unit-tests\n" -"```" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "7. You can add dependencies for your project by editing `Cargo.toml`. When you\n" +#~ " run `cargo` commands, it will automatically download and compile missing\n" +#~ " dependencies for you." +#~ msgstr "" +#~ "7. Sie können Abhängigkeiten für Ihr Projekt hinzufügen, indem Sie `Cargo.toml` bearbeiten. " +#~ "Wenn du\n" +#~ " Führen Sie \"Cargo\"-Befehle aus, es wird automatisch heruntergeladen und kompiliert\n" +#~ " Abhängigkeiten für Sie." -#: src/exercises/day-3/solutions-morning.md:1 #, fuzzy -msgid "# Day 3 Morning Exercise" -msgstr "# Tag 3 Morgengymnastik" +#~ msgid "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" +#~ msgstr "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" -#: src/exercises/day-3/solutions-morning.md:3 #, fuzzy -msgid "## A Simple GUI Library" -msgstr "## Eine einfache GUI-Bibliothek" +#~ msgid "" +#~ "* Basic Rust syntax: variables, scalar and compound types, enums, structs,\n" +#~ " references, functions, and methods." +#~ msgstr "" +#~ "* Grundlegende Rust-Syntax: Variablen, skalare und zusammengesetzte Typen, Aufzählungen, " +#~ "Strukturen,\n" +#~ " Referenzen, Funktionen und Methoden." -#: src/exercises/day-3/solutions-morning.md:5 #, fuzzy -msgid "([back to exercise](simple-gui.md))" -msgstr "([zurück zur Übung](simple-gui.md))" +#~ msgid "" +#~ "* Memory management: stack vs heap, manual memory management, scope-based memory\n" +#~ " management, and garbage collection." +#~ msgstr "" +#~ "* Speicherverwaltung: Stack vs. Heap, manuelle Speicherverwaltung, bereichsbasierter Speicher\n" +#~ " Verwaltung und Garbage Collection." -#: src/exercises/day-3/solutions-morning.md:22 -msgid "" -"// ANCHOR: setup\n" -"pub trait Widget {\n" -" /// Natural width of `self`.\n" -" fn width(&self) -> usize;" -msgstr "" +#, fuzzy +#~ msgid "* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." +#~ msgstr "* Eigentum: Verschieben von Semantik, Kopieren und Klonen, Ausleihen und Lebensdauern." -#: src/exercises/day-3/solutions-morning.md:82 #, fuzzy -msgid "// ANCHOR_END: setup" -msgstr "// ANCHOR_END: Einrichtung" +#~ msgid "" +#~ "* Rust is very much like other languages in the C/C++/Java tradition. It is\n" +#~ " imperative (not functional) and it doesn't try to reinvent things unless\n" +#~ " absolutely necessary." +#~ msgstr "" +#~ "* Rust ist anderen Sprachen in der C/C++/Java-Tradition sehr ähnlich. Es ist\n" +#~ " Imperativ (nicht funktional) und es versucht nicht, Dinge neu zu erfinden, es sei denn\n" +#~ " absolut notwendig." + +#, fuzzy +#~ msgid "* Rust is modern with full support for things like Unicode." +#~ msgstr "* Rust ist modern mit voller Unterstützung für Dinge wie Unicode." + +#, fuzzy +#~ msgid "" +#~ "* Rust uses macros for situations where you want to have a variable number of\n" +#~ " arguments (no function [overloading](basic-syntax/functions-interlude.md))." +#~ msgstr "" +#~ "* Rust verwendet Makros für Situationen, in denen Sie eine variable Anzahl von Makros haben " +#~ "möchten\n" +#~ " Argumente (keine Funktion [Überladen] (Grundsyntax/Funktionen-Zwischenspiel.md))." + +#, fuzzy +#~ msgid "" +#~ "* Explain that all variables are statically typed. Try removing `i32` to trigger\n" +#~ " type inference. Try with `i8` instead and trigger a runtime integer overflow." +#~ msgstr "" +#~ "* Erklären Sie, dass alle Variablen statisch typisiert sind. Versuchen Sie, „i32“ zu entfernen, " +#~ "um auszulösen\n" +#~ " Typ Inferenz. Versuchen Sie es stattdessen mit \"i8\" und lösen Sie einen Integer-Überlauf " +#~ "zur Laufzeit aus." + +#, fuzzy +#~ msgid "* Change `let mut x` to `let x`, discuss the compiler error." +#~ msgstr "* Ändere `let mut x` in `let x`, diskutiere den Compiler-Fehler." + +#, fuzzy +#~ msgid "" +#~ "* Show how `print!` gives a compilation error if the arguments don't match the\n" +#~ " format string." +#~ msgstr "" +#~ "* Zeigen Sie, wie `print!` einen Kompilierungsfehler ausgibt, wenn die Argumente nicht " +#~ "übereinstimmen\n" +#~ " Zeichenfolge formatieren." + +#, fuzzy +#~ msgid "" +#~ "* Show how you need to use `{}` as a placeholder if you want to print an\n" +#~ " expression which is more complex than just a single variable." +#~ msgstr "" +#~ "* Zeigen Sie, wie Sie `{}` als Platzhalter verwenden müssen, wenn Sie eine drucken möchten\n" +#~ " Ausdruck, der komplexer ist als nur eine einzelne Variable." + +#, fuzzy +#~ msgid "" +#~ "* Show the students the standard library, show them how to search for `std::fmt`\n" +#~ " 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 "" +#~ "* Zeigen Sie den Schülern die Standardbibliothek, zeigen Sie ihnen, wie man nach `std::fmt` " +#~ "sucht\n" +#~ " die die Regeln der Formatierungsminisprache hat. Wichtig ist, dass die\n" +#~ " Die Schüler lernen die Suche in der Standardbibliothek kennen." + +#, 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" +#~ " have the memory unsafety issues. In addition, you get a modern language with\n" +#~ " constructs like pattern matching and built-in dependency management." +#~ msgstr "" +#~ "* Erfahrung mit C oder C++: Rust eliminiert eine ganze Klasse von _Laufzeitfehlern_\n" +#~ " über den Ausleihprüfer. Sie erhalten eine Leistung wie in C und C++, aber Sie tun es nicht\n" +#~ " habe die Speicherunsicherheitsprobleme. Außerdem bekommt man eine moderne Sprache mit\n" +#~ " Konstrukte wie Musterabgleich und integriertes Abhängigkeitsmanagement." + +#, fuzzy +#~ msgid "" +#~ "[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak\n" +#~ "[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" +#~ "[reference cycle]: https://doc.rust-lang.org/book/ch15-06-reference-cycles.html" +#~ msgstr "" +#~ "[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak\n" +#~ "[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" +#~ "[Referenzzyklus]: https://doc.rust-lang.org/book/ch15-06-reference-cycles.html" + +#, fuzzy +#~ msgid "" +#~ "* Bounds checking cannot be disabled with a compiler flag. It can also\n" +#~ " not be disabled directly with the `unsafe` keyword. However,\n" +#~ " `unsafe` allows you to call functions such as `slice::get_unchecked`\n" +#~ " which does not do bounds checking." +#~ msgstr "" +#~ "* Die Begrenzungsprüfung kann nicht mit einem Compiler-Flag deaktiviert werden. Es kann auch\n" +#~ " nicht direkt mit dem Schlüsselwort „unsafe“ deaktiviert werden. Jedoch,\n" +#~ " `unsafe` erlaubt Ihnen, Funktionen wie `slice::get_unchecked` aufzurufen\n" +#~ " die keine Begrenzungsprüfung durchführt." + +#, fuzzy +#~ msgid "" +#~ "* Zero-cost abstractions, similar to C++, means that you don't have to 'pay'\n" +#~ " for higher-level programming constructs with memory or CPU. For example,\n" +#~ " writing a loop using `for` should result in roughly the same low level\n" +#~ " instructions as using the `.iter().fold()` construct." +#~ msgstr "" +#~ "* Zero-Cost-Abstraktionen, ähnlich wie C++, bedeutet, dass Sie nicht „bezahlen“ müssen\n" +#~ " für übergeordnete Programmierkonstrukte mit Speicher oder CPU. Zum Beispiel,\n" +#~ " Das Schreiben einer Schleife mit `for` sollte ungefähr den gleichen niedrigen Pegel ergeben\n" +#~ " Anweisungen wie die Verwendung des `.iter().fold()`-Konstrukts." + +#, fuzzy +#~ msgid "" +#~ "* It may be worth mentioning that Rust enums are 'Algebraic Data Types', also\n" +#~ " known as 'sum types', which allow the type system to express things like\n" +#~ " `Option` and `Result`." +#~ msgstr "" +#~ "* Es sollte erwähnt werden, dass Rust-Enumerationen auch 'algebraische Datentypen' sind\n" +#~ " bekannt als \"Summentypen\", die es dem Typsystem ermöglichen, Dinge wie auszudrücken\n" +#~ " `Option` und `Ergebnis`." + +#, fuzzy +#~ msgid "" +#~ "* Remind people to read the errors --- many developers have gotten used to\n" +#~ " ignore lengthy compiler output. The Rust compiler is significantly more\n" +#~ " talkative than other compilers. It will often provide you with _actionable_\n" +#~ " feedback, ready to copy-paste into your code." +#~ msgstr "" +#~ "* Erinnere die Leute daran, die Fehler zu lesen --- viele Entwickler haben sich daran gewöhnt\n" +#~ " Ignoriere lange Compiler-Ausgaben. Der Rust-Compiler ist deutlich mehr\n" +#~ " gesprächiger als andere Compiler. Es wird Ihnen oft _umsetzbare_\n" +#~ " Feedback, bereit zum Kopieren und Einfügen in Ihren Code." + +#, fuzzy +#~ msgid "" +#~ "* The Rust standard library is small compared to languages like Java, Python,\n" +#~ " and Go. Rust does not come with several things you might consider standard and\n" +#~ " essential:" +#~ msgstr "" +#~ "* Die Rust-Standardbibliothek ist klein im Vergleich zu Sprachen wie Java, Python,\n" +#~ " Los geht. Rust kommt nicht mit einigen Dingen, die Sie als Standard betrachten könnten und\n" +#~ " essentiell:" + +#, fuzzy +#~ msgid "" +#~ " * a random number generator, but see [rand].\n" +#~ " * support for SSL or TLS, but see [rusttls].\n" +#~ " * support for JSON, but see [serde_json]." +#~ msgstr "" +#~ " * ein Zufallszahlengenerator, aber siehe [rand].\n" +#~ " * Unterstützung für SSL oder TLS, aber siehe [rusttls].\n" +#~ " * Unterstützung für JSON, aber siehe [serde_json]." + +#, fuzzy +#~ msgid "" +#~ " The reasoning behind this is that functionality in the standard library cannot\n" +#~ " go away, so it has to be very stable. For the examples above, the Rust\n" +#~ " community is still working on finding the best solution --- and perhaps there\n" +#~ " isn't a single \"best solution\" for some of these things." +#~ msgstr "" +#~ " Der Grund dafür ist, dass die Funktionalität in der Standardbibliothek dies nicht kann\n" +#~ " weggehen, also muss es sehr stabil sein. Für die obigen Beispiele ist die Rust\n" +#~ " Die Community arbeitet immer noch daran, die beste Lösung zu finden --- und vielleicht gibt " +#~ "es sie\n" +#~ " ist für einige dieser Dinge keine einzige \"beste Lösung\"." + +#, fuzzy +#~ msgid "" +#~ " Rust comes with a built-in package manager in the form of Cargo and this makes\n" +#~ " it trivial to download and compile third-party crates. A consequence of this\n" +#~ " is that the standard library can be smaller." +#~ msgstr "" +#~ " Rust kommt mit einem eingebauten Paketmanager in Form von Cargo und macht das\n" +#~ " Es ist trivial, Crates von Drittanbietern herunterzuladen und zu kompilieren. Eine Folge " +#~ "davon\n" +#~ " ist, dass die Standardbibliothek kleiner sein kann." + +#, fuzzy +#~ msgid "" +#~ " Discovering good third-party crates can be a problem. Sites like\n" +#~ " help with this by letting you compare health metrics for\n" +#~ " crates to find a good and trusted one.\n" +#~ " \n" +#~ "* [rust-analyzer] is a well supported LSP implementation used in major\n" +#~ " IDEs and text editors." +#~ msgstr "" +#~ " Das Entdecken guter Kisten von Drittanbietern kann ein Problem sein. Seiten wie\n" +#~ " hilft dabei, indem es Ihnen ermöglicht, Gesundheitsmetriken für zu " +#~ "vergleichen\n" +#~ " Kisten, um eine gute und vertrauenswürdige zu finden.\n" +#~ " \n" +#~ "* [rust-analyzer] ist eine gut unterstützte LSP-Implementierung, die in Major verwendet wird\n" +#~ " IDEs und Texteditoren." + +#, fuzzy +#~ msgid "" +#~ "[rand]: https://docs.rs/rand/\n" +#~ "[rusttls]: https://docs.rs/rustls/\n" +#~ "[serde_json]: https://docs.rs/serde_json/\n" +#~ "[rust-analyzer]: https://rust-analyzer.github.io/" +#~ msgstr "" +#~ "[rand]: https://docs.rs/rand/\n" +#~ "[rusttls]: https://docs.rs/rustls/\n" +#~ "[serde_json]: https://docs.rs/serde_json/\n" +#~ "[Rostanalyzer]: https://rust-analyzer.github.io/" + +#, fuzzy +#~ msgid "* We can use literals to assign values to arrays." +#~ msgstr "* Wir können Literale verwenden, um Arrays Werte zuzuweisen." + +#, fuzzy +#~ msgid "" +#~ "* In the main function, the print statement asks for the debug implementation with the `?` " +#~ "format\n" +#~ " parameter: `{}` gives the default output, `{:?}` gives the debug output. We\n" +#~ " could also have used `{a}` and `{a:?}` without specifying the value after the\n" +#~ " format string." +#~ msgstr "" +#~ "* In der main-Funktion fragt die print-Anweisung nach der Debug-Implementierung mit dem `?`-" +#~ "Format\n" +#~ " Parameter: `{}` gibt die Standardausgabe, `{:?}` gibt die Debug-Ausgabe. Wir\n" +#~ " hätte auch `{a}` und `{a:?}` verwenden können, ohne den Wert nach dem anzugeben\n" +#~ " Zeichenfolge formatieren." + +#, fuzzy +#~ msgid "" +#~ "* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read." +#~ msgstr "" +#~ "* Das Hinzufügen von `#`, z. B. `{a:#?}`, ruft ein \"hübsches Druckformat\" auf, das einfacher " +#~ "zu lesen sein kann." -#: src/exercises/day-3/solutions-morning.md:84 #, fuzzy -msgid "" -"// ANCHOR: Window-width\n" -"impl Widget for Window {\n" -" fn width(&self) -> usize {\n" -" // ANCHOR_END: Window-width\n" -" std::cmp::max(\n" -" self.title.chars().count(),\n" -" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" -" )\n" -" }" -msgstr "" -"// ANCHOR: Fensterbreite\n" -"impl-Widget für Fenster {\n" -" fn width(&self) -> use {\n" -" // ANCHOR_END: Fensterbreite\n" -" std::cmp::max(\n" -" self.title.chars().count(),\n" -" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" -" )\n" -" }" +#~ msgid "* Like arrays, tuples have a fixed length." +#~ msgstr "* Tupel haben wie Arrays eine feste Länge." + +#, fuzzy +#~ msgid "* Tuples group together values of different types into a compound type." +#~ msgstr "* Tupel fassen Werte verschiedener Typen zu einem zusammengesetzten Typ zusammen." -#: src/exercises/day-3/solutions-morning.md:94 -msgid "" -" // ANCHOR: Window-draw_into\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" // ANCHOR_END: Window-draw_into\n" -" let mut inner = String::new();\n" -" for widget in &self.widgets {\n" -" widget.draw_into(&mut inner);\n" -" }" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "* Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`." +#~ msgstr "" +#~ "* Auf Felder eines Tupels kann über den Punkt und den Index des Werts zugegriffen werden, z. " +#~ "„t.0“, „t.1“." -#: src/exercises/day-3/solutions-morning.md:102 -msgid " let window_width = self.width();" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "* We create a slice by borrowing `a` and specifying the starting and ending indexes in brackets." +#~ msgstr "" +#~ "* Wir erstellen einen Slice, indem wir `a` ausleihen und den Anfangs- und Endindex in Klammern " +#~ "angeben." -#: src/exercises/day-3/solutions-morning.md:104 -msgid "" -" // TODO: after learning about error handling, you can change\n" -" // draw_into to return Result<(), std::fmt::Error>. Then use\n" -" // the ?-operator here instead of .unwrap().\n" -" writeln!(buffer, \"+-{:- usize {\n" -" // ANCHOR_END: Button-width\n" -" self.label.width() + 8 // add a bit of padding\n" -" }" -msgstr "" -"// ANCHOR: Button-Breite\n" -"impl-Widget für Schaltfläche {\n" -" fn width(&self) -> use {\n" -" // ANCHOR_END: Button-Breite\n" -" self.label.width() + 8 // etwas Polsterung hinzufügen\n" -" }" +#~ msgid "* To easily create a slice of the full array, we can therefore use `&a[..]`." +#~ msgstr "" +#~ "* Um einfach einen Teil des gesamten Arrays zu erstellen, können wir daher `&a[..]` verwenden." + +#, fuzzy +#~ msgid "" +#~ "* `&str` introduces a string slice, which is an immutable reference to UTF-8 encoded string " +#~ "data \n" +#~ " stored in a block of memory. String literals (`”Hello”`), are stored in the program’s binary." +#~ msgstr "" +#~ "* `&str` führt ein String-Slice ein, das eine unveränderliche Referenz auf UTF-8-codierte " +#~ "String-Daten ist\n" +#~ " in einem Speicherblock gespeichert. String-Literale (`”Hallo”`) werden in der Binärdatei des " +#~ "Programms gespeichert." + +#, fuzzy +#~ msgid " (Type annotations added for clarity, but they can be elided.)" +#~ msgstr "" +#~ " (Typ-Anmerkungen wurden der Übersichtlichkeit halber hinzugefügt, können aber entfernt " +#~ "werden.)" + +#, fuzzy +#~ msgid "" +#~ "impl Rectangle {\n" +#~ " fn area(&self) -> u32 {\n" +#~ " self.width * self.height\n" +#~ " }" +#~ msgstr "" +#~ "impl Rechteck {\n" +#~ " fn-Bereich(&self) -> u32 {\n" +#~ " selbst.Breite * selbst.Höhe\n" +#~ " }" + +#, fuzzy +#~ msgid "* Arrays and `for` loops." +#~ msgstr "* Arrays und „for“-Schleifen." + +#, fuzzy +#~ msgid "* Alternatively, use the Rust Playground." +#~ msgstr "* Benutze alternativ den Rust Playground." + +#, fuzzy +#~ msgid "[solutions]: solutions-morning.md" +#~ msgstr "[Lösungen]: Lösungen-Morgen.md" -#: src/exercises/day-3/solutions-morning.md:124 -msgid "" -" // ANCHOR: Button-draw_into\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" // ANCHOR_END: Button-draw_into\n" -" let width = self.width();\n" -" let mut label = String::new();\n" -" self.label.draw_into(&mut label);" -msgstr "" +#, fuzzy +#~ msgid "[Using Cargo]: ../../cargo.md" +#~ msgstr "[Fracht verwenden]: ../../cargo.md" -#: src/exercises/day-3/solutions-morning.md:131 -msgid "" -" writeln!(buffer, \"+{:- usize {\n" -" // ANCHOR_END: Label-width\n" -" self.label\n" -" .lines()\n" -" .map(|line| line.chars().count())\n" -" .max()\n" -" .unwrap_or(0)\n" -" }" -msgstr "" -"// ANCHOR: Etikettenbreite\n" -"impl-Widget für Label {\n" -" fn width(&self) -> use {\n" -" // ANCHOR_END: Etikettenbreite\n" -" self.label\n" -" .Linien()\n" -" .map(|line| line.chars().count())\n" -" .max()\n" -" .unwrap_or(0)\n" -" }" +#~ msgid "2. Update the code above to use `into()` to do the conversion." +#~ msgstr "" +#~ "2. Aktualisieren Sie den obigen Code, um `into()` zu verwenden, um die Konvertierung " +#~ "durchzuführen." -#: src/exercises/day-3/solutions-morning.md:150 -msgid "" -" // ANCHOR: Label-draw_into\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" // ANCHOR_END: Label-draw_into\n" -" writeln!(buffer, \"{}\", &self.label).unwrap();\n" -" }\n" -"}" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" +#~ "[2]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" +#~ "[3]: https://en.cppreference.com/w/cpp/language/implicit_conversion" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" +#~ "[2]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" +#~ "[3]: https://en.cppreference.com/w/cpp/language/implicit_conversion" -#: src/exercises/day-3/solutions-morning.md:157 -msgid "" -"// ANCHOR: main\n" -"fn main() {\n" -" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" -" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" -" window.add_widget(Box::new(Button::new(\n" -" \"Click me!\",\n" -" Box::new(|| println!(\"You clicked the button!\")),\n" -" )));\n" -" window.draw();\n" -"}\n" -"// ANCHOR_END: main\n" -"```" -msgstr "" +#, fuzzy +#~ msgid "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" +#~ msgstr "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" -#: src/exercises/day-3/solutions-afternoon.md:1 #, fuzzy -msgid "# Day 3 Afternoon Exercises" -msgstr "# Tag 3 Nachmittagsübungen" +#~ msgid "" +#~ "* Heap: Storage of values outside of function calls.\n" +#~ " * Values have dynamic sizes determined at runtime.\n" +#~ " * Slightly slower than the stack: some book-keeping needed.\n" +#~ " * No guarantee of memory locality." +#~ msgstr "" +#~ "* Heap: Speicherung von Werten außerhalb von Funktionsaufrufen.\n" +#~ " * Werte haben dynamische Größen, die zur Laufzeit bestimmt werden.\n" +#~ " * Etwas langsamer als der Stapel: Etwas Buchhaltung erforderlich.\n" +#~ " * Keine Garantie auf Speicherort." -#: src/exercises/day-3/solutions-afternoon.md:3 #, fuzzy -msgid "## Safe FFI Wrapper" -msgstr "## Sicherer FFI-Wrapper" +#~ msgid "" +#~ "* Mention that a `String` is backed by a `Vec`, so it has a capacity and length and can grow if " +#~ "mutable via reallocation on the heap." +#~ msgstr "" +#~ "* Erwähnen Sie, dass ein `String` von einem `Vec` unterstützt wird, sodass er eine Kapazität " +#~ "und Länge hat und wachsen kann, wenn er durch Neuzuweisung auf dem Haufen veränderbar ist." -#: src/exercises/day-3/solutions-afternoon.md:5 #, fuzzy -msgid "([back to exercise](safe-ffi-wrapper.md))" -msgstr "([zurück zur Übung](safe-ffi-wrapper.md))" +#~ msgid "" +#~ "* If students ask about it, you can mention that the underlying memory is heap allocated using " +#~ "the [System Allocator] and custom allocators can be implemented using the [Allocator API]" +#~ msgstr "" +#~ "* Wenn die Schüler danach fragen, können Sie erwähnen, dass der zugrunde liegende Speicher mit " +#~ "dem [System Allocator] Heap zugewiesen wird und benutzerdefinierte Allokatoren mit der " +#~ "[Allocator API] implementiert werden können." -#: src/exercises/day-3/solutions-afternoon.md:22 -msgid "" -"// ANCHOR: ffi\n" -"mod ffi {\n" -" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "[System Allocator]: https://doc.rust-lang.org/std/alloc/struct.System.html\n" +#~ "[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html" +#~ msgstr "" +#~ "[Systemzuordner]: https://doc.rust-lang.org/std/alloc/struct.System.html\n" +#~ "[Allocator-API]: https://doc.rust-lang.org/std/alloc/index.html" -#: src/exercises/day-3/solutions-afternoon.md:53 #, fuzzy -msgid "" -"#[derive(Debug)]\n" -"struct DirectoryIterator {\n" -" path: CString,\n" -" dir: *mut ffi::DIR,\n" -"}\n" -"// ANCHOR_END: ffi" -msgstr "" -"#[ableiten(Debuggen)]\n" -"struct DirectoryIterator {\n" -" Pfad: CString,\n" -" dir: *mut ffi::DIR,\n" -"}\n" -"// ANCHOR_END: ffi" +#~ msgid "* You may be asked about destructors here, the [Drop] trait is the Rust equivalent." +#~ msgstr "" +#~ "* Möglicherweise werden Sie hier nach Destruktoren gefragt, die Eigenschaft [Drop] ist das Rust-" +#~ "Äquivalent." -#: src/exercises/day-3/solutions-afternoon.md:60 -msgid "" -"// ANCHOR: DirectoryIterator\n" -"impl DirectoryIterator {\n" -" fn new(path: &str) -> Result {\n" -" // Call opendir and return a Ok value if that worked,\n" -" // otherwise return Err with a message.\n" -" // ANCHOR_END: DirectoryIterator\n" -" let path = CString::new(path).map_err(|err| format!(\"Invalid path: {err}\"))?;\n" -" // SAFETY: path.as_ptr() cannot be NULL.\n" -" let dir = unsafe { ffi::opendir(path.as_ptr()) };\n" -" if dir.is_null() {\n" -" Err(format!(\"Could not open {:?}\", path))\n" -" } else {\n" -" Ok(DirectoryIterator { path, dir })\n" -" }\n" -" }\n" -"}" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "[Box]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +#~ "[Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +#~ "[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +#~ "[Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html" +#~ msgstr "" +#~ "[Box]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +#~ "[Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +#~ "[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +#~ "[Bogen]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html" + +#, fuzzy +#~ msgid "* In Rust, you clones are explicit (by using `clone`)." +#~ msgstr "* In Rust sind Klone explizit (durch Verwendung von `clone`)." -#: src/exercises/day-3/solutions-afternoon.md:77 -msgid "" -"// ANCHOR: Iterator\n" -"impl Iterator for DirectoryIterator {\n" -" type Item = OsString;\n" -" fn next(&mut self) -> Option {\n" -" // Keep calling readdir until we get a NULL pointer back.\n" -" // ANCHOR_END: Iterator\n" -" // SAFETY: self.dir is never NULL.\n" -" let dirent = unsafe { ffi::readdir(self.dir) };\n" -" if dirent.is_null() {\n" -" // We have reached the end of the directory.\n" -" return None;\n" -" }\n" -" // SAFETY: dirent is not NULL and dirent.d_name is NUL\n" -" // terminated.\n" -" let d_name = unsafe { CStr::from_ptr((*dirent).d_name.as_ptr()) };\n" -" let os_str = OsStr::from_bytes(d_name.to_bytes());\n" -" Some(os_str.to_owned())\n" -" }\n" -"}" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "fn add(p1: &Point, p2: &Point) -> Point {\n" +#~ " Point(p1.0 + p2.0, p1.1 + p2.1)\n" +#~ "}" +#~ msgstr "" +#~ "fn add(p1: &Punkt, p2: &Punkt) -> Punkt {\n" +#~ " Punkt(p1.0 + p2.0, p1.1 + p2.1)\n" +#~ "}" + +#~ msgid "" +#~ "* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy " +#~ "operation. Change the above code to print stack addresses and run it on the [Playground]. In " +#~ "the \"DEBUG\" optimization level, the addresses should change, while the stay the same when " +#~ "changing to the \"RELEASE\" setting:" +#~ msgstr "" +#~ "* Zeigen Sie, dass die Rückgabe von `add` billig ist, weil der Compiler den Kopiervorgang " +#~ "eliminieren kann. Ändern Sie den obigen Code, um Stapeladressen zu drucken, und führen Sie ihn " +#~ "auf dem [Playground] aus. In der Optimierungsstufe „DEBUG“ sollen sich die Adressen ändern, " +#~ "während sie beim Wechsel in die Einstellung „RELEASE“ gleich bleiben:" + +#, fuzzy +#~ msgid "[Playground]: https://play.rust-lang.org/" +#~ msgstr "[Spielplatz]: https://play.rust-lang.org/" + +#, fuzzy +#~ msgid "" +#~ "fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +#~ " if p1.0 < p2.0 { p1 } else { p2 }\n" +#~ "}" +#~ msgstr "" +#~ "fn left_most<'a>(p1: &'a Punkt, p2: &'a Punkt) -> &'a Punkt {\n" +#~ " wenn p1.0 < p2.0 { p1 } sonst { p2 }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +#~ " if p1.0 < p2.0 { p1 } else { p2 }\n" +#~ " }" +#~ msgstr "" +#~ " fn left_most<'a>(p1: &'a Punkt, p2: &'a Punkt) -> &'a Punkt {\n" +#~ " wenn p1.0 < p2.0 { p1 } sonst { p2 }\n" +#~ " }" + +#, fuzzy +#~ msgid "* A small book library," +#~ msgstr "* Eine kleine Buchbibliothek," + +#, fuzzy +#~ msgid "[solutions]: solutions-afternoon.md" +#~ msgstr "[Lösungen]: Lösungen-Nachmittag.md" + +#, fuzzy +#~ msgid "" +#~ "struct Library {\n" +#~ " books: Vec,\n" +#~ "}" +#~ msgstr "" +#~ "Struktur Bibliothek {\n" +#~ " Bücher: Vec,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "struct Book {\n" +#~ " title: String,\n" +#~ " year: u16,\n" +#~ "}" +#~ msgstr "" +#~ "struct Buch {\n" +#~ " Titel: Zeichenkette,\n" +#~ " Jahr: u16,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Book {\n" +#~ " // This is a constructor, used below.\n" +#~ " fn new(title: &str, year: u16) -> Book {\n" +#~ " Book {\n" +#~ " title: String::from(title),\n" +#~ " year,\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Buch {\n" +#~ " // Dies ist ein Konstruktor, der unten verwendet wird.\n" +#~ " fn neu(titel: &str, jahr: u16) -> Buch {\n" +#~ " Buch {\n" +#~ " Titel: Zeichenkette::von(Titel),\n" +#~ " Jahr,\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// 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" +#~ "}" +#~ msgstr "" +#~ "// Dadurch ist es möglich, Buchwerte mit {} zu drucken.\n" +#~ "impl std::fmt::Anzeige für Buch {\n" +#~ " fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n" +#~ " schreibe!(f, \"{} ({})\", self.title, self.year)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Library {\n" +#~ " fn new() -> Library {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl-Bibliothek {\n" +#~ " fn new() -> Bibliothek {\n" +#~ " nicht implementiert!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " //fn len(self) -> usize {\n" +#~ " // unimplemented!()\n" +#~ " //}" +#~ msgstr "" +#~ " //fn len(self) -> verwenden {\n" +#~ " // nicht implementiert!()\n" +#~ " //}" + +#, fuzzy +#~ msgid "" +#~ " //fn is_empty(self) -> bool {\n" +#~ " // unimplemented!()\n" +#~ " //}" +#~ msgstr "" +#~ " //fn is_empty(self) -> bool {\n" +#~ " // nicht implementiert!()\n" +#~ " //}" + +#, fuzzy +#~ msgid "" +#~ " //fn add_book(self, book: Book) {\n" +#~ " // unimplemented!()\n" +#~ " //}" +#~ msgstr "" +#~ " //fn add_book(selbst, Buch: Buch) {\n" +#~ " // nicht implementiert!()\n" +#~ " //}" + +#, fuzzy +#~ msgid "" +#~ " //fn print_books(self) {\n" +#~ " // unimplemented!()\n" +#~ " //}" +#~ msgstr "" +#~ " //fn print_books(selbst) {\n" +#~ " // nicht implementiert!()\n" +#~ " //}" + +#, fuzzy +#~ msgid "" +#~ " //fn oldest_book(self) -> Option<&Book> {\n" +#~ " // unimplemented!()\n" +#~ " //}\n" +#~ "}" +#~ msgstr "" +#~ " //fn ältestes_buch(selbst) -> Option<&Buch> {\n" +#~ " // nicht implementiert!()\n" +#~ " //}\n" +#~ "}" + +#, fuzzy +#~ msgid "* Structs, enums, methods." +#~ msgstr "* Strukturen, Aufzählungen, Methoden." + +#, fuzzy +#~ msgid "* Pattern matching: destructuring enums, structs, and arrays." +#~ msgstr "* Mustervergleich: Destrukturierung von Aufzählungen, Strukturen und Arrays." + +#, fuzzy +#~ msgid "" +#~ "* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and\n" +#~ " `continue`." +#~ msgstr "" +#~ "* Kontrollflusskonstrukte: `if`, `if let`, `while`, `while let`, `break` und\n" +#~ " \"weitermachen\"." + +#, fuzzy +#~ msgid "" +#~ "* The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, `Rc`\n" +#~ " and `Arc`." +#~ msgstr "" +#~ "* Die Standardbibliothek: `String`, `Option` und `Result`, `Vec`, `HashMap`, `Rc`\n" +#~ " und \"Bogen\"." + +#, fuzzy +#~ msgid "* Modules: visibility, paths, and filesystem hierarchy." +#~ msgstr "* Module: Sichtbarkeit, Pfade und Dateisystemhierarchie." + +#, fuzzy +#~ msgid "" +#~ "fn compute_thruster_force() -> PoundOfForce {\n" +#~ " todo!(\"Ask a rocket scientist at NASA\")\n" +#~ "}" +#~ msgstr "" +#~ "fn compute_thruster_force() -> PoundOfForce {\n" +#~ " todo! (\"Fragen Sie einen Raketenwissenschaftler bei der NASA\")\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "fn set_thruster_force(force: Newtons) {\n" +#~ " // ...\n" +#~ "}" +#~ msgstr "" +#~ "fn set_thruster_force(Kraft: Newton) {\n" +#~ " // ...\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "Newtypes are a great way to encode additional information about the value in a primitive type, " +#~ "for example:\n" +#~ msgstr "" +#~ "Newtypes sind eine großartige Möglichkeit, zusätzliche Informationen über den Wert in einem " +#~ "primitiven Typ zu codieren, zum Beispiel:\n" + +#~ msgid "" +#~ " * The number is measured in some units: `Newtons` in the example above.\n" +#~ " * The value passed some validation when it was created, so you no longer have to validate it " +#~ "again at every use: 'PhoneNumber(String)` or `OddNumber(u32)`.\n" +#~ " \n" +#~ "
" +#~ msgstr "" +#~ " * Die Zahl wird in einigen Einheiten gemessen: „Newton“ im obigen Beispiel.\n" +#~ " * Der Wert hat bei seiner Erstellung einige Validierungen durchlaufen, sodass Sie ihn nicht " +#~ "mehr bei jeder Verwendung erneut validieren müssen: 'PhoneNumber(String)' oder " +#~ "'OddNumber(u32)'.\n" +#~ " \n" +#~ "
" + +#, fuzzy +#~ msgid "" +#~ "impl Person {\n" +#~ " fn new(name: String, age: u8) -> Person {\n" +#~ " Person { name, age }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Person {\n" +#~ " fn new(name: String, age: u8) -> Person {\n" +#~ " Person { Name, Alter }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "The `new` function could be written using `Self` as a type, as it is interchangeable with the " +#~ "struct type name" +#~ msgstr "" +#~ "Die „neue“ Funktion könnte unter Verwendung von „Self“ als Typ geschrieben werden, da sie mit " +#~ "dem Namen des Strukturtyps austauschbar ist" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug)]\n" +#~ "enum CoinFlip {\n" +#~ " Heads,\n" +#~ " Tails,\n" +#~ "}" +#~ msgstr "" +#~ "#[ableiten(Debuggen)]\n" +#~ "enum CoinFlip {\n" +#~ " Köpfe,\n" +#~ " Schwänze,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "#[rustfmt::skip]\n" +#~ "fn inspect(event: WebEvent) {\n" +#~ " match event {\n" +#~ " WebEvent::PageLoad => println!(\"page loaded\"),\n" +#~ " WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" +#~ " WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "#[rustfmt::skip]\n" +#~ "fn inspect(event: WebEvent) {\n" +#~ " Spielereignis {\n" +#~ " WebEvent::PageLoad => println!(\"Seite geladen\"),\n" +#~ " WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" +#~ " WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "* In the above example, accessing the `char` in `KeyPress`, or `x` and `y` in `Click` only " +#~ "works within a `match` statement.\n" +#~ "* `match` inspects a hidden discriminant field in the `enum`.\n" +#~ "* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::Click(Click)` with a top " +#~ "level `struct Click { ... }`. The inlined version cannot implement traits, for example." +#~ msgstr "" +#~ "* Im obigen Beispiel funktioniert der Zugriff auf „char“ in „KeyPress“ oder „x“ und „y“ in " +#~ "„Click“ nur innerhalb einer „match“-Anweisung.\n" +#~ "* „match“ untersucht ein verstecktes Diskriminanzfeld in „enum“.\n" +#~ "* `WebEvent::Click { ... }` ist nicht genau dasselbe wie `WebEvent::Click(Click)` mit einem Top-" +#~ "Level-`struct Click { ... }`. Die Inline-Version kann beispielsweise keine Traits " +#~ "implementieren." + +#, fuzzy +#~ msgid "" +#~ "enum Foo {\n" +#~ " A,\n" +#~ " B,\n" +#~ "}" +#~ msgstr "" +#~ "Aufzählung Foo {\n" +#~ " A,\n" +#~ " B,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "#[repr(u32)]\n" +#~ "enum Bar {\n" +#~ " A, // 0\n" +#~ " B = 10000,\n" +#~ " C, // 10001\n" +#~ "}" +#~ msgstr "" +#~ "#[repr(u32)]\n" +#~ "Aufzählungsbalken {\n" +#~ " A, // 0\n" +#~ " B = 10000,\n" +#~ " C, // 10001\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " * Internally Rust is using a field (discriminant) to keep track of the enum variant.\n" +#~ " * `Bar` enum demonstrates that there is a way to control the discriminant value and type. If " +#~ "`repr` is removed, the discriminant type takes 2 bytes, becuase 10001 fits 2 bytes.\n" +#~ " * As a niche optimization an enum discriminant is merged with the pointer so that " +#~ "`Option<&Foo>` is the same size as `&Foo`.\n" +#~ " * `Option` is another example of tight packing.\n" +#~ " * For [some types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees that " +#~ "`size_of::()` equals `size_of::>()`.\n" +#~ " * Zero-sized types allow for efficient implementation of `HashSet` using `HashMap` with `()` " +#~ "as the value." +#~ msgstr "" +#~ " * Rust verwendet intern ein Feld (Discriminant), um die Enum-Variante zu verfolgen.\n" +#~ " * `Bar` enum demonstriert, dass es eine Möglichkeit gibt, den Diskriminanzwert und -typ zu " +#~ "steuern. Wenn \"repr\" entfernt wird, nimmt der Diskriminantentyp 2 Bytes ein, da 10001 auf 2 " +#~ "Bytes passt.\n" +#~ " * Als Nischenoptimierung wird eine Enum-Diskriminante mit dem Zeiger zusammengeführt, sodass " +#~ "`Option<&Foo>` die gleiche Größe wie `&Foo` hat.\n" +#~ " * `Option` ist ein weiteres Beispiel für Tight Packing.\n" +#~ " * Für [einige Typen](https://doc.rust-lang.org/std/option/#representation) garantiert Rust, " +#~ "dass „size_of::()“ gleich „size_of::“ ist >()`.\n" +#~ " * Typen mit der Größe Null ermöglichen eine effiziente Implementierung von `HashSet` unter " +#~ "Verwendung von `HashMap` mit `()` als Wert." + +#, fuzzy +#~ msgid "" +#~ "impl Race {\n" +#~ " fn new(name: &str) -> Race { // No receiver, a static method\n" +#~ " Race { name: String::from(name), laps: Vec::new() }\n" +#~ " }" +#~ msgstr "" +#~ "impl Rennen {\n" +#~ " fn new(name: &str) -> Race { // Kein Empfänger, eine statische Methode\n" +#~ " Rennen { Name: String::from(Name), Runden: Vec::new() }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "fn divide_in_two(n: i32) -> Result {\n" +#~ " if n % 2 == 0 {\n" +#~ " Result::Ok(n / 2)\n" +#~ " } else {\n" +#~ " Result::Err(format!(\"cannot divide {} into two equal parts\", n))\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "fn divide_in_two(n: i32) -> Ergebnis {\n" +#~ " wenn n % 2 == 0 {\n" +#~ " Ergebnis::Okay(n / 2)\n" +#~ " } anders {\n" +#~ " Ergebnis::Err(format!(\"kann {} nicht in zwei gleiche Teile teilen\", n))\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "* Simple struct which tracks health statistics." +#~ msgstr "* Einfache Struktur, die Gesundheitsstatistiken verfolgt." + +#, fuzzy +#~ msgid "" +#~ "struct User {\n" +#~ " name: String,\n" +#~ " age: u32,\n" +#~ " weight: f32,\n" +#~ "}" +#~ msgstr "" +#~ "Struktur Benutzer {\n" +#~ " Name: Zeichenfolge,\n" +#~ " Alter: u32,\n" +#~ " Gewicht: f32,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl User {\n" +#~ " pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl Benutzer {\n" +#~ " pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +#~ " nicht implementiert!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn name(&self) -> &str {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn name(&self) -> &str {\n" +#~ " nicht implementiert!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn age(&self) -> u32 {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn alter(&selbst) -> u32 {\n" +#~ " nicht implementiert!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn weight(&self) -> f32 {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn Gewicht(&self) -> f32 {\n" +#~ " nicht implementiert!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn set_age(&mut self, new_age: u32) {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn set_age(&mut selbst, new_age: u32) {\n" +#~ " nicht implementiert!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn set_weight(&mut self, new_weight: f32) {\n" +#~ " unimplemented!()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " pub fn set_weight(&mut self, new_weight: f32) {\n" +#~ " nicht implementiert!()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Point {\n" +#~ " // add fields\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Punkt {\n" +#~ " // Felder hinzufügen\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Point {\n" +#~ " // add methods\n" +#~ "}" +#~ msgstr "" +#~ "impl Punkt {\n" +#~ " // Methoden hinzufügen\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Polygon {\n" +#~ " // add fields\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Polygon {\n" +#~ " // Felder hinzufügen\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Polygon {\n" +#~ " // add methods\n" +#~ "}" +#~ msgstr "" +#~ "impl Polygon {\n" +#~ " // Methoden hinzufügen\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Circle {\n" +#~ " // add fields\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Kreis {\n" +#~ " // Felder hinzufügen\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Circle {\n" +#~ " // add methods\n" +#~ "}" +#~ msgstr "" +#~ "impl Kreis {\n" +#~ " // Methoden hinzufügen\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub enum Shape {\n" +#~ " Polygon(Polygon),\n" +#~ " Circle(Circle),\n" +#~ "}" +#~ msgstr "" +#~ "Pub-Aufzählung Form {\n" +#~ " Vieleck(Vieleck),\n" +#~ " Kreis (Kreis),\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " fn round_two_digits(x: f64) -> f64 {\n" +#~ " (x * 100.0).round() / 100.0\n" +#~ " }" +#~ msgstr "" +#~ " fn round_two_digits(x: f64) -> f64 {\n" +#~ " (x * 100.0).round() / 100.0\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "* [`Option` and `Result`](std/option-result.md) types: used for optional values\n" +#~ " and [error handling](error-handling.md)." +#~ msgstr "" +#~ "* Typen von [`Option` und `Result`](std/option-result.md): Wird für optionale Werte verwendet\n" +#~ " und [Fehlerbehandlung](error-handling.md)." + +#, fuzzy +#~ msgid "* [`String`](std/string.md): the default string type used for owned data." +#~ msgstr "" +#~ "* [`String`](std/string.md): der Standard-String-Typ, der für eigene Daten verwendet wird." + +#, fuzzy +#~ msgid "* [`Vec`](std/vec.md): a standard extensible vector." +#~ msgstr "* [`Vec`](std/vec.md): ein erweiterbarer Standardvektor." + +#, fuzzy +#~ msgid "" +#~ "* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" +#~ " algorithm." +#~ msgstr "" +#~ "* [`HashMap`](std/hashmap.md): ein Hash-Map-Typ mit konfigurierbarem Hashing\n" +#~ " Algorithmus." + +#, fuzzy +#~ msgid "* [`Box`](std/box.md): an owned pointer for heap-allocated data." +#~ msgstr "* [`Box`](std/box.md): ein eigener Zeiger für Heap-zugewiesene Daten." + +#, fuzzy +#~ msgid "* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated data." +#~ msgstr "" +#~ "* [`Rc`](std/rc.md): ein gemeinsam genutzter referenzgezählter Zeiger für Heap-zugeordnete " +#~ "Daten." + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/string/struct.String.html\n" +#~ "[2]: https://doc.rust-lang.org/std/string/struct.String.html#deref-methods-str" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/string/struct.String.html\n" +#~ "[2]: https://doc.rust-lang.org/std/string/struct.String.html#deref-methods-str" + +#, fuzzy +#~ msgid "" +#~ "* `len` returns the size of the `String` in bytes, not its length in characters.\n" +#~ "* `chars` returns an iterator over the actual characters.\n" +#~ "* `String` implements `Deref` which transparently gives it access to `str`'s " +#~ "methods." +#~ msgstr "" +#~ "* `len` gibt die Größe des `String` in Bytes zurück, nicht seine Länge in Zeichen.\n" +#~ "* `chars` gibt einen Iterator über die eigentlichen Zeichen zurück.\n" +#~ "* `String` implementiert `Deref`, wodurch es transparent Zugriff auf die Methoden " +#~ "von `str` erhält." + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +#~ "[2]: https://doc.rust-lang.org/std/vec/struct.Vec.html#deref-methods-[T]" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +#~ "[2]: https://doc.rust-lang.org/std/vec/struct.Vec.html#deref-methods-[T]" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +#~ "[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +#~ "[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion" + +#, fuzzy +#~ msgid "" +#~ "* `Box` is like `std::unique_ptr` in C++.\n" +#~ "* In the above example, you can even leave out the `*` in the `println!` statement thanks to " +#~ "`Deref`." +#~ msgstr "" +#~ "* `Box` ist wie `std::unique_ptr` in C++.\n" +#~ "* Im obigen Beispiel können Sie dank `Deref` sogar das `*` in der `println!`-Anweisung " +#~ "weglassen." + +#, fuzzy +#~ msgid "" +#~ "If the `Box` was not used here and we attempted to embed a `List` directly into the `List`,\n" +#~ "the compiler would not compute a fixed size of the struct in memory, it would look infinite.\n" +#~ msgstr "" +#~ "`Box` löst dieses Problem, da es die gleiche Größe wie ein normaler Zeiger hat und nur auf den " +#~ "nächsten zeigt\n" +#~ "Element der `Liste` im Heap.\n" + +#~ msgid "" +#~ "`Box` solves this problem as it has the same size as a regular pointer and just points at the " +#~ "next\n" +#~ "element of the `List` in the heap. \n" +#~ msgstr "" +#~ "Wenn die `Box` hier nicht verwendet wurde und wir versucht haben, eine `List` direkt in die " +#~ "`List` einzubetten,\n" +#~ "Der Compiler würde keine feste Größe der Struktur im Speicher berechnen, es würde unendlich " +#~ "aussehen.\n" -#: src/exercises/day-3/solutions-afternoon.md:97 -msgid "" -"// ANCHOR: Drop\n" -"impl Drop for DirectoryIterator {\n" -" fn drop(&mut self) {\n" -" // Call closedir as needed.\n" -" // ANCHOR_END: Drop\n" -" if !self.dir.is_null() {\n" -" // SAFETY: self.dir is not NULL.\n" -" if unsafe { ffi::closedir(self.dir) } != 0 {\n" -" panic!(\"Could not close {:?}\", self.path);\n" -" }\n" -" }\n" -" }\n" -"}" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/cell/index.html\n" +#~ "[3]: ../concurrency/shared_state/arc.md" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/cell/index.html\n" +#~ "[3]: ../concurrency/shared_state/arc.md" -#: src/exercises/day-3/solutions-afternoon.md:111 -msgid "" -"// ANCHOR: main\n" -"fn main() -> Result<(), String> {\n" -" let iter = DirectoryIterator::new(\".\")?;\n" -" println!(\"files: {:#?}\", iter.collect::>());\n" -" Ok(())\n" -"}\n" -"// ANCHOR_END: main\n" -"```" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "* Like C++'s `std::shared_ptr`.\n" +#~ "* `clone` is cheap: creates a pointer to the same allocation and increases the reference " +#~ "count.\n" +#~ "* `make_mut` actually clones the inner value if necessary (\"clone-on-write\") and returns a " +#~ "mutable reference." +#~ msgstr "" +#~ "* Wie `std::shared_ptr` von C++.\n" +#~ "* `clone` ist billig: erstellt einen Zeiger auf die gleiche Zuweisung und erhöht die " +#~ "Referenzanzahl.\n" +#~ "* `make_mut` klont bei Bedarf tatsächlich den inneren Wert (\"clone-on-write\") und gibt eine " +#~ "veränderliche Referenz zurück." + +#, fuzzy +#~ msgid "" +#~ "1. As a relative path:\n" +#~ " * `foo` or `self::foo` refers to `foo` in the current module,\n" +#~ " * `super::foo` refers to `foo` in the parent module." +#~ msgstr "" +#~ "1. Als relativer Pfad:\n" +#~ " * `foo` oder `self::foo` bezieht sich auf `foo` im aktuellen Modul,\n" +#~ " * „super::foo“ bezieht sich auf „foo“ im übergeordneten Modul." + +#, fuzzy +#~ msgid "* Ignore all spaces. Reject number with less than two digits." +#~ msgstr "* Ignoriere alle Leerzeichen. Ablehnungsnummer mit weniger als zwei Ziffern." + +#, fuzzy +#~ msgid "" +#~ "* Moving from right to left, double every second digit: for the number `1234`,\n" +#~ " we double `3` and `1`." +#~ msgstr "" +#~ "* Bewegen Sie sich von rechts nach links, verdoppeln Sie jede zweite Ziffer: für die Zahl " +#~ "\"1234\",\n" +#~ " wir verdoppeln `3` und `1`." + +#, fuzzy +#~ msgid "" +#~ "* After doubling a digit, sum the digits. So doubling `7` becomes `14` which\n" +#~ " becomes `5`." +#~ msgstr "" +#~ "* Nachdem Sie eine Ziffer verdoppelt haben, addieren Sie die Ziffern. Das Verdoppeln von '7' " +#~ "wird also zu '14', was\n" +#~ " wird \"5\"." + +#, fuzzy +#~ msgid "* Sum all the undoubled and doubled digits." +#~ msgstr "* Summiere alle unverdoppelten und verdoppelten Ziffern." + +#, fuzzy +#~ msgid "* The credit card number is valid if the sum ends with `0`." +#~ msgstr "* Die Kreditkartennummer ist gültig, wenn die Summe mit `0` endet." + +#, fuzzy +#~ msgid "" +#~ "pub fn luhn(cc_number: &str) -> bool {\n" +#~ " unimplemented!()\n" +#~ "}" +#~ msgstr "" +#~ "pub fn luhn(cc_number: &str) -> bool {\n" +#~ " nicht implementiert!()\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +#~ " unimplemented!()\n" +#~ "}" +#~ msgstr "" +#~ "pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +#~ " nicht implementiert!()\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "* Traits: deriving traits, default methods, and important standard library\n" +#~ " traits." +#~ msgstr "" +#~ "* Merkmale: Ableitung von Merkmalen, Standardmethoden und wichtige Standardbibliothek\n" +#~ " Züge." + +#, fuzzy +#~ msgid "" +#~ "* Generics: generic data types, generic methods, monomorphization, and trait\n" +#~ " objects." +#~ msgstr "" +#~ "* Generics: generische Datentypen, generische Methoden, Monomorphisierung und Eigenschaften\n" +#~ " Objekte." + +#, fuzzy +#~ msgid "* Error handling: panics, `Result`, and the try operator `?`." +#~ msgstr "* Fehlerbehandlung: Panics, `Result` und der Try-Operator `?`." + +#, fuzzy +#~ msgid "* Testing: unit tests, documentation tests, and integration tests." +#~ msgstr "* Testen: Einheitentests, Dokumentationstests und Integrationstests." + +#, fuzzy +#~ msgid "" +#~ "* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" +#~ " functions." +#~ msgstr "" +#~ "* Unsicherer Rost: rohe Zeiger, statische Variablen, unsichere Funktionen und extern\n" +#~ " Funktionen." + +#, fuzzy +#~ msgid "" +#~ "struct Dog {\n" +#~ " name: String,\n" +#~ "}" +#~ msgstr "" +#~ "struct Hund {\n" +#~ " Name: Zeichenfolge,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Equals for Centimeter {\n" +#~ " fn equal(&self, other: &Centimeter) -> bool {\n" +#~ " self.0 == other.0\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Gleich für Zentimeter {\n" +#~ " fn gleich(&selbst, andere: &Zentimeter) -> bool {\n" +#~ " self.0 == andere.0\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "* `IntoIterator` is the trait that makes for loops work. It is implemented by collection types " +#~ "such as\n" +#~ " `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also implement it.\n" +#~ "* The `Iterator` trait implements many common functional programming operations over " +#~ "collections \n" +#~ " (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can find all the " +#~ "documentation\n" +#~ " about them. In Rust these functions should produce the code as efficient as equivalent " +#~ "imperative\n" +#~ " implementations.\n" +#~ " \n" +#~ "
" +#~ msgstr "" +#~ "* `IntoIterator` ist die Eigenschaft, die dafür sorgt, dass for-Schleifen funktionieren. Es " +#~ "wird durch Sammlungstypen wie implementiert\n" +#~ " `Vec` und Verweise darauf wie `&Vec` und `&[T]`. Ranges implementieren es auch.\n" +#~ "* Die Eigenschaft „Iterator“ implementiert viele gängige funktionale Programmieroperationen " +#~ "über Sammlungen\n" +#~ " (z. B. `map`, `filter`, `reduce`, etc). Dies ist die Eigenschaft, in der Sie die gesamte " +#~ "Dokumentation finden können\n" +#~ " über sie. In Rust sollten diese Funktionen den Code so effizient wie gleichwertig erzeugen\n" +#~ " Implementierungen.\n" +#~ " \n" +#~ "
" + +#, fuzzy +#~ msgid "" +#~ " fn add(self, other: Self) -> Self {\n" +#~ " Self {x: self.x + other.x, y: self.y + other.y}\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " fn add(self, other: Self) -> Self {\n" +#~ " Selbst {x: selbst.x + andere.x, y: selbst.y + andere.y}\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Point {\n" +#~ " fn x(&self) -> &T {\n" +#~ " &self.0 // + 10\n" +#~ " }" +#~ msgstr "" +#~ "imple Punkt {\n" +#~ " fn x(&selbst) -> &T {\n" +#~ " &self.0 // + 10\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // fn set_x(&mut self, x: T)\n" +#~ "}" +#~ msgstr "" +#~ " // fn set_x(&mut selbst, x: T)\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "fn get_x(name: impl Display) -> impl Display {\n" +#~ " format!(\"Hello {name}\")\n" +#~ "}" +#~ msgstr "" +#~ "fn get_x(name: impl Display) -> impl Display {\n" +#~ " format!(\"Hallo {Name}\")\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "enum Option_f64 {\n" +#~ " Some(f64),\n" +#~ " None,\n" +#~ "}" +#~ msgstr "" +#~ "Aufzählung Option_f64 {\n" +#~ " Einige (f64),\n" +#~ " Keiner,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Label {\n" +#~ " label: String,\n" +#~ "}" +#~ msgstr "" +#~ "Pub-Struktur Label {\n" +#~ " Label: Zeichenkette,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Label {\n" +#~ " fn new(label: &str) -> Label {\n" +#~ " Label {\n" +#~ " label: label.to_owned(),\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Label {\n" +#~ " fn new(label: &str) -> Label {\n" +#~ " Etikett {\n" +#~ " Bezeichnung: label.to_owned(),\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Button {\n" +#~ " label: Label,\n" +#~ " callback: Box,\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Schaltfläche {\n" +#~ " Etikett: Etikett,\n" +#~ " Rückruf: Box,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Button {\n" +#~ " fn new(label: &str, callback: Box) -> Button {\n" +#~ " Button {\n" +#~ " label: Label::new(label),\n" +#~ " callback,\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl-Schaltfläche {\n" +#~ " fn new(label: &str, callback: Box) -> Button {\n" +#~ " Taste {\n" +#~ " Label: Label::neu(Label),\n" +#~ " Ruf zurück,\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Window {\n" +#~ " title: String,\n" +#~ " widgets: Vec>,\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Fenster {\n" +#~ " Titel: Zeichenkette,\n" +#~ " Widgets: Vec>,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Window {\n" +#~ " fn new(title: &str) -> Window {\n" +#~ " Window {\n" +#~ " title: title.to_owned(),\n" +#~ " widgets: Vec::new(),\n" +#~ " }\n" +#~ " }" +#~ msgstr "" +#~ "impl-Fenster {\n" +#~ " fn new(title: &str) -> Fenster {\n" +#~ " Fenster {\n" +#~ " Titel: title.to_owned(),\n" +#~ " Widgets: Vec::new(),\n" +#~ " }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "impl Widget for Label {\n" +#~ " fn width(&self) -> usize {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl-Widget für Label {\n" +#~ " fn width(&self) -> use {\n" +#~ " nicht implementiert!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +#~ " unimplemented!()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +#~ " nicht implementiert!()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Widget for Button {\n" +#~ " fn width(&self) -> usize {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl-Widget für Schaltfläche {\n" +#~ " fn width(&self) -> use {\n" +#~ " nicht implementiert!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "impl Widget for Window {\n" +#~ " fn width(&self) -> usize {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl-Widget für Fenster {\n" +#~ " fn width(&self) -> use {\n" +#~ " nicht implementiert!()\n" +#~ " }" + +#, fuzzy +#~ msgid "This is a small text GUI demo." +#~ msgstr "Dies ist eine kleine Text-GUI-Demo." + +#, fuzzy +#~ msgid "" +#~ " match username_file.read_to_string(&mut username) {\n" +#~ " Ok(_) => Ok(username),\n" +#~ " Err(e) => Err(e),\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " match username_file.read_to_string(&mut username) {\n" +#~ " Ok(_) => Ok(Benutzername),\n" +#~ " Fehler(e) => Fehler(e),\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug)]\n" +#~ "enum ReadUsernameError {\n" +#~ " IoError(io::Error),\n" +#~ " EmptyUsername(String),\n" +#~ "}" +#~ msgstr "" +#~ "#[ableiten(Debuggen)]\n" +#~ "enum ReadUsernameError {\n" +#~ " IoError(io::Fehler),\n" +#~ " LeererBenutzername(String),\n" +#~ "}" + +#, fuzzy +#~ msgid "impl Error for ReadUsernameError {}" +#~ msgstr "impl-Fehler für ReadUsernameError {}" + +#, fuzzy +#~ msgid "" +#~ "impl Display for ReadUsernameError {\n" +#~ " fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" +#~ " match self {\n" +#~ " Self::IoError(e) => write!(f, \"IO error: {}\", e),\n" +#~ " Self::EmptyUsername(filename) => write!(f, \"Found no username in {}\", filename),\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Anzeige für ReadUsernameError {\n" +#~ " fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" +#~ " mit sich selbst übereinstimmen {\n" +#~ " Self::IoError(e) => write!(f, \"IO error: {}\", e),\n" +#~ " Self::EmptyUsername(filename) => write!(f, \"Keinen Benutzernamen gefunden in {}\", " +#~ "filename),\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl From for ReadUsernameError {\n" +#~ " fn from(err: io::Error) -> ReadUsernameError {\n" +#~ " ReadUsernameError::IoError(err)\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl From für ReadUsernameError {\n" +#~ " fn from(err: io::Error) -> ReadUsernameError {\n" +#~ " ReadUsernameError::IoError(err)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug, Error)]\n" +#~ "enum ReadUsernameError {\n" +#~ " #[error(\"Could not read: {0}\")]\n" +#~ " IoError(#[from] io::Error),\n" +#~ " #[error(\"Found no username in {0}\")]\n" +#~ " EmptyUsername(String),\n" +#~ "}" +#~ msgstr "" +#~ "#[ableiten(Debug, Fehler)]\n" +#~ "enum ReadUsernameError {\n" +#~ " #[error(\"Konnte nicht gelesen werden: {0}\")]\n" +#~ " IoError(#[von] io::Fehler),\n" +#~ " #[error(\"Keinen Benutzernamen in {0} gefunden\")]\n" +#~ " LeererBenutzername(String),\n" +#~ "}" + +#, fuzzy +#~ msgid "* Unit tests are supported throughout your code." +#~ msgstr "* Komponententests werden im gesamten Code unterstützt." + +#, fuzzy +#~ msgid "[solution]: solutions-afternoon.md" +#~ msgstr "[Lösung]: Lösungen-Nachmittag.md" + +#, fuzzy +#~ msgid "" +#~ "[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" +#~ "[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" +#~ "[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" +#~ "[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" +#~ msgstr "" +#~ "[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" +#~ "[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" +#~ "[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" +#~ "[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug)]\n" +#~ "struct DirectoryIterator {\n" +#~ " path: CString,\n" +#~ " dir: *mut ffi::DIR,\n" +#~ "}" +#~ msgstr "" +#~ "#[ableiten(Debuggen)]\n" +#~ "struct DirectoryIterator {\n" +#~ " Pfad: CString,\n" +#~ " dir: *mut ffi::DIR,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl DirectoryIterator {\n" +#~ " fn new(path: &str) -> Result {\n" +#~ " // Call opendir and return a Ok value if that worked,\n" +#~ " // otherwise return Err with a message.\n" +#~ " unimplemented!()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl DirectoryIterator {\n" +#~ " fn new(path: &str) -> Ergebnis {\n" +#~ " // Opendir aufrufen und einen Ok-Wert zurückgeben, wenn das funktioniert hat,\n" +#~ " // andernfalls Err mit einer Nachricht zurückgeben.\n" +#~ " nicht implementiert!()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Drop for DirectoryIterator {\n" +#~ " fn drop(&mut self) {\n" +#~ " // Call closedir as needed.\n" +#~ " unimplemented!()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Drop für DirectoryIterator {\n" +#~ " fn drop(&mut self) {\n" +#~ " // Gegebenenfalls closedir aufrufen.\n" +#~ " nicht implementiert!()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "Today we will look at two main topics:" +#~ msgstr "Heute werden wir uns mit zwei Hauptthemen befassen:" + +#, fuzzy +#~ msgid "* Concurrency: threads, channels, shared state, `Send` and `Sync`." +#~ msgstr "* Gleichzeitigkeit: Threads, Kanäle, gemeinsamer Status, „Senden“ und „Synchronisieren“." + +#, fuzzy +#~ msgid "" +#~ "* Android: building binaries and libraries, using AIDL, logging, and\n" +#~ " interoperability with C, C++, and Java." +#~ msgstr "" +#~ "* Android: Erstellung von Binärdateien und Bibliotheken, Verwendung von AIDL, Protokollierung " +#~ "und\n" +#~ " Interoperabilität mit C, C++ und Java." + +#, fuzzy +#~ msgid "" +#~ "* Notice that the thread is stopped before it reaches 10 — the main thread is\n" +#~ " not waiting." +#~ msgstr "" +#~ "* Beachten Sie, dass der Thread gestoppt wird, bevor er 10 erreicht – der Haupt-Thread ist es\n" +#~ " nicht warten." + +#, fuzzy +#~ msgid "" +#~ "* Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for\n" +#~ " the thread to finish." +#~ msgstr "" +#~ "* Verwenden Sie `let handle = thread::spawn(...)` und später `handle.join()`, um darauf zu " +#~ "warten\n" +#~ " den Thread zu beenden." -#: src/exercises/day-4/solutions-morning.md:1 #, fuzzy -msgid "# Day 4 Morning Exercise" -msgstr "# Tag 4 Morgengymnastik" +#~ msgid "* Trigger a panic in the thread, notice how this doesn't affect `main`." +#~ msgstr "* Lösen Sie eine Panik im Thread aus, beachten Sie, dass dies `main` nicht betrifft." -#: src/exercises/day-4/solutions-morning.md:3 #, fuzzy -msgid "## Dining Philosophers" -msgstr "## Essende Philosophen" +#~ msgid "" +#~ "* 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 "" +#~ "* Verwenden Sie den `Result`-Rückgabewert von `handle.join()`, um Zugriff auf die Panik zu " +#~ "erhalten\n" +#~ " Nutzlast. Dies ist ein guter Zeitpunkt, um über [`Any`] zu sprechen." -#: src/exercises/day-4/solutions-morning.md:5 #, fuzzy -msgid "([back to exercise](dining-philosophers.md))" -msgstr "([zurück zur Übung](dining-philosophers.md))" +#~ msgid "[`Any`]: https://doc.rust-lang.org/std/any/index.html" +#~ msgstr "[`Any`]: https://doc.rust-lang.org/std/any/index.html" -#: src/exercises/day-4/solutions-morning.md:22 -msgid "" -"// ANCHOR: Philosopher\n" -"use std::sync::mpsc;\n" -"use std::sync::{Arc, Mutex};\n" -"use std::thread;\n" -"use std::time::Duration;" -msgstr "" +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" -#: src/exercises/day-4/solutions-morning.md:30 #, fuzzy -msgid "" -"struct Philosopher {\n" -" name: String,\n" -" // ANCHOR_END: Philosopher\n" -" left_fork: Arc>,\n" -" right_fork: Arc>,\n" -" thoughts: mpsc::SyncSender,\n" -"}" -msgstr "" -"struct Philosoph {\n" -" Name: Zeichenfolge,\n" -" // ANCHOR_END: Philosoph\n" -" left_fork: Arc>,\n" -" right_fork: Arc>,\n" -" Gedanken: mpsc::SyncSender,\n" -"}" +#~ msgid "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" -#: src/exercises/day-4/solutions-morning.md:38 -msgid "" -"// 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" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-Mutex%3CT%3E\n" +#~ "[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-Mutex%3CT%3E\n" +#~ "[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" -#: src/exercises/day-4/solutions-morning.md:47 -msgid "" -" // 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();" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "[`PoisonError`]: https://doc.rust-lang.org/std/sync/struct.PoisonError.html \n" +#~ " \n" +#~ "" +#~ msgstr "" +#~ "[`PoisonError`]: https://doc.rust-lang.org/std/sync/struct.PoisonError.html\n" +#~ " \n" +#~ "" -#: src/exercises/day-4/solutions-morning.md:54 -msgid "" -" // ANCHOR: Philosopher-eat-end\n" -" println!(\"{} is eating...\", &self.name);\n" -" thread::sleep(Duration::from_millis(10));\n" -" }\n" -"}" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" +#~ "[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html\n" +#~ "[3]: ../unsafe/unsafe-traits.md" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" +#~ "[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html\n" +#~ "[3]: ../unsafe/unsafe-traits.md" -#: src/exercises/day-4/solutions-morning.md:63 -msgid "" -"fn main() {\n" -" // ANCHOR_END: Philosopher-eat-end\n" -" let (tx, rx) = mpsc::sync_channel(10);" -msgstr "" +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" -#: src/exercises/day-4/solutions-morning.md:67 -msgid "" -" let forks = (0..PHILOSOPHERS.len())\n" -" .map(|_| Arc::new(Mutex::new(Fork)))\n" -" .collect::>();" -msgstr "" +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Sync.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Sync.html" -#: src/exercises/day-4/solutions-morning.md:71 -msgid "" -" 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();" -msgstr "" +#, fuzzy +#~ msgid "* Dining philosophers: a classic problem in concurrency." +#~ msgstr "* Speisephilosophen: ein klassisches Problem der Nebenläufigkeit." -#: src/exercises/day-4/solutions-morning.md:76 -msgid "" -" // To avoid a deadlock, we have to break the symmetry\n" -" // somewhere. This will swap the forks without deinitializing\n" -" // either of them.\n" -" if i == forks.len() - 1 {\n" -" std::mem::swap(&mut left_fork, &mut right_fork);\n" -" }" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "struct Philosopher {\n" +#~ " name: String,\n" +#~ " // left_fork: ...\n" +#~ " // right_fork: ...\n" +#~ " // thoughts: ...\n" +#~ "}" +#~ msgstr "" +#~ "struct Philosoph {\n" +#~ " Name: Zeichenfolge,\n" +#~ " // left_fork: ...\n" +#~ " // right_fork: ...\n" +#~ " // Gedanken: ...\n" +#~ "}" -#: src/exercises/day-4/solutions-morning.md:83 -msgid "" -" let philosopher = Philosopher {\n" -" name: PHILOSOPHERS[i].to_string(),\n" -" thoughts: tx,\n" -" left_fork,\n" -" right_fork,\n" -" };" -msgstr "" +#, fuzzy +#~ msgid "" +#~ "fn main() {\n" +#~ " // Create forks" +#~ msgstr "" +#~ "fn Haupt() {\n" +#~ " // Gabeln erstellen" -#: src/exercises/day-4/solutions-morning.md:90 -msgid "" -" thread::spawn(move || {\n" -" for _ in 0..100 {\n" -" philosopher.eat();\n" -" philosopher.think();\n" -" }\n" -" });\n" -" }" -msgstr "" +#, fuzzy +#~ msgid " // Create philosophers" +#~ msgstr " // Philosophen erstellen" -#: src/exercises/day-4/solutions-morning.md:98 -msgid "" -" drop(tx);\n" -" for thought in rx {\n" -" println!(\"{}\", thought);\n" -" }\n" -"}\n" -"```" -msgstr "" +#, fuzzy +#~ msgid " // Make them think and eat" +#~ msgstr " // Lass sie denken und essen" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Error, Debug)]\n" +#~ "enum Error {\n" +#~ " #[error(\"request error: {0}\")]\n" +#~ " ReqwestError(#[from] reqwest::Error),\n" +#~ "}" +#~ msgstr "" +#~ "#[ableiten(Fehler, Debug)]\n" +#~ "Aufzählungsfehler {\n" +#~ " #[error(\"Anforderungsfehler: {0}\")]\n" +#~ " ReqwestError(#[from]reqwest::Error),\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " Ok(valid_urls)\n" +#~ "}" +#~ msgstr "" +#~ " Okay (valid_urls)\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://docs.rs/reqwest/\n" +#~ "[2]: https://docs.rs/scraper/\n" +#~ "[3]: https://docs.rs/thiserror/" +#~ msgstr "" +#~ "[1]: https://docs.rs/reqwest/\n" +#~ "[2]: https://docs.rs/scraper/\n" +#~ "[3]: https://docs.rs/thiserror/" + +#, fuzzy +#~ msgid "" +#~ "[crates]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/" +#~ msgstr "" +#~ "[Kisten]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/" + +#, fuzzy +#~ msgid "impl binder::Interface for BirthdayService {}" +#~ msgstr "impl binder::Interface für BirthdayService {}" + +#, fuzzy +#~ msgid "" +#~ "/// Connect to the BirthdayService.\n" +#~ "pub fn connect() -> Result, binder::StatusCode> {\n" +#~ " binder::get_interface(SERVICE_IDENTIFIER)\n" +#~ "}" +#~ msgstr "" +#~ "/// Mit dem Geburtstagsdienst verbinden.\n" +#~ "pub fn connect() -> Ergebnis, binder::StatusCode> {\n" +#~ " binder::get_interface(SERVICE_IDENTIFIER)\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://cxx.rs/\n" +#~ "[2]: https://cxx.rs/tutorial.html" +#~ msgstr "" +#~ "[1]: https://cxx.rs/\n" +#~ "[2]: https://cxx.rs/tutorial.html" + +#, fuzzy +#~ msgid "* Call your AIDL service with a client written in Rust." +#~ msgstr "* Rufen Sie Ihren AIDL-Service mit einem in Rust geschriebenen Client an." + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: setup\n" +#~ "struct Library {\n" +#~ " books: Vec,\n" +#~ "}" +#~ msgstr "" +#~ "// ANKER: einrichten\n" +#~ "Struktur Bibliothek {\n" +#~ " Bücher: Vec,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// 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" +#~ msgstr "" +#~ "// Dadurch ist es möglich, Buchwerte mit {} zu drucken.\n" +#~ "impl std::fmt::Anzeige für Buch {\n" +#~ " fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n" +#~ " schreibe!(f, \"{} ({})\", self.title, self.year)\n" +#~ " }\n" +#~ "}\n" +#~ "// ANCHOR_END: Einrichtung" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Library_new\n" +#~ "impl Library {\n" +#~ " fn new() -> Library {\n" +#~ " // ANCHOR_END: Library_new\n" +#~ " Library { books: Vec::new() }\n" +#~ " }" +#~ msgstr "" +#~ "// ANKER: Bibliothek_neu\n" +#~ "impl-Bibliothek {\n" +#~ " fn new() -> Bibliothek {\n" +#~ " // ANCHOR_END: Bibliothek_neu\n" +#~ " Bibliothek { Bücher: Vec::new() }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // ANCHOR: Library_len\n" +#~ " //fn len(self) -> usize {\n" +#~ " // unimplemented!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_len\n" +#~ " fn len(&self) -> usize {\n" +#~ " self.books.len()\n" +#~ " }" +#~ msgstr "" +#~ " // ANKER: Library_len\n" +#~ " //fn len(self) -> verwenden {\n" +#~ " // nicht implementiert!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_len\n" +#~ " fn len(&self) -> verwenden {\n" +#~ " self.books.len()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // ANCHOR: Library_is_empty\n" +#~ " //fn is_empty(self) -> bool {\n" +#~ " // unimplemented!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_is_empty\n" +#~ " fn is_empty(&self) -> bool {\n" +#~ " self.books.is_empty()\n" +#~ " }" +#~ msgstr "" +#~ " // ANKER: Bibliothek_ist_leer\n" +#~ " //fn is_empty(self) -> bool {\n" +#~ " // nicht implementiert!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Bibliothek_ist_leer\n" +#~ " fn is_empty(&self) -> bool {\n" +#~ " self.books.is_empty()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // ANCHOR: Library_add_book\n" +#~ " //fn add_book(self, book: Book) {\n" +#~ " // unimplemented!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_add_book\n" +#~ " fn add_book(&mut self, book: Book) {\n" +#~ " self.books.push(book)\n" +#~ " }" +#~ msgstr "" +#~ " // ANKER: Library_add_book\n" +#~ " //fn add_book(selbst, Buch: Buch) {\n" +#~ " // nicht implementiert!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_add_book\n" +#~ " fn add_book(&mut self, book: Buch) {\n" +#~ " self.books.push(Buch)\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // ANCHOR: Library_oldest_book\n" +#~ " //fn oldest_book(self) -> Option<&Book> {\n" +#~ " // unimplemented!()\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" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " // ANKER: Library_oldest_book\n" +#~ " //fn ältestes_buch(selbst) -> Option<&Buch> {\n" +#~ " // nicht implementiert!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Bibliothek_ältestes_Buch\n" +#~ " fn ältestes_buch(&self) -> Option<&Buch> {\n" +#~ " self.books.iter().min_by_key(|Buch| Buch.Jahr)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" +#~ "// ANCHOR: Point\n" +#~ "pub struct Point {\n" +#~ " // ANCHOR_END: Point\n" +#~ " x: i32,\n" +#~ " y: i32,\n" +#~ "}" +#~ msgstr "" +#~ "#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" +#~ "// Ankerpunkt\n" +#~ "pub struct Punkt {\n" +#~ " // ANCHOR_END: Punkt\n" +#~ " x: i32,\n" +#~ " y: i32,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Point-impl\n" +#~ "impl Point {\n" +#~ " // ANCHOR_END: Point-impl\n" +#~ " pub fn new(x: i32, y: i32) -> Point {\n" +#~ " Point { x, y }\n" +#~ " }" +#~ msgstr "" +#~ "// ANCHOR: Punkt-impl\n" +#~ "impl Punkt {\n" +#~ " // ANCHOR_END: Punkt-impl\n" +#~ " pub fn neu(x: i32, y: i32) -> Punkt {\n" +#~ " Punkt { x, y }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn magnitude(self) -> f64 {\n" +#~ " f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +#~ " }" +#~ msgstr "" +#~ " Pub fn Magnitude (selbst) -> f64 {\n" +#~ " f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn dist(self, other: Point) -> f64 {\n" +#~ " (self - other).magnitude()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " pub fn dist(self, other: Point) -> f64 {\n" +#~ " (selbst - andere).magnitude()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " fn add(self, other: Self) -> Self::Output {\n" +#~ " Self {\n" +#~ " x: self.x + other.x,\n" +#~ " y: self.y + other.y,\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " fn add(self, other: Self) -> Self::Output {\n" +#~ " Selbst {\n" +#~ " x: selbst.x + andere.x,\n" +#~ " y: self.y + other.y,\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " fn sub(self, other: Self) -> Self::Output {\n" +#~ " Self {\n" +#~ " x: self.x - other.x,\n" +#~ " y: self.y - other.y,\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " fn sub(self, other: Self) -> Self::Output {\n" +#~ " Selbst {\n" +#~ " x: self.x - other.x,\n" +#~ " y: self.y - other.y,\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Polygon\n" +#~ "pub struct Polygon {\n" +#~ " // ANCHOR_END: Polygon\n" +#~ " points: Vec,\n" +#~ "}" +#~ msgstr "" +#~ "// ANKER: Vieleck\n" +#~ "pub struct Polygon {\n" +#~ " // ANCHOR_END: Vieleck\n" +#~ " Punkte: Vec,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Polygon-impl\n" +#~ "impl Polygon {\n" +#~ " // ANCHOR_END: Polygon-impl\n" +#~ " pub fn new() -> Polygon {\n" +#~ " Polygon { points: Vec::new() }\n" +#~ " }" +#~ msgstr "" +#~ "// ANCHOR: Polygon-Impl\n" +#~ "impl Polygon {\n" +#~ " // ANCHOR_END: Polygon-Impl\n" +#~ " pub fn new() -> Polygon {\n" +#~ " Vieleck { Punkte: Vec::new() }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn left_most_point(&self) -> Option {\n" +#~ " self.points.iter().min_by_key(|p| p.x).copied()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn left_most_point(&self) -> Option {\n" +#~ " self.points.iter().min_by_key(|p| p.x).kopiert()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn iter(&self) -> impl Iterator {\n" +#~ " self.points.iter()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn iter(&self) -> impl Iterator {\n" +#~ " self.points.iter()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Circle\n" +#~ "pub struct Circle {\n" +#~ " // ANCHOR_END: Circle\n" +#~ " center: Point,\n" +#~ " radius: i32,\n" +#~ "}" +#~ msgstr "" +#~ "// ANKER: Kreis\n" +#~ "pub struct Kreis {\n" +#~ " // ANCHOR_END: Kreis\n" +#~ " Mittelpunkt,\n" +#~ " Radius: i32,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Circle-impl\n" +#~ "impl Circle {\n" +#~ " // ANCHOR_END: Circle-impl\n" +#~ " pub fn new(center: Point, radius: i32) -> Circle {\n" +#~ " Circle { center, radius }\n" +#~ " }" +#~ msgstr "" +#~ "// ANCHOR: Kreis-Impl\n" +#~ "impl Kreis {\n" +#~ " // ANCHOR_END: Kreis-Impl\n" +#~ " pub fn neu (Zentrum: Punkt, Radius: i32) -> Kreis {\n" +#~ " Kreis { Mittelpunkt, Radius }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn circumference(&self) -> f64 {\n" +#~ " 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +#~ " }" +#~ msgstr "" +#~ " pub fn Umfang(&self) -> f64 {\n" +#~ " 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn dist(&self, other: &Self) -> f64 {\n" +#~ " self.center.dist(other.center)\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " pub fn dist(&selbst, andere: &selbst) -> f64 {\n" +#~ " self.center.dist(anderes.center)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Shape\n" +#~ "pub enum Shape {\n" +#~ " Polygon(Polygon),\n" +#~ " Circle(Circle),\n" +#~ "}\n" +#~ "// ANCHOR_END: Shape" +#~ msgstr "" +#~ "// ANKER: Form\n" +#~ "Pub-Aufzählung Form {\n" +#~ " Vieleck(Vieleck),\n" +#~ " Kreis (Kreis),\n" +#~ "}\n" +#~ "// ANCHOR_END: Form" + +#, fuzzy +#~ msgid "" +#~ "impl From for Shape {\n" +#~ " fn from(poly: Polygon) -> Self {\n" +#~ " Shape::Polygon(poly)\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl From für Form {\n" +#~ " fn from(poly: Polygon) -> Self {\n" +#~ " Form::Polygon (poly)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl From for Shape {\n" +#~ " fn from(circle: Circle) -> Self {\n" +#~ " Shape::Circle(circle)\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Von für Form {\n" +#~ " fn from(Kreis: Kreis) -> Selbst {\n" +#~ " Form :: Kreis (Kreis)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Shape {\n" +#~ " pub fn perimeter(&self) -> f64 {\n" +#~ " match self {\n" +#~ " Shape::Polygon(poly) => poly.length(),\n" +#~ " Shape::Circle(circle) => circle.circumference(),\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "Impl-Form {\n" +#~ " pub fn perimeter(&self) -> f64 {\n" +#~ " mit sich selbst übereinstimmen {\n" +#~ " Shape::Polygon(poly) => poly.length(),\n" +#~ " Form::Kreis(Kreis) => Kreis.Umfang(),\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " sum % 10 == 0\n" +#~ "}" +#~ msgstr "" +#~ " Summe % 10 == 0\n" +#~ "}" + +#, fuzzy +#~ msgid "// ANCHOR_END: setup" +#~ msgstr "// ANCHOR_END: Einrichtung" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Window-width\n" +#~ "impl Widget for Window {\n" +#~ " fn width(&self) -> usize {\n" +#~ " // ANCHOR_END: Window-width\n" +#~ " std::cmp::max(\n" +#~ " self.title.chars().count(),\n" +#~ " self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +#~ " )\n" +#~ " }" +#~ msgstr "" +#~ "// ANCHOR: Fensterbreite\n" +#~ "impl-Widget für Fenster {\n" +#~ " fn width(&self) -> use {\n" +#~ " // ANCHOR_END: Fensterbreite\n" +#~ " std::cmp::max(\n" +#~ " self.title.chars().count(),\n" +#~ " self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +#~ " )\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Button-width\n" +#~ "impl Widget for Button {\n" +#~ " fn width(&self) -> usize {\n" +#~ " // ANCHOR_END: Button-width\n" +#~ " self.label.width() + 8 // add a bit of padding\n" +#~ " }" +#~ msgstr "" +#~ "// ANCHOR: Button-Breite\n" +#~ "impl-Widget für Schaltfläche {\n" +#~ " fn width(&self) -> use {\n" +#~ " // ANCHOR_END: Button-Breite\n" +#~ " self.label.width() + 8 // etwas Polsterung hinzufügen\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Label-width\n" +#~ "impl Widget for Label {\n" +#~ " fn width(&self) -> usize {\n" +#~ " // ANCHOR_END: Label-width\n" +#~ " self.label\n" +#~ " .lines()\n" +#~ " .map(|line| line.chars().count())\n" +#~ " .max()\n" +#~ " .unwrap_or(0)\n" +#~ " }" +#~ msgstr "" +#~ "// ANCHOR: Etikettenbreite\n" +#~ "impl-Widget für Label {\n" +#~ " fn width(&self) -> use {\n" +#~ " // ANCHOR_END: Etikettenbreite\n" +#~ " self.label\n" +#~ " .Linien()\n" +#~ " .map(|line| line.chars().count())\n" +#~ " .max()\n" +#~ " .unwrap_or(0)\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug)]\n" +#~ "struct DirectoryIterator {\n" +#~ " path: CString,\n" +#~ " dir: *mut ffi::DIR,\n" +#~ "}\n" +#~ "// ANCHOR_END: ffi" +#~ msgstr "" +#~ "#[ableiten(Debuggen)]\n" +#~ "struct DirectoryIterator {\n" +#~ " Pfad: CString,\n" +#~ " dir: *mut ffi::DIR,\n" +#~ "}\n" +#~ "// ANCHOR_END: ffi" + +#, fuzzy +#~ msgid "" +#~ "struct Philosopher {\n" +#~ " name: String,\n" +#~ " // ANCHOR_END: Philosopher\n" +#~ " left_fork: Arc>,\n" +#~ " right_fork: Arc>,\n" +#~ " thoughts: mpsc::SyncSender,\n" +#~ "}" +#~ msgstr "" +#~ "struct Philosoph {\n" +#~ " Name: Zeichenfolge,\n" +#~ " // ANCHOR_END: Philosoph\n" +#~ " left_fork: Arc>,\n" +#~ " right_fork: Arc>,\n" +#~ " Gedanken: mpsc::SyncSender,\n" +#~ "}" diff --git a/po/el.po b/po/el.po new file mode 100644 index 0000000..4cdc8b4 --- /dev/null +++ b/po/el.po @@ -0,0 +1,22020 @@ +msgid "" +msgstr "" +"Project-Id-Version: Comprehensive Rust 🦀\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2023-02-07 01:09+0000\n" +"Last-Translator: root \n" +"Language-Team: Greek \n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/SUMMARY.md:3 +msgid "Welcome to Comprehensive Rust 🦀" +msgstr "Καλώς ήρθατε στην Comprehensive Rust 🦀" + +#: src/SUMMARY.md:4 +msgid "Running the Course" +msgstr "Διεξαγωγή του μαθήματος" + +#: src/SUMMARY.md:5 +msgid "Course Structure" +msgstr "Δομή Μαθήματος" + +#: src/SUMMARY.md:6 +msgid "Ημέρα 4η" +msgstr "" + +#: src/SUMMARY.md:7 +msgid "Keyboard Shortcuts" +msgstr "Συντομεύσεις πληκτρολογίου" + +#: src/SUMMARY.md:8 +msgid "Translations" +msgstr "Μεταφράσεις" + +#: src/SUMMARY.md:9 +msgid "Using Cargo" +msgstr "Χρήση Cargo" + +#: src/SUMMARY.md:10 +msgid "Rust Ecosystem" +msgstr "Rust Οικοσύστημα" + +#: src/SUMMARY.md:11 +msgid "Code Samples" +msgstr "Δείγματα κώδικα" + +#: src/SUMMARY.md:12 +msgid "Running Cargo Locally" +msgstr "Εκτέλεση Cargo τοπικά" + +#: src/SUMMARY.md:15 +msgid "Day 1: Morning" +msgstr "1η μέρα: Πρωί" + +#: src/SUMMARY.md:19 src/SUMMARY.md:76 src/SUMMARY.md:129 src/SUMMARY.md:185 +#: src/SUMMARY.md:239 +msgid "Welcome" +msgstr "Καλως Ήρθατε" + +#: src/SUMMARY.md:20 +msgid "What is Rust?" +msgstr "Τι είναι η Rust;" + +#: src/SUMMARY.md:21 +msgid "Hello World!" +msgstr "Γειά σου Κόσμε!" + +#: src/SUMMARY.md:22 +msgid "Small Example" +msgstr "Μικρό Παράδειγμα" + +#: src/SUMMARY.md:23 +msgid "Why Rust?" +msgstr "Γιατί Rust;" + +#: src/SUMMARY.md:24 +msgid "Compile Time Guarantees" +msgstr "Εγγυήσεις Χρόνου Μεταγλώττισης" + +#: src/SUMMARY.md:25 +msgid "Runtime Guarantees" +msgstr "Εγγυήσεις χρόνου εκτέλεσης" + +#: src/SUMMARY.md:26 +msgid "Modern Features" +msgstr "Σύγχρονα Χαρακτηριστικά" + +#: src/SUMMARY.md:27 +msgid "Basic Syntax" +msgstr "Βασική Σύνταξη" + +#: src/SUMMARY.md:28 +msgid "Scalar Types" +msgstr "Βαθμωτοί Τύποι" + +#: src/SUMMARY.md:29 +msgid "Compound Types" +msgstr "Σύνθετοι τύποι" + +#: src/SUMMARY.md:30 +msgid "References" +msgstr "Αναφορές" + +#: src/SUMMARY.md:31 +msgid "Dangling References" +msgstr "Κρεμασμένες αναφορές" + +#: src/SUMMARY.md:32 +msgid "Slices" +msgstr "Φέτες" + +#: src/SUMMARY.md:33 +msgid "String vs str" +msgstr "String vs str" + +#: src/SUMMARY.md:34 +msgid "Functions" +msgstr "Συναρτήσεις" + +#: src/SUMMARY.md:35 +msgid "Rustdoc" +msgstr "" + +#: src/SUMMARY.md:36 src/SUMMARY.md:83 +msgid "Methods" +msgstr "Μέθοδοι" + +#: src/SUMMARY.md:37 +msgid "Overloading" +msgstr "Υπερφόρτωση" + +#: src/SUMMARY.md:38 src/SUMMARY.md:67 src/SUMMARY.md:91 src/SUMMARY.md:120 +#: src/SUMMARY.md:149 src/SUMMARY.md:177 src/SUMMARY.md:200 src/SUMMARY.md:227 +#: src/SUMMARY.md:253 src/SUMMARY.md:279 +msgid "Exercises" +msgstr "Ασκήσεις" + +#: src/SUMMARY.md:39 +msgid "Implicit Conversions" +msgstr "Έμμεσες μετατροπές" + +#: src/SUMMARY.md:40 +msgid "Arrays and for Loops" +msgstr "Πίνακες και βρόχοι for" + +#: src/SUMMARY.md:42 +msgid "Day 1: Afternoon" +msgstr "1η μέρα: Απόγευμα" + +#: src/SUMMARY.md:44 +msgid "Variables" +msgstr "Μεταβλητές" + +#: src/SUMMARY.md:45 +msgid "Type Inference" +msgstr "Συμπερασμός Τύπων" + +#: src/SUMMARY.md:46 +msgid "static & const" +msgstr "static & const" + +#: src/SUMMARY.md:47 +msgid "Scopes and Shadowing" +msgstr "Εμβέλια και σκίαση" + +#: src/SUMMARY.md:48 +msgid "Memory Management" +msgstr "Διαχείριση μνήμης" + +#: src/SUMMARY.md:49 +msgid "Stack vs Heap" +msgstr "Στοίβα και Σωρός" + +#: src/SUMMARY.md:50 +msgid "Stack Memory" +msgstr "Μνήμη στοίβας" + +#: src/SUMMARY.md:51 +msgid "Manual Memory Management" +msgstr "Χειροκίνητη διαχείριση μνήμης" + +#: src/SUMMARY.md:52 +msgid "Scope-Based Memory Management" +msgstr "Διαχείριση μνήμης βάσει εμβέλιας" + +#: src/SUMMARY.md:53 +msgid "Garbage Collection" +msgstr "Συλλογή σκουπιδιών" + +#: src/SUMMARY.md:54 +msgid "Rust Memory Management" +msgstr "Διαχείριση μνήμης στη Rust" + +#: src/SUMMARY.md:55 +msgid "Comparison" +msgstr "Σύγκριση" + +#: src/SUMMARY.md:56 +msgid "Ownership" +msgstr "Ιδιοκτησία" + +#: src/SUMMARY.md:57 +msgid "Move Semantics" +msgstr "Σημασιολογία μετακίνησης" + +#: src/SUMMARY.md:58 +msgid "Moved Strings in Rust" +msgstr "Μετακινημένες συμβολοσειρές στη Rust" + +#: src/SUMMARY.md:59 +msgid "Double Frees in Modern C++" +msgstr "Διπλές απελευθερώσεις μνήμης στη σύγχρονη C++" + +#: src/SUMMARY.md:60 +msgid "Moves in Function Calls" +msgstr "Μετακινήσεις σε κλήσεις συναρτήσεων" + +#: src/SUMMARY.md:61 +msgid "Copying and Cloning" +msgstr "Αντιγραφή και κλωνοποίηση" + +#: src/SUMMARY.md:62 +msgid "Borrowing" +msgstr "Δανεισμός" + +#: src/SUMMARY.md:63 +msgid "Shared and Unique Borrows" +msgstr "Κοινόχρηστα και μοναδικά δάνεια" + +#: src/SUMMARY.md:64 +msgid "Lifetimes" +msgstr "Διάρκειες" + +#: src/SUMMARY.md:65 +msgid "Lifetimes in Function Calls" +msgstr "Διάρκειες σε κλήσεις συναρτήσεων" + +#: src/SUMMARY.md:66 +msgid "Lifetimes in Data Structures" +msgstr "Διάρκειες ζωής σε δομές δεδομένων" + +#: src/SUMMARY.md:68 +msgid "Designing a Library" +msgstr "Σχεδιασμός Βιβλιοθηκών" + +#: src/SUMMARY.md:69 +msgid "Iterators and Ownership" +msgstr "Iterators και ιδιοκτησία" + +#: src/SUMMARY.md:72 +msgid "Day 2: Morning" +msgstr "2η μέρα: Πρωί" + +#: src/SUMMARY.md:77 +msgid "Structs" +msgstr "Δομές" + +#: src/SUMMARY.md:78 +msgid "Tuple Structs" +msgstr "Δομές Τούπλας" + +#: src/SUMMARY.md:79 +msgid "Field Shorthand Syntax" +msgstr "Συντομευμένο συντακτικό πεδίων" + +#: src/SUMMARY.md:80 +msgid "Enums" +msgstr "Απαριθμήσεις" + +#: src/SUMMARY.md:81 +msgid "Variant Payloads" +msgstr "Περιεχόμενο Παραλλαγών" + +#: src/SUMMARY.md:82 +msgid "Enum Sizes" +msgstr "Μέγεθος Απαριθμήσεων" + +#: src/SUMMARY.md:84 +msgid "Method Receiver" +msgstr "Δέκτης Μεθόδων" + +#: src/SUMMARY.md:85 src/SUMMARY.md:160 src/SUMMARY.md:195 +msgid "Example" +msgstr "Παράδειγμα" + +#: src/SUMMARY.md:86 +msgid "Pattern Matching" +msgstr "Αντιστοίχιση προτύπων" + +#: src/SUMMARY.md:87 +msgid "Destructuring Enums" +msgstr "Αποδόμηση Απαριθμήσεων" + +#: src/SUMMARY.md:88 +msgid "Destructuring Structs" +msgstr "Αποδόμηση Δομών" + +#: src/SUMMARY.md:89 +msgid "Destructuring Arrays" +msgstr "Αποδόμηση Πινάκων" + +#: src/SUMMARY.md:90 +msgid "Match Guards" +msgstr "Φύλακες Αντιστοιχίσεων" + +#: src/SUMMARY.md:92 +msgid "Health Statistics" +msgstr "Στατιστικά Υγείας" + +#: src/SUMMARY.md:93 +msgid "Points and Polygons" +msgstr "Σημεία και Πολύγωνα" + +#: src/SUMMARY.md:95 +msgid "Day 2: Afternoon" +msgstr "2η μέρα: Απόγευμα" + +#: src/SUMMARY.md:97 +msgid "Control Flow" +msgstr "Ροή ελέγχου" + +#: src/SUMMARY.md:98 +msgid "Blocks" +msgstr "Μπλοκ" + +#: src/SUMMARY.md:99 +msgid "if expressions" +msgstr "Eκφράσεις if" + +#: src/SUMMARY.md:100 +msgid "if let expressions" +msgstr "Εκφράσεις if let" + +#: src/SUMMARY.md:101 +msgid "while expressions" +msgstr "Εκφράσεις while" + +#: src/SUMMARY.md:102 +msgid "while let expressions" +msgstr "Εκφράσεις while let" + +#: src/SUMMARY.md:103 +msgid "for expressions" +msgstr "Εκφράσεις for" + +#: src/SUMMARY.md:104 +msgid "loop expressions" +msgstr "Εκφράσεις loop" + +#: src/SUMMARY.md:105 +msgid "match expressions" +msgstr "Εκφράσεις match" + +#: src/SUMMARY.md:106 +msgid "break & continue" +msgstr "break & continue" + +#: src/SUMMARY.md:107 +msgid "Standard Library" +msgstr "Στάνταρ Βιβλιοθήκη" + +#: src/SUMMARY.md:108 +msgid "Option and Result" +msgstr "Option και Result" + +#: src/SUMMARY.md:109 +msgid "String" +msgstr "Συμβολοσειρές" + +#: src/SUMMARY.md:110 +msgid "Vec" +msgstr "Vec" + +#: src/SUMMARY.md:111 +msgid "HashMap" +msgstr "HashMap" + +#: src/SUMMARY.md:112 +msgid "Box" +msgstr "Box" + +#: src/SUMMARY.md:113 +msgid "Recursive Data Types" +msgstr "Αναδρομικοί τύποι δεδομένων" + +#: src/SUMMARY.md:114 +msgid "Niche Optimization" +msgstr "Εξειδικευμένη Βελτιστοποίηση" + +#: src/SUMMARY.md:115 +msgid "Rc" +msgstr "Rc" + +#: src/SUMMARY.md:116 +msgid "Modules" +msgstr "Δομικές Μονάδες" + +#: src/SUMMARY.md:117 +msgid "Visibility" +msgstr "Ορατότητα" + +#: src/SUMMARY.md:118 +msgid "Paths" +msgstr "Μονοπάτια" + +#: src/SUMMARY.md:119 +msgid "Filesystem Hierarchy" +msgstr "Ιεραρχία συστήματος αρχείων" + +#: src/SUMMARY.md:121 +msgid "Luhn Algorithm" +msgstr "Αλγόριθμος Luhn" + +#: src/SUMMARY.md:122 +msgid "Strings and Iterators" +msgstr "Συμβολοσειρές και Επαναλήπτες" + +#: src/SUMMARY.md:125 +msgid "Day 3: Morning" +msgstr "3η μέρα: Πρωί" + +#: src/SUMMARY.md:130 +msgid "Traits" +msgstr "Χαρακτηριστικά" + +#: src/SUMMARY.md:131 +msgid "Deriving Traits" +msgstr "Εξάγωντας χαρακτηριστικά" + +#: src/SUMMARY.md:132 +msgid "Default Methods" +msgstr "Προ-υλοποιημένες μέθοδοι" + +#: src/SUMMARY.md:133 +msgid "Important Traits" +msgstr "Σημαντικά Χαρακτηριστικά" + +#: src/SUMMARY.md:134 +msgid "Iterator" +msgstr "Iterator" + +#: src/SUMMARY.md:135 +msgid "FromIterator" +msgstr "FromIterator" + +#: src/SUMMARY.md:136 +msgid "From and Into" +msgstr "From και Into" + +#: src/SUMMARY.md:137 +msgid "Read and Write" +msgstr "Read και Write" + +#: src/SUMMARY.md:138 +msgid "Add, Mul, ..." +msgstr "Add, Mul, ..." + +#: src/SUMMARY.md:139 +msgid "Drop" +msgstr "Drop" + +#: src/SUMMARY.md:140 +msgid "Default" +msgstr "" + +#: src/SUMMARY.md:141 +msgid "Generics" +msgstr "Γενικευσεις" + +#: src/SUMMARY.md:142 +msgid "Generic Data Types" +msgstr "Γενικοί τύποι δεδομένων" + +#: src/SUMMARY.md:143 +msgid "Generic Methods" +msgstr "Γενικές Μέθοδοι" + +#: src/SUMMARY.md:144 +msgid "Trait Bounds" +msgstr "Περιορισμοί χαρακτηριστικών" + +#: src/SUMMARY.md:145 +msgid "impl Trait" +msgstr "impl Trait" + +#: src/SUMMARY.md:146 +msgid "Closures" +msgstr "Κλεισίματα" + +#: src/SUMMARY.md:147 +msgid "Monomorphization" +msgstr "Μονομορφοποίηση" + +#: src/SUMMARY.md:148 +msgid "Trait Objects" +msgstr "Αντικείμενα Χαρακτηριστικών" + +#: src/SUMMARY.md:150 +msgid "A Simple GUI Library" +msgstr "Μια απλή βιβλιοθήκη GUI" + +#: src/SUMMARY.md:152 +msgid "Day 3: Afternoon" +msgstr "3η μέρα: Απόγευμα" + +#: src/SUMMARY.md:154 +msgid "Error Handling" +msgstr "Χειρισμός σφαλμάτων" + +#: src/SUMMARY.md:155 +msgid "Panics" +msgstr "Πανικοί" + +#: src/SUMMARY.md:156 +msgid "Catching Stack Unwinding" +msgstr "Πιάνοντας ξετυλίγματα στοίβας" + +#: src/SUMMARY.md:157 +msgid "Structured Error Handling" +msgstr "Δομημένη διαχείριση σφαλμάτων" + +#: src/SUMMARY.md:158 +msgid "Propagating Errors with ?" +msgstr "Διάδοση σφαλμάτων με ?" + +#: src/SUMMARY.md:159 +msgid "Converting Error Types" +msgstr "Μετατροπή τύπων σφαλμάτων" + +#: src/SUMMARY.md:161 +msgid "Deriving Error Enums" +msgstr "Εξαγωγή απαριθμήσεων σφαλμάτων" + +#: src/SUMMARY.md:162 +msgid "Dynamic Error Types" +msgstr "Δυναμικοί τύποι σφαλμάτων" + +#: src/SUMMARY.md:163 +msgid "Adding Context to Errors" +msgstr "Προσθήκη περιεχομένου στα σφάλματα" + +#: src/SUMMARY.md:164 +msgid "Testing" +msgstr "Τεστ" + +#: src/SUMMARY.md:165 +msgid "Unit Tests" +msgstr "Τεστ μονάδων" + +#: src/SUMMARY.md:166 +msgid "Test Modules" +msgstr "Δομικές μονάδες τεστ" + +#: src/SUMMARY.md:167 +msgid "Documentation Tests" +msgstr "Τεστ τεκμηρίωσης" + +#: src/SUMMARY.md:168 +msgid "Integration Tests" +msgstr "Τεστ ενσωμάτωσης" + +#: src/SUMMARY.md:169 +msgid "Unsafe Rust" +msgstr "Μη ασφαλής Rust" + +#: src/SUMMARY.md:170 +msgid "Dereferencing Raw Pointers" +msgstr "Αποαναφορά δεικτών" + +#: src/SUMMARY.md:171 +msgid "Mutable Static Variables" +msgstr "Μεταβλητές στατικές μεταβλητές" + +#: src/SUMMARY.md:172 +msgid "Unions" +msgstr "Σωματεία" + +#: src/SUMMARY.md:173 +msgid "Calling Unsafe Functions" +msgstr "Κλήση μη ασφαλών συναρτήσεων" + +#: src/SUMMARY.md:174 +msgid "Writing Unsafe Functions" +msgstr "Υλοποίηση μη ασφαλών συναρτήσεων" + +#: src/SUMMARY.md:175 +msgid "Extern Functions" +msgstr "Εξωτερικές Συναρτήσεις" + +#: src/SUMMARY.md:176 +msgid "Implementing Unsafe Traits" +msgstr "Υλοποίηση μη ασφαλών χαρακτηριστικών" + +#: src/SUMMARY.md:178 +msgid "Safe FFI Wrapper" +msgstr "Ασφαλές περιτύλιγμα FFI" + +#: src/SUMMARY.md:181 +msgid "Day 4: Morning" +msgstr "4η μέρα: Πρωί" + +#: src/SUMMARY.md:186 +msgid "Concurrency" +msgstr "Συγχρονισμός" + +#: src/SUMMARY.md:187 +msgid "Threads" +msgstr "Νήματα" + +#: src/SUMMARY.md:188 +msgid "Scoped Threads" +msgstr "Νήματα με εμβέλεια" + +#: src/SUMMARY.md:189 +msgid "Channels" +msgstr "Κανάλια" + +#: src/SUMMARY.md:190 +msgid "Unbounded Channels" +msgstr "Κανάλια χωρίς Όρια" + +#: src/SUMMARY.md:191 +msgid "Bounded Channels" +msgstr "Κανάλια με Όρια" + +#: src/SUMMARY.md:192 +msgid "Shared State" +msgstr "Κοινόχρηστα Δεδομένα" + +#: 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 και Sync" + +#: src/SUMMARY.md:196 +msgid "Send" +msgstr "Send" + +#: src/SUMMARY.md:196 +msgid "Sync" +msgstr "Sync" + +#: src/SUMMARY.md:199 +msgid "Examples" +msgstr "Παραδείγματα" + +#: src/SUMMARY.md:201 +msgid "Dining Philosophers" +msgstr "Δείπνο με φιλόσοφους" + +#: src/SUMMARY.md:202 +msgid "Multi-threaded Link Checker" +msgstr "Έλεγχος συνδέσμων πολλαπλών νημάτων" + +#: src/SUMMARY.md:204 +msgid "Day 4: Afternoon (Android)" +msgstr "4η μέρα: Απόγευμα (Android)" + +#: src/SUMMARY.md:204 src/SUMMARY.md:277 +msgid "Android" +msgstr "Android" + +#: src/SUMMARY.md:209 +msgid "Setup" +msgstr "Προετοιμασία" + +#: src/SUMMARY.md:210 +msgid "Build Rules" +msgstr "Κανόνες Κατασκευής" + +#: src/SUMMARY.md:211 +msgid "Binary" +msgstr "Εκτελέσιμα" + +#: src/SUMMARY.md:212 +msgid "Library" +msgstr "Βιβλιοθήκες" + +#: src/SUMMARY.md:213 +msgid "AIDL" +msgstr "AIDL" + +#: src/SUMMARY.md:214 +msgid "Interface" +msgstr "Διεπαφές" + +#: src/SUMMARY.md:215 +msgid "Implementation" +msgstr "Υλοποίηση" + +#: src/SUMMARY.md:216 +msgid "Server" +msgstr "Εξυπηρετητής" + +#: src/SUMMARY.md:217 +msgid "Deploy" +msgstr "Deploy" + +#: src/SUMMARY.md:218 +msgid "Client" +msgstr "Πελάτης" + +#: src/SUMMARY.md:219 +msgid "Changing API" +msgstr "Αλλαγή API" + +#: src/SUMMARY.md:220 src/SUMMARY.md:268 +msgid "Logging" +msgstr "Καταγραφή" + +#: src/SUMMARY.md:221 +msgid "Interoperability" +msgstr "Διαλειτουργικότητα" + +#: src/SUMMARY.md:222 +msgid "With C" +msgstr "Με C" + +#: src/SUMMARY.md:223 +msgid "Calling C with Bindgen" +msgstr "Καλώντας C με Bindgen" + +#: src/SUMMARY.md:224 +msgid "Calling Rust from C" +msgstr "Καλώντας Rust από C" + +#: src/SUMMARY.md:225 +msgid "With C++" +msgstr "Με C++" + +#: src/SUMMARY.md:226 +msgid "With Java" +msgstr "Με Java" + +#: src/SUMMARY.md:229 +msgid "Final Words" +msgstr "Κλείσιμο" + +#: src/SUMMARY.md:231 +msgid "Thanks!" +msgstr "Ευχαριστήρια" + +#: src/SUMMARY.md:232 +msgid "Other Resources" +msgstr "Επιπλέον Υλικό" + +#: src/SUMMARY.md:233 +msgid "Credits" +msgstr "" + +#: src/SUMMARY.md:237 +msgid "Bare Metal Rust: Morning" +msgstr "Rust χωρίς λειτουργικό σύστημα: Πρωί;" + +#: src/SUMMARY.md:240 +msgid "no_std" +msgstr "" + +#: src/SUMMARY.md:241 +msgid "A Minimal Example" +msgstr "# Μικρό Παράδειγμα" + +#: src/SUMMARY.md:242 +msgid "alloc" +msgstr "" + +#: src/SUMMARY.md:243 +msgid "Microcontrollers" +msgstr "Μικροεπεξεργαστές" + +#: src/SUMMARY.md:244 +msgid "Raw MMIO" +msgstr "" + +#: src/SUMMARY.md:245 +msgid "PACs" +msgstr "" + +#: src/SUMMARY.md:246 +msgid "HAL Crates" +msgstr "" + +#: src/SUMMARY.md:247 +msgid "Board Support Crates" +msgstr "Crates υποστήριξης πλακετών" + +#: src/SUMMARY.md:248 +msgid "The Type State Pattern" +msgstr "Το μοτίβο Τύπου Κατάστασης" + +#: src/SUMMARY.md:249 +msgid "embedded-hal" +msgstr "" + +#: src/SUMMARY.md:250 +msgid "probe-rs, cargo-embed" +msgstr "" + +#: src/SUMMARY.md:251 +msgid "Debugging" +msgstr "Αποσφαλμάτωση" + +#: src/SUMMARY.md:252 src/SUMMARY.md:270 +msgid "Other Projects" +msgstr "Επιπλέον Projects" + +#: src/SUMMARY.md:254 +msgid "Compass" +msgstr "Πυξίδα" + +#: src/SUMMARY.md:256 +msgid "Bare Metal Rust: Afternoon" +msgstr "Rust χωρίς λειτουργικό σύστημα: Απόγευμα" + +#: src/SUMMARY.md:258 +#, fuzzy +msgid "Application Processors" +msgstr "" + +#: src/SUMMARY.md:259 +#, fuzzy +msgid "Inline Assembly" +msgstr "" + +#: src/SUMMARY.md:260 +msgid "MMIO" +msgstr "" + +#: src/SUMMARY.md:261 +msgid "Let's Write a UART Driver" +msgstr "Ας γράψουμε έναν οδηγό UART" + +#: src/SUMMARY.md:262 +msgid "More Traits" +msgstr "Επιπλέον Χαρακτηριστικά" + +#: src/SUMMARY.md:263 +msgid "A Better UART Driver" +msgstr "Ένας καλύτερος οδηγός UART" + +#: src/SUMMARY.md:264 +msgid "Bitflags" +msgstr "" + +#: src/SUMMARY.md:265 +msgid "Multiple Registers" +msgstr "Πολλαπλοί καταχωρητές" + +#: src/SUMMARY.md:266 +msgid "Driver" +msgstr "Οδηγός" + +#: src/SUMMARY.md:267 src/SUMMARY.md:269 +#, fuzzy +msgid "Using It" +msgstr "Χρήση" + +#: src/SUMMARY.md:271 +msgid "Useful Crates" +msgstr "Χρήσιμα Crates" + +#: src/SUMMARY.md:272 +msgid "zerocopy" +msgstr "" + +#: src/SUMMARY.md:273 +msgid "aarch64-paging" +msgstr "" + +#: src/SUMMARY.md:274 +msgid "buddy_system_allocator" +msgstr "" + +#: src/SUMMARY.md:275 +msgid "tinyvec" +msgstr "" + +#: src/SUMMARY.md:276 +msgid "spin" +msgstr "" + +#: src/SUMMARY.md:278 +msgid "vmbase" +msgstr "" + +#: src/SUMMARY.md:280 +msgid "RTC Driver" +msgstr "Οδηγός RTC" + +#: src/SUMMARY.md:284 +msgid "Solutions" +msgstr "Λύσεις" + +#: src/SUMMARY.md:289 +msgid "Day 1 Morning" +msgstr "1η ημέρα Πρωί" + +#: src/SUMMARY.md:290 +msgid "Day 1 Afternoon" +msgstr "1η μέρα Απόγευμα" + +#: src/SUMMARY.md:291 +msgid "Day 2 Morning" +msgstr "2η ημέρα Πρωί" + +#: src/SUMMARY.md:292 +msgid "Day 2 Afternoon" +msgstr "2η μέρα Απόγευμα" + +#: src/SUMMARY.md:293 +msgid "Day 3 Morning" +msgstr "3η ημέρα Πρωί" + +#: src/SUMMARY.md:294 +msgid "Day 3 Afternoon" +msgstr "3η μέρα Απόγευμα" + +#: src/SUMMARY.md:295 +msgid "Day 4 Morning" +msgstr "4η ημέρα Πρωί" + +#: src/SUMMARY.md:296 +msgid "Bare Metal Rust Morning" +msgstr "Rust χωρίς λειτουργικό σύστημα: Πρωί" + +#: src/SUMMARY.md:297 +msgid "Bare Metal Rust Afternoon" +msgstr "Rust χωρίς λειτουργικό σύστημα Απόγευμα" + +#: src/welcome.md:1 +msgid "# Welcome to Comprehensive Rust 🦀" +msgstr "# Καλώς ήρθατε στην Comprehensive Rust 🦀" + +#: src/welcome.md:3 +msgid "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/" +"google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" +"google/comprehensive-rust/actions/workflows/build.yml)" +msgstr "" + +#: src/welcome.md:3 +msgid "Build workflow" +msgstr "Ροή εργασίας κατασκευής" + +#: src/welcome.md:3 +msgid "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/" +"google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" +"google/comprehensive-rust/actions/workflows/build.yml)\n" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/" +"comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)" +msgstr "" + +#: src/welcome.md:4 +msgid "GitHub contributors" +msgstr "Συνεργάτες GitHub" + +#: src/welcome.md:4 +msgid "" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/" +"comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)\n" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" +"rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers)" +msgstr "" + +#: src/welcome.md:5 +msgid "GitHub stars" +msgstr "Αστέρια GitHub" + +#: src/welcome.md:5 +msgid "" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" +"rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers)" +msgstr "" + +#: src/welcome.md:7 +msgid "" +"This is a four 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 "" +"Αυτό είναι ένα τετραήμερο μάθημα Rust που αναπτύχθηκε από την ομάδα Android. " +"Το μάθημα καλύπτει\n" +"το πλήρες φάσμα της Rust, από τη βασική σύνταξη έως τα προηγμένα θέματα όπως " +"οι γενικευμένοι τύποι\n" +"και διαχείριση σφαλμάτων. Περιλαμβάνει επίσης περιεχόμενο ειδικά για Android " +"την τελευταία ημέρα." + +#: src/welcome.md:11 +msgid "" +"The goal of the course is to teach you Rust. We assume you don't know " +"anything\n" +"about Rust and hope to:" +msgstr "" +"Ο στόχος του μαθήματος είναι να σας διδάξει τη γλώσσα Rust. Υποθέτουμε ότι " +"δεν ξέρετε τίποτα\n" +"σχετικά με τη Rust και ελπίζουμε να:" + +#: src/welcome.md:14 +msgid "" +"* Give you a comprehensive understanding of the Rust syntax and language.\n" +"* Enable you to modify existing programs and write new programs in Rust.\n" +"* Show you common Rust idioms." +msgstr "" +"* Σας δώσουμε μια ολοκληρωμένη κατανόηση της σύνταξης και της γλώσσας Rust.\n" +"* Σας καταστήσουμε ικανούς να τροποποιείτε υπάρχοντα προγράμματα και να " +"γράφετε νέα προγράμματα με τη Rust.\n" +"* Σας δείξουμε τους συνήθεις ιδιωματισμούς της Rust." + +#: src/welcome.md:18 +msgid "On Day 4, we will cover Android-specific things such as:" +msgstr "" +"Την 4η Ημέρα, θα καλύψουμε πράγματα που αφορούν συγκεκριμένα το Android, " +"όπως:" + +#: src/welcome.md:20 +msgid "" +"* Building Android components in Rust.\n" +"* AIDL servers and clients.\n" +"* Interoperability with C, C++, and Java." +msgstr "" +"* Δημιουργία Android components με Rust.\n" +"* Εξυπηρετητές και πελάτες AIDL.\n" +"* Διαλειτουργικότητα με C, C++ και Java." + +#: src/welcome.md:24 +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 "" +"Είναι σημαντικό να σημειωθεί ότι αυτό το μάθημα δεν καλύπτει την " +"ανάπτυξη**εφαρμογών** Android\n" +"σε Rust. Το κομμάτι του μαθήματος που αφορά τοAndroid\n" +"έχει να κάνει με ανάπτυξη κώδικα για το ίδιο το Android, ως λειτουργικό " +"σύστημα." + +#: src/welcome.md:28 +msgid "## Non-Goals" +msgstr "## Μη-Στόχοι" + +#: src/welcome.md:30 +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:" +msgstr "" +"Η Rust είναι μια μεγάλη γλώσσα και δεν θα μπορούμε να την καλύψουμε όλη σε " +"λίγες μέρες.\n" +"Μερικοί μη-στόχοι αυτού του μαθήματος είναι:" + +#: src/welcome.md:33 +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 "" +"* Χρήση async Rust --- θα αναφέρουμε στην async Rust μόνο όταν\n" +" καλύψουμε τα παραδοσιακά δομικά στοιχεία συγχρονισμού. Δείτε και " +"[Ασύγχρονος\n" +" Προγραμματισμός σε Rust](https://rust-lang.github.io/async-book/) για\n" +" λεπτομέρειες για αυτό το θέμα.\n" +"* Ανάπτυξη μακροεντολών, ανατρέξτε στο [Κεφάλαιο 19.5 στο Rust\n" +" Book](https://doc.rust-lang.org/book/ch19-06-macros.html) και [Rust by\n" +" Example](https://doc.rust-lang.org/rust-by-example/macros.html) αντ' αυτού." + +#: src/welcome.md:41 +msgid "## Assumptions" +msgstr "## Υποθέσεις" + +#: src/welcome.md:43 +msgid "" +"The course assumes that you already know how to program. Rust is a " +"statically\n" +"typed language and we will sometimes make comparisons with C and C++ to " +"better\n" +"explain or contrast the Rust approach." +msgstr "" +"Το μάθημα προϋποθέτει ότι γνωρίζετε ήδη πώς να προγραμματίζετε. Η Rust είναι " +"γλώσσα με στατικό\n" +"σύτημα τύπων και μερικές φορές θα κάνουμε συγκρίσεις με C και C++ για " +"καλύτερη\n" +"κατανόηση της προσέγγισης της Rust." + +#: src/welcome.md:47 +msgid "" +"If you know how to program in a dynamically typed language such as Python " +"or\n" +"JavaScript, then you will be able to follow along just fine too." +msgstr "" +"Εάν γνωρίζετε πώς να προγραμματίζετε σε μια γλώσσα με δυναμικό σύστημα τύπων " +"όπως Python ή\n" +"JavaScript, τότε θα μπορέσετε να ακολουθήσετε άνεση." + +#: src/welcome.md:50 src/cargo/rust-ecosystem.md:19 +#: src/cargo/code-samples.md:22 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/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/traits.md:41 src/traits/iterator.md:30 src/traits/from-iterator.md:15 +#: src/traits/from-into.md:27 src/traits/operators.md:24 src/traits/drop.md:32 +#: src/traits/default.md:38 src/generics/methods.md:23 +#: src/generics/trait-bounds.md:33 src/generics/impl-trait.md:21 +#: src/generics/closures.md:23 src/generics/trait-objects.md:88 +#: 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/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/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/bare-metal/minimal.md:15 +#: src/bare-metal/alloc.md:36 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 +#: src/bare-metal/microcontrollers/type-state.md:30 +#: src/bare-metal/microcontrollers/embedded-hal.md:17 +#: src/bare-metal/microcontrollers/probe-rs.md:14 +#: src/bare-metal/microcontrollers/debugging.md:25 +#: src/bare-metal/microcontrollers/other-projects.md:16 +#: src/exercises/bare-metal/morning.md:5 src/bare-metal/aps.md:7 +#: src/bare-metal/aps/inline-assembly.md:41 src/bare-metal/aps/mmio.md:7 +#: 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:47 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/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 +msgid "
" +msgstr "" + +#: src/welcome.md:52 +msgid "" +"This is an example of a _speaker note_. We will use these to add additional\n" +"information to the slides. This could be key points which the instructor " +"should\n" +"cover as well as answers to typical questions which come up in class." +msgstr "" +"Αυτό είναι ένα παράδειγμα _σημειώσεων ομιλητή_. Θα τις χρησιμοποιήσουμε για " +"να προσθέτουμε επιπλέον\n" +"πληροφορίες στις διαφάνειες. Αυτές θα μπορούσαν να είναι βασικά σημεία που " +"θα πρέπει να καλύψει ο εκπαιδευτής \n" +"καθώς και απαντήσεις σε συχνές ερωτήσεις που προκύπτουν στην τάξη." + +#: src/welcome.md:56 src/cargo/rust-ecosystem.md:67 +#: src/cargo/code-samples.md:35 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/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 +#: src/memory-management/rust.md:18 src/ownership/move-semantics.md:26 +#: 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/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/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:26 +#: 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/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/traits.md:47 src/traits/iterator.md:42 src/traits/from-iterator.md:26 +#: src/traits/from-into.md:33 src/traits/operators.md:38 src/traits/drop.md:42 +#: src/traits/default.md:47 src/generics/methods.md:31 +#: src/generics/trait-bounds.md:50 src/generics/impl-trait.md:44 +#: src/generics/closures.md:38 src/generics/trait-objects.md:102 +#: 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/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/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/bare-metal/no_std.md:65 +#: src/bare-metal/minimal.md:26 src/bare-metal/alloc.md:47 +#: 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 +#: src/bare-metal/microcontrollers/other-projects.md:26 +#: src/exercises/bare-metal/morning.md:11 src/bare-metal/aps.md:15 +#: src/bare-metal/aps/inline-assembly.md:51 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:51 src/bare-metal/aps/logging.md:52 +#: src/bare-metal/aps/logging/using.md:48 +#: src/bare-metal/useful-crates/zerocopy.md:51 +#: src/bare-metal/useful-crates/aarch64-paging.md:32 +#: src/bare-metal/useful-crates/buddy_system_allocator.md:28 +#: src/bare-metal/useful-crates/tinyvec.md:25 +#: src/bare-metal/useful-crates/spin.md:29 src/bare-metal/android/vmbase.md:25 +#: src/exercises/bare-metal/afternoon.md:11 +msgid "
" +msgstr "" + +#: src/running-the-course.md:1 +msgid "# Running the Course" +msgstr "# Διεξαγωγή του μαθήματος" + +#: 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 "> Αυτή η σελίδα είναι για τον εκπαιδευτή του μαθήματος." + +#: src/running-the-course.md:5 +msgid "" +"Here is a bit of background information about how we've been running the " +"course\n" +"internally at Google." +msgstr "" +"Ακολουθούν ορισμένες βασικές πληροφορίες σχετικά με τον τρόπο λειτουργίας " +"του μαθήματος\n" +"εσωτερικά στην Google." + +#: src/running-the-course.md:8 +msgid "Before you run the course, you will want to:" +msgstr "Για να διεξάξετε το μάθημα, πρέπει:" + +#: src/running-the-course.md:10 +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" +" notes!). When presenting, you should make sure to open the speaker notes " +"in a\n" +" 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" +" 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" +" 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" +" In particular, you will be doing a lot of live-coding as an instructor, " +"so a lectern won't\n" +" be very helpful for you.\n" +"\n" +"1. On the day of your course, show up to the room a little early to set " +"things\n" +" up. We recommend presenting directly using `mdbook serve` running on " +"your\n" +" laptop (see the [installation instructions][3]). This ensures optimal " +"performance with no lag as you change pages.\n" +" 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" +" 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." +msgstr "" +" 1. Εξοικειωθείτε με το υλικό του μαθήματος. Έχουμε συμπεριλάβει σημειώσεις " +"ομιλητών για να τονίσουμε τα βασικά σημεία (παρακαλούμε βοηθήστε μας " +"συνεισφέροντας περισσότερες σημειώσεις ομιλητή!). Κατά την παρουσίαση, θα " +"πρέπει να βεβαιωθείτε ότι ανοίγετε τις σημειώσεις του ομιλητή σε ένα " +"αναδυόμενο παράθυρο (κάντε κλικ στο σύνδεσμο με ένα μικρό βέλος δίπλα " +"στο \"Speaker Notes\"). Με αυτόν τον τρόπο έχετε μια καθαρή οθόνη για να " +"παρουσιάσετε στην τάξη.\n" +"\n" +" 1. Επιλέξτε το θέμα σας για το απόγευμα της τέταρτης ημέρας. Αυτό " +"μπορεί να βασίζεται στο κοινό που περιμένετε ή στη δική σας εμπειρία.\n" +"\n" +" 1. Αποφασίστε για τις ημερομηνίες. Επειδή το μάθημα είναι μεγάλο, σας " +"συνιστούμε να προγραμματίσετε τις τέσσερις ημέρες σε δύο εβδομάδες. Οι " +"προηγούμενοι συμμετέχοντες στο μάθημα θεωρούν χρήσιμο να υπάρχει ένα κενό στο " +"μάθημα, καθώς τους βοηθά να επεξεργάζονται όλες τις πληροφορίες που τους " +"δίνουμε.\n" +"\n" +" 1. Βρείτε ένα δωμάτιο αρκετά μεγάλο για όλους τους " +"συμμετέχοντες. Προτείνουμε μέγεθος τάξης 15-20 ατόμων. Είναι αρκετά μικρό " +"ώστε οι άνθρωποι να αισθάνονται άνετα να κάνουν ερωτήσεις - είναι επίσης " +"αρκετά μικρό ώστε ένας εκπαιδευτής να έχει χρόνο να απαντήσει. " +"Βεβαιωθείτε ότι το δωμάτιο έχει θρανία για εσάς και τους μαθητές: " +"όλοι θα πρέπει να μπορείτε να καθίσετε και να εργάζεστε με τους φορητούς " +"υπολογιστές σας. Συγκεκριμένα, θα γράψετε πολύ κώδικα ζωντανά ως " +"εκπαιδευτής, επομένως ένα αναλόγιο δεν θα σας βοηθήσει πολύ.\n" +"\n" +" 1. Την ημέρα του μαθήματος, εμφανιστείτε στην αίθουσα νωρίς για " +"να ρυθμίσετε τα πράγματα. Συνιστούμε την απευθείας παρουσίαση " +"χρησιμοποιώντας την υπηρεσία mdbook που εκτελείται στον φορητό υπολογιστή " +"σας (δείτε τις οδηγίες εγκατάστασης). Αυτό εξασφαλίζει βέλτιστη απόδοση " +"χωρίς καθυστέρηση καθώς αλλάζετε σελίδες. Η χρήση του φορητού υπολογιστή " +"σας θα σας επιτρέψει επίσης να διορθώσετε τυπογραφικά λάθη καθώς τα " +"εντοπίζετε εσείς ή οι συμμετέχοντες στο μάθημα.\n" +"\n" +" 1. Αφήστε τους μαθητές να λύσουν τις ασκήσεις μόνοι τους ή σε μικρές " +"ομάδες. Βεβαιωθείτε ότι τους ρωτάτε εάν έχουν κολλήσει ή εάν " +"υπάρχει κάτι με το οποίο μπορείτε να βοηθήσετε. Όταν δείτε ότι πολλά άτομα " +"έχουν το ίδιο πρόβλημα, αναφέρετέ το στην τάξη και προσφέρετε μια λύση, π.χ., " +"δείχνοντας στους μαθητές πού να βρουν τις σχετικές πληροφορίες στην τυπική " +"βιβλιοθήκη.\n" +"\n" +" 1. Ετοιμάστε οτιδήποτε χρειάζεστε για το απόγευμα της 4ης ημέρας." + +#: src/running-the-course.md:46 +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!" +msgstr "" +"Αυτό ήταν! Καλή επιτυχία στη διεξαγωγή του μαθήματος! Ελπίζουμε ότι θα είναι " +"τόσο διασκεδαστικό για εσάς όπως ήταν και για εμάς!" + +#: src/running-the-course.md:49 +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" +"better. Your students are also very welcome to [send us feedback][2]!" +msgstr "" +"Παρακαλούμε [παρέχετε σχόλια][1] μετά το μάθημα, ώστε να συνεχίσουμε να " +"βελτιώνουμε το υλικό. Θα θέλαμε να ακούσουμε τι πήγε καλά για εσάς και τι " +"μπορεί να γίνει\n" +"καλύτερα. Οι μαθητές σας είναι επίσης πολύ ευπρόσδεκτοι να [μας στείλουν " +"σχόλια][2]!" + +#: src/running-the-course/course-structure.md:1 +msgid "# Course Structure" +msgstr "# Δομή μαθήματος" + +#: src/running-the-course/course-structure.md:5 +msgid "The course is fast paced and covers a lot of ground:" +msgstr "Το μάθημα έχει γρήγορο ρυθμό και καλύπτει:" + +#: src/running-the-course/course-structure.md:7 +msgid "" +"* Day 1: Basic Rust, ownership and the borrow checker.\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." +msgstr "" +"* Ημέρα 1: Βασική Rust, ιδιοκτησία και ο έλεγχος δανείων.\n" +"* Ημέρα 2: Σύνθετοι τύποι δεδομένων, ταίριασμα προτύπων, τυπική βιβλιοθήκη.\n" +"* Ημέρα 3: Χαρακτηριστικά και γενικοί τύποι, χειρισμός σφαλμάτων, τεστ, μη " +"ασφαλής Rust.\n" +"* Ημέρα 4: Συγχρονισμός στη Rust. Rust στην πράξη." + +#: src/running-the-course/course-structure.md:12 +msgid "## Format" +msgstr "## Μορφή" + +#: src/running-the-course/course-structure.md:14 +msgid "" +"The course is meant to be very interactive and we recommend letting the\n" +"questions drive the exploration of Rust!" +msgstr "" +"Το μάθημα σχεδιάστηκε να είναι διαδραστικό και συνιστούμε να αφήσετε τις " +"ερωτήσεις να οδηγήσουν την κουβέντα γύρω από τη Rust!" + +#: src/running-the-course/day-4.md:1 +msgid "# Day 4" +msgstr "Ημέρα 4η" + +#: src/running-the-course/day-4.md:5 +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 "" +"Το απόγευμα της τέταρτης ημέρας μπορεί να καλύψει ένα θέμα της" +"αρεσκείας σας.\n" +"Σημειώστε το θέμα που επιλέξατε στην ανακοίνωση του μαθήματος ώστε οι" +"συμμετέχοντες να ξέρουν τι να περιμένουν." + +#: src/running-the-course/day-4.md:9 +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 "" +"Αυτή η φάση του μαθήματος είναι μια ευκαιρία για τους συμμετέχοντες " +"να δουν τη Rust στην πράξη, σε ένα πρότζεκτ με το οποίο μπορεί να είναι ήδη " +"εξοικειωμένοι. Μπορείτε να διαλέξετε θέματα που έχουμε ήδη προετοιμάσει, " +"ή κάτι δικό σας." + + +#: src/running-the-course/day-4.md:13 +msgid "Some topics need additional preparation:" +msgstr "Κάποια θέματα απαιτούν επιπλέον προετοιμασία." + +#: 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/`." +msgstr "" +"Εάν δεν επιλέξετε τo κομμάτι του Android την 4η Ημέρα, θα χρειαστείτε " +"ένα [AOSP\n" +" checkout][1]. Δημιουργήστε ένα checkout από το [αποθετήριο του μαθήματος]" +"[2] στον ίδιο\n" +" υπολογιστή και μετακινήστε τον κατάλογο `src/android/` στη ρίζα του AOSP " +"checkout σας.\n" +" Αυτό θα διασφαλίσει ότι το build system του Android βλέπει τα\n" +" Αρχεία `Android.bp` κάτω από τον φάκελο `src/android/`." + +#: src/running-the-course/day-4.md:22 +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." +msgstr "" +" Βεβαιωθείτε ότι το \"adb sync\" λειτουργεί με τον εξομοιωτή ή την συσκευή " +"σας και χτίστε όλα τα παραδείγματα του Android χρησιμοποιώντας το `src/" +"android/build_all.sh`. Διαβάστε το script για να δείτε\n" +" τις εντολές που εκτελεί και βεβαιωθείτε ότι λειτουργούν όταν τις " +"εκτελείτε με το χέρι." + +#: src/running-the-course/keyboard-shortcuts.md:1 +msgid "# Keyboard Shortcuts" +msgstr "# Συντομεύσεις πληκτρολογίου" + +#: src/running-the-course/keyboard-shortcuts.md:3 +msgid "There are several useful keyboard shortcuts in mdBook:" +msgstr "Υπάρχουν πολλές χρήσιμες συντομεύσεις πληκτρολογίου στο mdBook:" + +#: src/running-the-course/keyboard-shortcuts.md:5 +msgid "" +"* Arrow-Left: Navigate to the previous page.\n" +"* Arrow-Right: Navigate to the next page.\n" +"* Ctrl + Enter: Execute the code sample that has focus.\n" +"* s: Activate the search bar." +msgstr "" +"* Βέλος-Αριστερά: Μεταβείτε στην προηγούμενη σελίδα.\n" +"* Βέλος-Δεξιά: Μεταβείτε στην επόμενη σελίδα.\n" +"* Ctrl + Enter: Εκτελέστε το δείγμα κώδικα υπό εστίαση.\n" +"* s: Ενεργοποιήστε τη γραμμή αναζήτησης." + +#: src/running-the-course/translations.md:1 +msgid "# Translations" +msgstr "# Μεταφράσεις" + +#: src/running-the-course/translations.md:3 +msgid "" +"The course has been translated into other languages by a set of wonderful\n" +"volunteers:" +msgstr "Το μάθημα έχουμε μεταφραστεί σε άλλες γλώσσες από ένα σύνολο " +"εκπληκτικών εθελοντών:" + +#: src/running-the-course/translations.md:6 +msgid "" +"* [Brazilian Portuguese][pt-BR] by [@rastringer] and [@hugojacob].\n" +"* [Korean][ko] by [@keispace], [@jiyongp] and [@jooyunghan]." +msgstr "" + +#: src/running-the-course/translations.md:9 +msgid "Use the language picker in the top-right corner to switch between languages." +msgstr "" +"Χρησιμοποιήστε την επιλογή γλώσσας στην πάνω-δεξιά γωνία για να " +"αλλάξετε γλώσσα." + +#: src/running-the-course/translations.md:11 +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]." +msgstr "" +"Εάν θέλετε να βοηθήσετε στη μεταγλώττιση δείτε τις οδηγίες μας για το πώς" +"να ξεκινήσετε. Οι μεταφράσεις οργανώνονται στον [issue tracker]." + +#: src/cargo.md:1 +#, fuzzy +msgid "# Using Cargo" +msgstr "# Χρήση φορτίου" + +#: src/cargo.md:3 +#, fuzzy +msgid "" +"When you start reading about Rust, you will soon meet [Cargo](https://doc." +"rust-lang.org/cargo/), the standard tool\n" +"used in the Rust ecosystem to build and run Rust applications. Here we want " +"to\n" +"give a brief overview of what Cargo is and how it fits into the wider " +"ecosystem\n" +"and how it fits into this training." +msgstr "" +"Όταν αρχίσετε να διαβάζετε για το Rust, σύντομα θα συναντήσετε το [Cargo]" +"(https://doc.rust-lang.org/cargo/), το τυπικό εργαλείο\n" +"χρησιμοποιείται στο οικοσύστημα Rust για τη δημιουργία και εκτέλεση " +"εφαρμογών Rust. Εδώ θέλουμε\n" +"δώστε μια σύντομη επισκόπηση του τι είναι το Cargo και πώς ταιριάζει στο " +"ευρύτερο οικοσύστημα\n" +"και πώς ταιριάζει σε αυτή την εκπαίδευση." + +#: src/cargo.md:8 +#, fuzzy +msgid "## Installation" +msgstr "## Εγκατάσταση" + +#: src/cargo.md:10 +#, fuzzy +msgid "### Rustup (Recommended)" +msgstr "### Rustup (Συνιστάται)" + +#: src/cargo.md:12 +#, fuzzy +msgid "" +"You can follow the instructions to install cargo and rust compiler, among " +"other standard ecosystem tools with the [rustup][3] tool, which is " +"maintained by the Rust Foundation." +msgstr "" +"Μπορείτε να ακολουθήσετε τις οδηγίες για την εγκατάσταση του μεταγλωττιστή " +"φορτίου και σκουριάς, μεταξύ άλλων τυπικών εργαλείων οικοσυστήματος με το " +"εργαλείο [rustup][3], το οποίο διατηρείται από το Rust Foundation." + +#: src/cargo.md:14 +#, fuzzy +msgid "" +"Along with cargo and rustc, Rustup will install itself as a command line " +"utility that you can use to install/switch toolchains, setup cross " +"compilation, etc." +msgstr "" +"Μαζί με το cargo και το rustc, το Rustup θα εγκατασταθεί ως βοηθητικό " +"πρόγραμμα γραμμής εντολών που μπορείτε να χρησιμοποιήσετε για να " +"εγκαταστήσετε/εναλλάξετε αλυσίδες εργαλείων, να ρυθμίσετε τη διασταυρούμενη " +"μεταγλώττιση κ.λπ." + +#: src/cargo.md:16 +#, fuzzy +msgid "### Package Managers" +msgstr "### Διαχειριστές πακέτων" + +#: src/cargo.md:18 +#, fuzzy +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 "" +"Στο Debian/Ubuntu, μπορείτε να εγκαταστήσετε το Cargo και την πηγή Rust με" + +#: src/cargo.md:22 +msgid "" +"```shell\n" +"$ sudo apt install cargo rust-src rustfmt\n" +"```" +msgstr "" + +#: src/cargo.md:26 +#, fuzzy +msgid "" +"This will allow [rust-analyzer][1] to jump to the definitions. We suggest " +"using\n" +"[VS Code][2] to edit the code (but any LSP compatible editor works)." +msgstr "" +"Αυτό θα επιτρέψει στον [rust-analyzer][1] να μεταβεί στους ορισμούς. " +"Προτείνουμε τη χρήση\n" +"[VS Code][2] για να επεξεργαστείτε τον κώδικα (αλλά κάθε πρόγραμμα " +"επεξεργασίας συμβατό με LSP λειτουργεί)." + +#: src/cargo.md:29 +#, fuzzy +msgid "" +"Some folks also like to use the [JetBrains][4] family of IDEs, which do " +"their own analysis but have their own tradeoffs. If you prefer them, you can " +"install the [Rust Plugin][5]. Please take note that as of January 2023 " +"debugging only works on the CLion version of the JetBrains IDEA suite." +msgstr "" +"Σε μερικούς ανθρώπους αρέσει επίσης να χρησιμοποιούν την οικογένεια IDE " +"[JetBrains][4], που κάνουν τη δική τους ανάλυση αλλά έχουν τις δικές τους " +"ανταλλαγές. Εάν τα προτιμάτε, μπορείτε να εγκαταστήσετε το [Rust Plugin][5]. " +"Λάβετε υπόψη ότι από τον Ιανουάριο του 2023 ο εντοπισμός σφαλμάτων " +"λειτουργεί μόνο στην έκδοση CLion της σουίτας JetBrains IDEA." + +#: src/cargo/rust-ecosystem.md:1 +#, fuzzy +msgid "# The Rust Ecosystem" +msgstr "# Το οικοσύστημα της σκουριάς" + +#: src/cargo/rust-ecosystem.md:3 +#, fuzzy +msgid "" +"The Rust ecosystem consists of a number of tools, of which the main ones are:" +msgstr "" +"Το οικοσύστημα Rust αποτελείται από μια σειρά από εργαλεία, από τα οποία τα " +"κυριότερα είναι:" + +#: src/cargo/rust-ecosystem.md:5 +#, fuzzy +msgid "" +"* `rustc`: the Rust compiler which turns `.rs` files into binaries and " +"other\n" +" intermediate formats.\n" +"\n" +"* `cargo`: the Rust dependency manager and build tool. Cargo knows how to\n" +" download dependencies hosted on and it will pass them " +"to\n" +" `rustc` when building your project. Cargo also comes with a built-in test\n" +" runner which is used to execute unit tests.\n" +"\n" +"* `rustup`: the Rust toolchain installer and updater. This tool is used to\n" +" install and update `rustc` and `cargo` when new versions of Rust is " +"released.\n" +" In addition, `rustup` can also download documentation for the standard\n" +" library. You can have multiple versions of Rust installed at once and " +"`rustup`\n" +" will let you switch between them as needed." +msgstr "" +"* «rustup»: το πρόγραμμα εγκατάστασης και ενημέρωσης της αλυσίδας εργαλείων " +"Rust. Αυτό το εργαλείο χρησιμοποιείται για να\n" +" εγκαταστήστε και ενημερώστε τα «rustc» και «cargo» όταν κυκλοφορήσουν νέες " +"εκδόσεις του Rust.\n" +" Επιπλέον, το \"rustup\" μπορεί επίσης να κατεβάσει τεκμηρίωση για το " +"πρότυπο\n" +" βιβλιοθήκη. Μπορείτε να εγκαταστήσετε πολλές εκδόσεις του Rust ταυτόχρονα " +"και το \"rustup\".\n" +" θα σας επιτρέψει να κάνετε εναλλαγή μεταξύ τους ανάλογα με τις ανάγκες." + +#: 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 +#, fuzzy +msgid "Key points:" +msgstr "Βασικά σημεία:" + +#: src/cargo/rust-ecosystem.md:23 +msgid "" +"* Rust has a rapid release schedule with a new release coming out\n" +" every six weeks. New releases maintain backwards compatibility with\n" +" old releases --- plus they enable new functionality.\n" +"\n" +"* There are three release channels: \"stable\", \"beta\", and \"nightly\".\n" +"\n" +"* New features are being tested on \"nightly\", \"beta\" is what becomes\n" +" \"stable\" every six weeks.\n" +"\n" +"* Rust also has [editions]: the current edition is Rust 2021. Previous\n" +" editions were Rust 2015 and Rust 2018.\n" +"\n" +" * The editions are allowed to make backwards incompatible changes to\n" +" the language.\n" +"\n" +" * To prevent breaking code, editions are opt-in: you select the\n" +" edition for your crate via the `Cargo.toml` file.\n" +"\n" +" * To avoid splitting the ecosystem, Rust compilers can mix code\n" +" written for different editions.\n" +"\n" +" * Mention that it is quite rare to ever use the compiler directly not " +"through `cargo` (most users never do).\n" +"\n" +" * It might be worth alluding that Cargo itself is an extremely powerful " +"and comprehensive tool. It is capable of many advanced features including " +"but not limited to: \n" +" * Project/package structure\n" +" * [workspaces]\n" +" * Dev Dependencies and Runtime Dependency management/caching\n" +" * [build scripting]\n" +" * [global installation]\n" +" * It is also extensible with sub command plugins as well (such as " +"[cargo clippy]).\n" +" * Read more from the [official Cargo Book]" +msgstr "" + +#: src/cargo/code-samples.md:1 +#, fuzzy +msgid "# Code Samples in This Training" +msgstr "# Δείγματα κώδικα σε αυτήν την εκπαίδευση" + +#: 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" +"ensures a consistent experience for everyone." +msgstr "" +"Για αυτήν την εκπαίδευση, θα εξερευνήσουμε κυρίως τη γλώσσα Rust μέσω " +"παραδειγμάτων\n" +"που μπορεί να εκτελεστεί μέσω του προγράμματος περιήγησής σας. Αυτό κάνει τη " +"ρύθμιση πολύ πιο εύκολη και\n" +"εξασφαλίζει μια συνεπή εμπειρία για όλους." + +#: 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 "" +"Η εγκατάσταση Cargo εξακολουθεί να ενθαρρύνεται: θα σας διευκολύνει να το " +"κάνετε\n" +"γυμνάσια. Την τελευταία μέρα, θα κάνουμε μια μεγαλύτερη άσκηση που σας " +"δείχνει πώς να το κάνετε\n" +"εργαστείτε με εξαρτήσεις και για αυτό χρειάζεστε Cargo." + +#: src/cargo/code-samples.md:11 +#, fuzzy +msgid "The code blocks in this course are fully interactive:" +msgstr "Τα μπλοκ κώδικα σε αυτό το μάθημα είναι πλήρως διαδραστικά:" + +#: src/cargo/code-samples.md:13 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" println!(\"Edit me!\");\n" +"}\n" +"```" +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 "" +"Μπορείτε να χρησιμοποιήσετε το Ctrl + Enter για να εκτελέσετε τον " +"κώδικα όταν η εστίαση βρίσκεται στο\n" +"πλαίσιο κειμένου." + +#: 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:" +msgstr "" +"Τα περισσότερα δείγματα κώδικα είναι επεξεργάσιμα όπως φαίνεται παραπάνω. " +"Μερικά δείγματα κώδικα\n" +"δεν είναι επεξεργάσιμα για διάφορους λόγους:" + +#: 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" +"\n" +"* The embedded playgrounds lose their state the moment you navigate\n" +" away from the page! This is the reason that the students should\n" +" solve the exercises using a local Rust installation or via the\n" +" Playground." +msgstr "" +"* Οι ενσωματωμένες παιδικές χαρές χάνουν την κατάστασή τους τη στιγμή που " +"πλοηγείστε\n" +" μακριά από τη σελίδα! Αυτός είναι ο λόγος που πρέπει οι μαθητές\n" +" λύστε τις ασκήσεις χρησιμοποιώντας τοπική εγκατάσταση Rust ή μέσω του\n" +" Παιδική χαρά." + +#: src/cargo/running-locally.md:1 +#, fuzzy +msgid "# Running Code Locally with Cargo" +msgstr "# Κωδικός λειτουργίας τοπικά με φορτίο" + +#: 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 "" +"Εάν θέλετε να πειραματιστείτε με τον κώδικα στο δικό σας σύστημα, τότε θα " +"χρειαστείτε\n" +"για να εγκαταστήσετε πρώτα το Rust. Κάντε αυτό ακολουθώντας τις [οδηγίες στο " +"Rust\n" +"Βιβλίο][1]. Αυτό θα σας δώσει ένα λειτουργικό «rustc» και «cargo». Την εποχή " +"του\n" +"γράφοντας, η τελευταία σταθερή έκδοση Rust έχει αυτούς τους αριθμούς έκδοσης:" + +#: src/cargo/running-locally.md:8 +msgid "" +"```shell\n" +"% rustc --version\n" +"rustc 1.61.0 (fe5b13d68 2022-05-18)\n" +"% cargo --version\n" +"cargo 1.61.0 (a028ae4 2022-04-29)\n" +"```" +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" +"of the examples in this training:" +msgstr "" +"Εφόσον υπάρχει αυτό, ακολουθήστε αυτά τα βήματα για να δημιουργήσετε ένα " +"δυαδικό αρχείο Rust από ένα\n" +"από τα παραδείγματα αυτής της εκπαίδευσης:" + +#: src/cargo/running-locally.md:18 +msgid "" +"1. Click the \"Copy to clipboard\" button on the example you want to copy.\n" +"\n" +"2. Use `cargo new exercise` to create a new `exercise/` directory for your " +"code:\n" +"\n" +" ```shell\n" +" $ cargo new exercise\n" +" Created binary (application) `exercise` package\n" +" ```\n" +"\n" +"3. Navigate into `exercise/` and use `cargo run` to build and run your " +"binary:\n" +"\n" +" ```shell\n" +" $ cd exercise\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +" Running `target/debug/exercise`\n" +" Hello, world!\n" +" ```\n" +"\n" +"4. Replace the boiler-plate code in `src/main.rs` with your own code. For\n" +" example, using the example on the previous page, make `src/main.rs` look " +"like\n" +"\n" +" ```rust\n" +" fn main() {\n" +" println!(\"Edit me!\");\n" +" }\n" +" ```\n" +"\n" +"5. Use `cargo run` to build and run your updated binary:\n" +"\n" +" ```shell\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +" Running `target/debug/exercise`\n" +" Edit me!\n" +" ```\n" +"\n" +"6. Use `cargo check` to quickly check your project for errors, use `cargo " +"build`\n" +" to compile it without running it. You will find the output in `target/" +"debug/`\n" +" for a normal debug build. Use `cargo build --release` to produce an " +"optimized\n" +" release build in `target/release/`.\n" +"\n" +"7. You can add dependencies for your project by editing `Cargo.toml`. When " +"you\n" +" run `cargo` commands, it will automatically download and compile missing\n" +" dependencies for you." +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 "" +"Προσπαθήστε να ενθαρρύνετε τους συμμετέχοντες στην τάξη να εγκαταστήσουν το " +"Cargo και χρησιμοποιήστε το α\n" +"τοπικός συντάκτης. Θα τους κάνει τη ζωή πιο εύκολη αφού θα έχουν α\n" +"κανονικό περιβάλλον ανάπτυξης." + +#: src/welcome-day-1.md:1 +#, fuzzy +msgid "# Welcome to Day 1" +msgstr "# Καλώς ήρθατε στην Ημέρα 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 "" +"Αυτή είναι η πρώτη μέρα του Comprehensive Rust. Θα καλύψουμε πολύ έδαφος\n" +"σήμερα:" + +#: src/welcome-day-1.md:6 +msgid "" +"* Basic Rust syntax: variables, scalar and compound types, enums, structs,\n" +" references, functions, and methods.\n" +"\n" +"* Memory management: stack vs heap, manual memory management, scope-based " +"memory\n" +" management, and garbage collection.\n" +"\n" +"* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." +msgstr "" + +#: src/welcome-day-1.md:16 +#, fuzzy +msgid "Please remind the students that:" +msgstr "Υπενθυμίστε στους μαθητές ότι:" + +#: 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" +"* 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 "" +"* Θα πρέπει να κάνουν ερωτήσεις όταν τις πάρουν, μην τις αποθηκεύσετε μέχρι " +"το τέλος.\n" +"* Η τάξη προορίζεται να είναι διαδραστική και οι συζητήσεις ενθαρρύνονται " +"πολύ!\n" +" * Ως εκπαιδευτής, θα πρέπει να προσπαθήσετε να διατηρήσετε τις συζητήσεις " +"σχετικές, π.χ.\n" +" κρατήστε τη σχετική με το πώς κάνει τα πράγματα ο Rust σε σχέση με " +"κάποια άλλη γλώσσα. Μπορεί να είναι\n" +" δύσκολο να βρεις τη σωστή ισορροπία, αλλά σφάλλησε να επιτρέψεις " +"συζητήσεις\n" +" αφού εμπλέκουν τους ανθρώπους πολύ περισσότερο από τη μονόδρομη " +"επικοινωνία.\n" +"* Οι ερωτήσεις πιθανότατα θα σημαίνουν ότι είμαστε για τα πράγματα πριν από " +"τις διαφάνειες.\n" +" * Αυτό είναι απολύτως εντάξει! Η επανάληψη είναι ένα σημαντικό μέρος της " +"κλίσης. Θυμάμαι\n" +" ότι οι διαφάνειες είναι απλώς μια υποστήριξη και είστε ελεύθεροι να τις " +"παραλείψετε όπως εσείς\n" +" αρέσει." + +#: 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 "" +"Η ιδέα για την πρώτη μέρα είναι να δείξουμε _αρκετά_ Rust για να μπορέσει να " +"μιλήσει\n" +"για το περίφημο δάνειο πούλι. Ο τρόπος με τον οποίο η Rust χειρίζεται τη " +"μνήμη είναι ένα σημαντικό χαρακτηριστικό\n" +"και αυτό θα πρέπει να το δείξουμε αμέσως στους μαθητές." + +#: 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 "" +"Εάν το διδάσκετε σε μια τάξη, αυτό είναι ένα καλό μέρος για να το δείτε\n" +"πρόγραμμα. Προτείνουμε να χωρίσετε την ημέρα σε δύο μέρη (ακολουθώντας τις " +"διαφάνειες):" + +#: src/welcome-day-1.md:36 +#, fuzzy +msgid "" +"* Morning: 9:00 to 12:00,\n" +"* Afternoon: 13:00 to 16:00." +msgstr "" +"* Πρωί: 9:00 έως 12:00,\n" +"* Απόγευμα: 13:00 έως 16:00." + +#: 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!" +msgstr "" +"Μπορείτε φυσικά να το προσαρμόσετε όπως απαιτείται. Φροντίστε να " +"συμπεριλάβετε διαλείμματα,\n" +"προτείνουμε ένα διάλειμμα κάθε ώρα!" + +#: src/welcome-day-1/what-is-rust.md:1 +#, fuzzy +msgid "# What is Rust?" +msgstr "# Τι είναι το 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 είναι μια νέα γλώσσα προγραμματισμού που κυκλοφόρησε το 1.0 το 2015:" + +#: 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" +"* Rust supports many [platforms and\n" +" architectures](https://doc.rust-lang.org/nightly/rustc/platform-support." +"html):\n" +" * x86, ARM, WebAssembly, ...\n" +" * Linux, Mac, Windows, ...\n" +"* Rust is used for a wide range of devices:\n" +" * firmware and boot loaders,\n" +" * smart displays,\n" +" * mobile phones,\n" +" * desktops,\n" +" * servers." +msgstr "" +"* Η Rust είναι μια στατικά μεταγλωττισμένη γλώσσα με παρόμοιο ρόλο με τη C+" +"+\n" +" * Το \"rustc\" χρησιμοποιεί το LLVM ως backend του.\n" +"* Το Rust υποστηρίζει πολλές [πλατφόρμες και\n" +" αρχιτεκτονικές](https://doc.rust-lang.org/nightly/rustc/platform-support." +"html):\n" +" * x86, ARM, WebAssembly, ...\n" +" * Linux, Mac, Windows, ...\n" +"* Το Rust χρησιμοποιείται για ένα ευρύ φάσμα συσκευών:\n" +" * υλικολογισμικό και φορτωτές εκκίνησης,\n" +" * έξυπνες οθόνες,\n" +" * κινητά τηλέφωνα,\n" +" * επιτραπέζιοι υπολογιστές,\n" +" * διακομιστές." + +#: src/welcome-day-1/what-is-rust.md:21 +#, fuzzy +msgid "Rust fits in the same area as C++:" +msgstr "Η σκουριά ταιριάζει στην ίδια περιοχή με το C++:" + +#: src/welcome-day-1/what-is-rust.md:23 +#, fuzzy +msgid "" +"* High flexibility.\n" +"* High level of control.\n" +"* Can be scaled down to very constrained devices like mobile phones.\n" +"* Has no runtime or garbage collection.\n" +"* Focuses on reliability and safety without sacrificing performance." +msgstr "" +"* Υψηλή ευελιξία.\n" +"* Υψηλό επίπεδο ελέγχου.\n" +"* Μπορεί να μειωθεί σε πολύ περιορισμένες συσκευές όπως κινητά τηλέφωνα.\n" +"* Δεν έχει χρόνο εκτέλεσης ή συλλογή σκουπιδιών.\n" +"* Εστιάζει στην αξιοπιστία και την ασφάλεια χωρίς να θυσιάζει την απόδοση." + +#: src/hello-world.md:1 +#, fuzzy +msgid "# Hello World!" +msgstr "# Γειά σου Κόσμε!" + +#: src/hello-world.md:3 +#, fuzzy +msgid "" +"Let us jump into the simplest possible Rust program, a classic Hello World\n" +"program:" +msgstr "" +"Ας μεταβούμε στο απλούστερο δυνατό πρόγραμμα Rust, ένα κλασικό Hello World\n" +"πρόγραμμα:" + +#: src/hello-world.md:6 +msgid "" +"```rust\n" +"fn main() {\n" +" println!(\"Hello 🌍!\");\n" +"}\n" +"```" +msgstr "" + +#: src/hello-world.md:12 +#, fuzzy +msgid "What you see:" +msgstr "Τι βλέπεις:" + +#: 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" +"* The `main` function is the entry point of the program.\n" +"* Rust has hygienic macros, `println!` is an example of this.\n" +"* Rust strings are UTF-8 encoded and can contain any Unicode character." +msgstr "" +"* Οι συναρτήσεις εισάγονται με το «fn».\n" +"* Τα μπλοκ οριοθετούνται με σγουρά τιράντες όπως στο C και το C++.\n" +"* Η λειτουργία «κύρια» είναι το σημείο εισόδου του προγράμματος.\n" +"* Το Rust έχει υγιεινές μακροεντολές, το «println!» είναι ένα παράδειγμα " +"αυτού.\n" +"* Οι συμβολοσειρές Rust έχουν κωδικοποίηση UTF-8 και μπορούν να περιέχουν " +"οποιονδήποτε χαρακτήρα Unicode." + +#: 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 "" +"Αυτή η διαφάνεια προσπαθεί να κάνει τους μαθητές άνετα με τον κώδικα Rust. " +"Θα δουν\n" +"ένας τόνος από αυτό τις επόμενες τέσσερις ημέρες, οπότε ξεκινάμε μικρά με " +"κάτι οικείο." + +#: src/hello-world.md:27 +msgid "" +"* Rust is very much like other languages in the C/C++/Java tradition. It is\n" +" imperative (not functional) and it doesn't try to reinvent things unless\n" +" absolutely necessary.\n" +"\n" +"* Rust is modern with full support for things like Unicode.\n" +"\n" +"* Rust uses macros for situations where you want to have a variable number " +"of\n" +" arguments (no function [overloading](basic-syntax/functions-interlude." +"md)).\n" +"\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)." +msgstr "" + +#: src/hello-world/small-example.md:1 +#, fuzzy +msgid "# Small Example" +msgstr "# Μικρό Παράδειγμα" + +#: src/hello-world/small-example.md:3 +#, fuzzy +msgid "Here is a small example program in Rust:" +msgstr "Ακολουθεί ένα μικρό παράδειγμα προγράμματος στο Rust:" + +#: src/hello-world/small-example.md:5 +msgid "" +"```rust,editable\n" +"fn main() { // Program entry point\n" +" let mut x: i32 = 6; // Mutable variable binding\n" +" print!(\"{x}\"); // Macro for printing, like printf\n" +" while x != 1 { // No parenthesis around expression\n" +" if x % 2 == 0 { // Math like in other languages\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +" print!(\" -> {x}\");\n" +" }\n" +" println!();\n" +"}\n" +"```" +msgstr "" + +#: 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 "" +"Ο κώδικας υλοποιεί την εικασία Collatz: πιστεύεται ότι ο βρόχος θα\n" +"πάντα τελειώνει, αλλά αυτό δεν έχει ακόμη αποδειχθεί. Επεξεργαστείτε τον " +"κώδικα και παίξτε με διαφορετικά\n" +"εισροές." + +#: src/hello-world/small-example.md:29 +msgid "" +"* Explain that all variables are statically typed. Try removing `i32` to " +"trigger\n" +" type inference. Try with `i8` instead and trigger a runtime integer " +"overflow.\n" +"\n" +"* Change `let mut x` to `let x`, discuss the compiler error.\n" +"\n" +"* Show how `print!` gives a compilation error if the arguments don't match " +"the\n" +" format string.\n" +"\n" +"* Show how you need to use `{}` as a placeholder if you want to print an\n" +" expression which is more complex than just a single variable.\n" +"\n" +"* Show the students the standard library, show them how to search for `std::" +"fmt`\n" +" 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 "" + +#: src/why-rust.md:1 +#, fuzzy +msgid "# Why Rust?" +msgstr "# Γιατί Rust;" + +#: src/why-rust.md:3 +#, fuzzy +msgid "Some unique selling points of Rust:" +msgstr "Μερικά μοναδικά σημεία πώλησης του Rust:" + +#: src/why-rust.md:5 +#, fuzzy +msgid "" +"* Compile time memory safety.\n" +"* Lack of undefined runtime behavior.\n" +"* Modern language features." +msgstr "" +"* Συγκεντρώστε την ασφάλεια της μνήμης χρόνου.\n" +"* Έλλειψη απροσδιόριστης συμπεριφοράς χρόνου εκτέλεσης.\n" +"* Χαρακτηριστικά σύγχρονης γλώσσας." + +#: 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 "" +"Φροντίστε να ρωτήσετε την τάξη με ποιες γλώσσες έχουν εμπειρία. Σε " +"συνάρτηση\n" +"στην απάντηση μπορείτε να επισημάνετε διαφορετικά χαρακτηριστικά του Rust:" + +#: 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" +" have the memory unsafety issues. In addition, you get a modern language " +"with\n" +" constructs like pattern matching and built-in dependency management.\n" +"\n" +"* Experience with Java, Go, Python, JavaScript...: You get the same memory " +"safety\n" +" as in those languages, plus a similar high-level language feeling. In " +"addition\n" +" 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 "" +"* Εμπειρία με Java, Go, Python, JavaScript...: Έχετε την ίδια ασφάλεια " +"μνήμης\n" +" όπως σε αυτές τις γλώσσες, συν ένα παρόμοιο γλωσσικό συναίσθημα υψηλού " +"επιπέδου. Επιπλέον\n" +" έχετε γρήγορη και προβλέψιμη απόδοση όπως C και C++ (χωρίς " +"σκουπιδοσυλλέκτη)\n" +" καθώς και πρόσβαση σε υλικό χαμηλού επιπέδου (σε περίπτωση που το " +"χρειάζεστε)" + +#: src/why-rust/compile-time.md:1 +#, fuzzy +msgid "# Compile Time Guarantees" +msgstr "# Συγκεντρώστε Εγγυήσεις χρόνου" + +#: src/why-rust/compile-time.md:3 +#, fuzzy +msgid "Static memory management at compile time:" +msgstr "Διαχείριση στατικής μνήμης κατά το χρόνο μεταγλώττισης:" + +#: src/why-rust/compile-time.md:5 +#, fuzzy +msgid "" +"* No uninitialized variables.\n" +"* No memory leaks (_mostly_, see notes).\n" +"* No double-frees.\n" +"* No use-after-free.\n" +"* No `NULL` pointers.\n" +"* No forgotten locked mutexes.\n" +"* No data races between threads.\n" +"* No iterator invalidation." +msgstr "" +"* Δεν υπάρχουν μη αρχικοποιημένες μεταβλητές.\n" +"* Δεν υπάρχουν διαρροές μνήμης (_κυρίως_, βλέπε σημειώσεις).\n" +"* Χωρίς διπλό δωρεάν.\n" +"* Καμία χρήση-μετά-δωρεάν.\n" +"* Δεν υπάρχουν δείκτες «NULL».\n" +"* Όχι ξεχασμένα κλειδωμένα mutexes.\n" +"* Δεν υπάρχουν αγώνες δεδομένων μεταξύ των νημάτων.\n" +"* Χωρίς ακύρωση επαναληπτικού." + +#: src/why-rust/compile-time.md:16 +#, fuzzy +msgid "" +"It is possible to produce memory leaks in (safe) Rust. Some examples\n" +"are:" +msgstr "" +"Είναι δυνατό να προκληθούν διαρροές μνήμης στο (ασφαλές) Rust. Μερικά " +"παραδείγματα\n" +"είναι:" + +#: 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" +" 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" +"* You can also accidentally create a [reference cycle] with `Rc` or\n" +" `Arc`.\n" +"* In fact, some will consider infinitely populating a collection a memory\n" +" leak and Rust does not protect from those." +msgstr "" +"* Μπορείτε να χρησιμοποιήσετε το [`Box::leak`] για να διαρρεύσετε έναν " +"δείκτη. Μια χρήση αυτού θα μπορούσε\n" +" να λάβετε στατικές μεταβλητές με αρχικοποίηση χρόνου εκτέλεσης και " +"στατικές μεταβλητές μεγέθους χρόνου εκτέλεσης\n" +"* Μπορείτε να χρησιμοποιήσετε το [`std::mem::forget`] για να κάνετε τον " +"μεταγλωττιστή να \"ξεχάσει\"\n" +" μια τιμή (που σημαίνει ότι ο καταστροφέας δεν εκτελείται ποτέ).\n" +"* Μπορείτε επίσης να δημιουργήσετε κατά λάθος έναν [κύκλο αναφοράς] με " +"\"Rc\" ή\n" +" «Τόξο».\n" +"* Στην πραγματικότητα, ορισμένοι θα εξετάσουν το ενδεχόμενο να συμπληρώσουν " +"άπειρα μια συλλογή ως ανάμνηση\n" +" διαρροή και η Rust δεν προστατεύει από αυτά." + +#: 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 "" +"Για τους σκοπούς αυτού του μαθήματος, θα πρέπει να γίνει κατανοητό το \"No " +"memory leaks\".\n" +"ως \"Σχεδόν καμία *τυχαία* διαρροή μνήμης\"." + +#: src/why-rust/runtime.md:1 +#, fuzzy +msgid "# Runtime Guarantees" +msgstr "# Εγγυήσεις χρόνου εκτέλεσης" + +#: src/why-rust/runtime.md:3 +#, fuzzy +msgid "No undefined behavior at runtime:" +msgstr "Χωρίς απροσδιόριστη συμπεριφορά κατά το χρόνο εκτέλεσης:" + +#: src/why-rust/runtime.md:5 +#, fuzzy +msgid "" +"* Array access is bounds checked.\n" +"* Integer overflow is defined." +msgstr "" +"* Η πρόσβαση σε πίνακα έχει επιλεγεί τα όρια.\n" +"* Ορίζεται υπερχείλιση ακέραιου αριθμού." + +#: 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" +" semantics. By default, you get panics in debug mode (`cargo build`)\n" +" and wrap-around in release mode (`cargo build --release`).\n" +"\n" +"* Bounds checking cannot be disabled with a compiler flag. It can also\n" +" not be disabled directly with the `unsafe` keyword. However,\n" +" `unsafe` allows you to call functions such as `slice::get_unchecked`\n" +" which does not do bounds checking." +msgstr "" +"* Η υπερχείλιση ακέραιου αριθμού ορίζεται μέσω μιας επισήμανσης χρόνου " +"μεταγλώττισης. Οι επιλογές είναι\n" +" είτε ένας πανικός (ένα ελεγχόμενο crash του προγράμματος) είτε να " +"αναδιπλωθεί\n" +" σημασιολογία. Από προεπιλογή, λαμβάνετε πανικό στη λειτουργία εντοπισμού " +"σφαλμάτων (\"κατασκευή φορτίου\")\n" +" και περιτύλιξη σε λειτουργία απελευθέρωσης («κατασκευή φορτίου --" +"απελευθέρωση»)." + +#: src/why-rust/modern.md:1 +#, fuzzy +msgid "# Modern Features" +msgstr "# Σύγχρονα χαρακτηριστικά" + +#: src/why-rust/modern.md:3 +#, fuzzy +msgid "Rust is built with all the experience gained in the last 40 years." +msgstr "" +"Το Rust κατασκευάζεται με όλη την εμπειρία που αποκτήθηκε τα τελευταία 40 " +"χρόνια." + +#: src/why-rust/modern.md:5 +#, fuzzy +msgid "## Language Features" +msgstr "## Χαρακτηριστικά γλώσσας" + +#: src/why-rust/modern.md:7 +#, fuzzy +msgid "" +"* Enums and pattern matching.\n" +"* Generics.\n" +"* No overhead FFI.\n" +"* Zero-cost abstractions." +msgstr "" +"* Αριθμοί και αντιστοίχιση μοτίβων.\n" +"* Γενόσημα.\n" +"* Όχι γενικά FFI.\n" +"* Αφαιρέσεις μηδενικού κόστους." + +#: src/why-rust/modern.md:12 +#, fuzzy +msgid "## Tooling" +msgstr "## Εργαλεία" + +#: 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 "" +"* Μεγάλα λάθη μεταγλωττιστή.\n" +"* Ενσωματωμένος διαχειριστής εξαρτήσεων.\n" +"* Ενσωματωμένη υποστήριξη για δοκιμές.\n" +"* Εξαιρετική υποστήριξη πρωτοκόλλου διακομιστή γλώσσας." + +#: src/why-rust/modern.md:23 +msgid "" +"* Zero-cost abstractions, similar to C++, means that you don't have to " +"'pay'\n" +" for higher-level programming constructs with memory or CPU. For example,\n" +" writing a loop using `for` should result in roughly the same low level\n" +" instructions as using the `.iter().fold()` construct.\n" +"\n" +"* It may be worth mentioning that Rust enums are 'Algebraic Data Types', " +"also\n" +" known as 'sum types', which allow the type system to express things like\n" +" `Option` and `Result`.\n" +"\n" +"* Remind people to read the errors --- many developers have gotten used to\n" +" ignore lengthy compiler output. The Rust compiler is significantly more\n" +" talkative than other compilers. It will often provide you with " +"_actionable_\n" +" feedback, ready to copy-paste into your code.\n" +"\n" +"* The Rust standard library is small compared to languages like Java, " +"Python,\n" +" and Go. Rust does not come with several things you might consider standard " +"and\n" +" essential:\n" +"\n" +" * a random number generator, but see [rand].\n" +" * support for SSL or TLS, but see [rusttls].\n" +" * support for JSON, but see [serde_json].\n" +"\n" +" The reasoning behind this is that functionality in the standard library " +"cannot\n" +" go away, so it has to be very stable. For the examples above, the Rust\n" +" community is still working on finding the best solution --- and perhaps " +"there\n" +" isn't a single \"best solution\" for some of these things.\n" +"\n" +" Rust comes with a built-in package manager in the form of Cargo and this " +"makes\n" +" it trivial to download and compile third-party crates. A consequence of " +"this\n" +" is that the standard library can be smaller.\n" +"\n" +" Discovering good third-party crates can be a problem. Sites like\n" +" help with this by letting you compare health metrics " +"for\n" +" crates to find a good and trusted one.\n" +" \n" +"* [rust-analyzer] is a well supported LSP implementation used in major\n" +" IDEs and text editors." +msgstr "" + +#: src/basic-syntax.md:1 +#, fuzzy +msgid "# Basic Syntax" +msgstr "# Βασική Σύνταξη" + +#: src/basic-syntax.md:3 +#, fuzzy +msgid "Much of the Rust syntax will be familiar to you from C, C++ or Java:" +msgstr "Μεγάλο μέρος της σύνταξης Rust θα σας είναι οικείο από τη C ή τη C++:" + +#: 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" +" */`.\n" +"* Keywords like `if` and `while` work the same.\n" +"* Variable assignment is done with `=`, comparison is done with `==`." +msgstr "" +"* Τα μπλοκ και τα πεδία οριοθετούνται με σγουρά τιράντες.\n" +"* Τα σχόλια γραμμής ξεκινούν με `//`, τα σχόλια αποκλεισμού οριοθετούνται " +"από `/* ...\n" +" */`.\n" +"* Λέξεις-κλειδιά όπως «αν» και «ενώ» λειτουργούν το ίδιο.\n" +"* Η ανάθεση μεταβλητής γίνεται με `=`, η σύγκριση γίνεται με `==`." + +#: src/basic-syntax/scalar-types.md:1 +#, fuzzy +msgid "# Scalar Types" +msgstr "# Scalar Types" + +#: src/basic-syntax/scalar-types.md:3 +#, fuzzy +msgid "" +"| | Types | " +"Literals |\n" +"|------------------------|--------------------------------------------|-------------------------------|\n" +"| Signed integers | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | " +"`-10`, `0`, `1_000`, `123i64` |\n" +"| Unsigned integers | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, " +"`123`, `10u16` |\n" +"| Floating point numbers | `f32`, `f64` | " +"`3.14`, `-10.0e20`, `2f32` |\n" +"| Strings | `&str` | " +"`\"foo\"`, `r#\"\\\\\"#` |\n" +"| Unicode scalar values | `char` | " +"`'a'`, `'α'`, `'∞'` |\n" +"| Byte strings | `&[u8]` | " +"`b\"abc\"`, `br#\" \" \"#` |\n" +"| Booleans | `bool` | " +"`true`, `false` |" +msgstr "" +"| | Τύποι | Κυριολεκτικά |\n" +"|------------------------------------------------- " +"-------------------------------------------------- --|\n" +"| Υπογεγραμμένοι ακέραιοι αριθμοί | `i8`, `i16`, `i32`, `i64`, `i128`, " +"`isize` | `-10`, `0`, `1_000`, `123i64` |\n" +"| Ανυπόγραφοι ακέραιοι αριθμοί | «u8», «u16», «u32», «u64», «u128», «χρήση» " +"| `0`, `123`, `10u16` |\n" +"| Αριθμοί κινητής υποδιαστολής | `f32`, `f64` | `3,14`, `-10,0e20`, `2f32` " +"|\n" +"| Χορδές | `&str` | `\"foo\"`, `r#\"\\\\\"#` |\n" +"| Βαθμωτές τιμές Unicode | `χαρ` | `'a', `'α'`, `'∞'` |\n" +"| Συμβολοσειρές byte | `&[u8]` | `b\"abc\"`, `br#\" \" \"#\" |\n" +"| Booleans | «μπουλ» | \"αληθές\", \"ψευδές\" |" + +#: src/basic-syntax/scalar-types.md:13 +#, fuzzy +msgid "The types have widths as follows:" +msgstr "Οι τύποι έχουν πλάτη ως εξής:" + +#: src/basic-syntax/scalar-types.md:15 +#, fuzzy +msgid "" +"* `iN`, `uN`, and `fN` are _N_ bits wide,\n" +"* `isize` and `usize` are the width of a pointer,\n" +"* `char` is 32 bit wide,\n" +"* `bool` is 8 bit wide." +msgstr "" +"* Τα \"iN\", \"uN\" και \"fN\" έχουν πλάτος _N_ bit,\n" +"* Το \"isize\" και το \"usize\" είναι το πλάτος ενός δείκτη,\n" +"* Το \"char\" έχει πλάτος 32 bit,\n" +"* Το «bool» έχει πλάτος 8 bit." + +#: src/basic-syntax/compound-types.md:1 +#, fuzzy +msgid "# Compound Types" +msgstr "# Σύνθετοι τύποι" + +#: src/basic-syntax/compound-types.md:3 +msgid "" +"| | Types | Literals " +"|\n" +"|--------|-------------------------------|-----------------------------------|\n" +"| Arrays | `[T; N]` | `[20, 30, 40]`, `[0; 3]` " +"|\n" +"| Tuples | `()`, `(T,)`, `(T1, T2)`, ... | `()`, `('x',)`, `('x', 1.2)`, ... " +"|" +msgstr "" + +#: src/basic-syntax/compound-types.md:8 +#, fuzzy +msgid "Array assignment and access:" +msgstr "Εκχώρηση πίνακα και πρόσβαση:" + +#: src/basic-syntax/compound-types.md:10 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut a: [i8; 10] = [42; 10];\n" +" a[5] = 0;\n" +" println!(\"a: {:?}\", a);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/compound-types.md:18 +#, fuzzy +msgid "Tuple assignment and access:" +msgstr "Διπλή ανάθεση και πρόσβαση:" + +#: src/basic-syntax/compound-types.md:20 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let t: (i8, bool) = (7, true);\n" +" println!(\"1st index: {}\", t.0);\n" +" println!(\"2nd index: {}\", t.1);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/compound-types.md:32 +#, fuzzy +msgid "Arrays:" +msgstr "Πίνακες:" + +#: src/basic-syntax/compound-types.md:34 +msgid "" +"* Arrays have elements of the same type, `T`, and length, `N`, which is a " +"compile-time constant.\n" +" Note that the length of the array is *part of its type*, which means that " +"`[u8; 3]` and\n" +" `[u8; 4]` are considered two different types.\n" +"\n" +"* We can use literals to assign values to arrays.\n" +"\n" +"* In the main function, the print statement asks for the debug " +"implementation with the `?` format\n" +" parameter: `{}` gives the default output, `{:?}` gives the debug output. " +"We\n" +" could also have used `{a}` and `{a:?}` without specifying the value after " +"the\n" +" format string.\n" +"\n" +"* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can " +"be easier to read." +msgstr "" + +#: src/basic-syntax/compound-types.md:47 +#, fuzzy +msgid "Tuples:" +msgstr "Πλειάδες:" + +#: src/basic-syntax/compound-types.md:49 +#, fuzzy +msgid "" +"* Like arrays, tuples have a fixed length.\n" +"\n" +"* Tuples group together values of different types into a compound type.\n" +"\n" +"* Fields of a tuple can be accessed by the period and the index of the " +"value, e.g. `t.0`, `t.1`.\n" +"\n" +"* The empty tuple `()` is also known as the \"unit type\". It is both a " +"type, and\n" +" the only valid value of that type - that is to say both the type and its " +"value\n" +" are expressed as `()`. It is used to indicate, for example, that a " +"function or\n" +" expression has no return value, as we'll see in a future slide. \n" +" * You can think of it as `void` that can be familiar to you from other \n" +" programming languages." +msgstr "" +"* Η άδεια πλειάδα `()` είναι επίσης γνωστή ως \"τύπος μονάδας\". Είναι και " +"τύπος, και\n" +" η μόνη έγκυρη τιμή αυτού του τύπου - δηλαδή και ο τύπος και η τιμή του\n" +" εκφράζονται ως «()». Χρησιμοποιείται για να υποδείξει, για παράδειγμα, ότι " +"μια συνάρτηση ή\n" +" Η έκφραση δεν έχει τιμή επιστροφής, όπως θα δούμε σε μια μελλοντική " +"διαφάνεια.\n" +" * Μπορείτε να το σκεφτείτε ως «κενό» που μπορεί να σας είναι οικείο από " +"άλλους\n" +" γλώσσες προγραμματισμού." + +#: src/basic-syntax/references.md:1 +#, fuzzy +msgid "# References" +msgstr "# Βιβλιογραφικές αναφορές" + +#: src/basic-syntax/references.md:3 +#, fuzzy +msgid "Like C++, Rust has references:" +msgstr "Όπως η C++, το Rust έχει αναφορές:" + +#: src/basic-syntax/references.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x: i32 = 10;\n" +" let ref_x: &mut i32 = &mut x;\n" +" *ref_x = 20;\n" +" println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/references.md:14 +#, fuzzy +msgid "Some notes:" +msgstr "Μερικές σημειώσεις:" + +#: 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 "" +"* Πρέπει να μην αναφέρουμε το «ref_x» κατά την ανάθεση σε αυτό, παρόμοια με " +"τους δείκτες C και C++.\n" +"* Το Rust θα επαναφέρει αυτόματα σε ορισμένες περιπτώσεις, ιδιαίτερα κατά " +"την επίκληση\n" +" μεθόδους (δοκιμάστε το `ref_x.count_ones()`).\n" +"* Οι αναφορές που δηλώνονται ως «mut» μπορούν να δεσμευτούν σε διαφορετικές " +"τιμές κατά τη διάρκεια της ζωής τους." + +#: src/basic-syntax/references.md:21 +#, fuzzy +msgid "" +"
\n" +"Key points:" +msgstr "" +"<λεπτομέρειες>\n" +"Βασικά σημεία:" + +#: src/basic-syntax/references.md:24 +#, fuzzy +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 "" +"* Φροντίστε να σημειώσετε τη διαφορά μεταξύ του \"let mut ref_x: &i32\" και " +"του \"let ref_x:\n" +" &mut i32`. Η πρώτη αντιπροσωπεύει μια μεταβλητή αναφορά στην οποία μπορεί " +"να συνδεθεί\n" +" διαφορετικές τιμές, ενώ η δεύτερη αντιπροσωπεύει μια αναφορά σε μια " +"μεταβλητή τιμή." + +#: src/basic-syntax/references-dangling.md:1 +#, fuzzy +msgid "# Dangling References" +msgstr "# Κρεμασμένες αναφορές" + +#: src/basic-syntax/references-dangling.md:3 +#, fuzzy +msgid "Rust will statically forbid dangling references:" +msgstr "Η σκουριά θα απαγορεύσει στατικά τις κρέμονται αναφορές:" + +#: src/basic-syntax/references-dangling.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let ref_x: &i32;\n" +" {\n" +" let x: i32 = 10;\n" +" ref_x = &x;\n" +" }\n" +" println!(\"ref_x: {ref_x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/references-dangling.md:16 +#, 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 "" +"* Μια αναφορά λέγεται ότι \"δανείζεται\" την τιμή στην οποία αναφέρεται.\n" +"* Το Rust παρακολουθεί τη διάρκεια ζωής όλων των αναφορών για να διασφαλίσει " +"ότι ζουν πολύ\n" +" αρκετά.\n" +"* Θα μιλήσουμε περισσότερο για δανεισμό όταν φτάσουμε στην ιδιοκτησία." + +#: src/basic-syntax/slices.md:1 +#, fuzzy +msgid "# Slices" +msgstr "# Φέτες" + +#: src/basic-syntax/slices.md:3 +#, fuzzy +msgid "A slice gives you a view into a larger collection:" +msgstr "Μια φέτα σάς δίνει μια προβολή σε μια μεγαλύτερη συλλογή:" + +#: src/basic-syntax/slices.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" +" println!(\"a: {a:?}\");\n" +"\n" +" let s: &[i32] = &a[2..4];\n" +" println!(\"s: {s:?}\");\n" +"}\n" +"```" +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 "" +"* Οι φέτες δανείζονται δεδομένα από τον τύπο σε φέτες.\n" +"* Ερώτηση: Τι θα συμβεί αν τροποποιήσετε το «a[3]»;" + +#: 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" +"* If the slice starts at index 0, Rust’s range syntax allows us to drop the " +"starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are " +"identical.\n" +" \n" +"* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are " +"identical.\n" +"\n" +"* To easily create a slice of the full array, we can therefore use " +"`&a[..]`.\n" +"\n" +"* `s` is a reference to a slice of `i32`s. Notice that the type of `s` " +"(`&[i32]`) no longer mentions the array length. This allows us to perform " +"computation on slices of different sizes.\n" +" \n" +"* Slices always borrow from another object. In this example, `a` has to " +"remain 'alive' (in scope) for at least as long as our slice. \n" +" \n" +"* The question about modifying `a[3]` can spark an interesting discussion, " +"but the answer is that for memory safety reasons\n" +" you cannot do it through `a` after you created a slice, but you can read " +"the data from both `a` and `s` safely. \n" +" More details will be explained in the borrow checker section." +msgstr "" +"* Το `s` είναι μια αναφορά σε ένα κομμάτι του `i32`. Παρατηρήστε ότι ο τύπος " +"`s` (`&[i32]`) δεν αναφέρει πλέον το μήκος του πίνακα. Αυτό μας επιτρέπει να " +"κάνουμε υπολογισμούς σε φέτες διαφορετικών μεγεθών.\n" +" \n" +"* Οι φέτες δανείζονται πάντα από άλλο αντικείμενο. Σε αυτό το παράδειγμα, το " +"«a» πρέπει να παραμείνει «ζωντανό» (στο πεδίο εφαρμογής) για τουλάχιστον όσο " +"το κομμάτι μας.\n" +" \n" +"* Η ερώτηση σχετικά με την τροποποίηση του «a[3]» μπορεί να προκαλέσει μια " +"ενδιαφέρουσα συζήτηση, αλλά η απάντηση είναι ότι για λόγους ασφαλείας της " +"μνήμης\n" +" δεν μπορείτε να το κάνετε μέσω του \"a\" αφού δημιουργήσετε ένα slice, " +"αλλά μπορείτε να διαβάσετε τα δεδομένα από το \"a\" και το \"s\" με " +"ασφάλεια.\n" +" Περισσότερες λεπτομέρειες θα επεξηγηθούν στην ενότητα ελέγχου δανεισμού." + +#: src/basic-syntax/string-slices.md:1 +#, fuzzy +msgid "# `String` vs `str`" +msgstr "# `String` vs `str`" + +#: src/basic-syntax/string-slices.md:3 +#, fuzzy +msgid "We can now understand the two string types in Rust:" +msgstr "Μπορούμε τώρα να κατανοήσουμε τους δύο τύπους χορδών στο Rust:" + +#: src/basic-syntax/string-slices.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: &str = \"World\";\n" +" println!(\"s1: {s1}\");\n" +"\n" +" let mut s2: String = String::from(\"Hello \");\n" +" println!(\"s2: {s2}\");\n" +" s2.push_str(s1);\n" +" println!(\"s2: {s2}\");\n" +" \n" +" let s3: &str = &s2[6..];\n" +" println!(\"s3: {s3}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/string-slices.md:20 +#, fuzzy +msgid "Rust terminology:" +msgstr "Ορολογία σκουριάς:" + +#: src/basic-syntax/string-slices.md:22 +#, fuzzy +msgid "" +"* `&str` an immutable reference to a string slice.\n" +"* `String` a mutable string buffer." +msgstr "" +"* «&str» μια αμετάβλητη αναφορά σε ένα κομμάτι συμβολοσειράς.\n" +"* \"String\" ένα μεταβλητό buffer συμβολοσειρών." + +#: src/basic-syntax/string-slices.md:27 +#, fuzzy +msgid "" +"* `&str` introduces a string slice, which is an immutable reference to UTF-8 " +"encoded string data \n" +" stored in a block of memory. String literals (`”Hello”`), are stored in " +"the program’s binary.\n" +"\n" +"* Rust’s `String` type is a wrapper around a vector of bytes. As with a " +"`Vec`, it is owned.\n" +" \n" +"* As with many other types `String::from()` creates a string from a string " +"literal; `String::new()` \n" +" creates a new empty string, to which string data can be added using the " +"`push()` and `push_str()` methods.\n" +"\n" +"* The `format!()` macro is a convenient way to generate an owned string from " +"dynamic values. It \n" +" accepts the same format specification as `println!()`.\n" +" \n" +"* You can borrow `&str` slices from `String` via `&` and optionally range " +"selection.\n" +" \n" +"* For C++ programmers: think of `&str` as `const char*` from C++, but the " +"one that always points \n" +" to a valid string in memory. Rust `String` is a rough equivalent of `std::" +"string` from C++ \n" +" (main difference: it can only contain UTF-8 encoded bytes and will never " +"use a small-string optimization).\n" +" " +msgstr "" +"* Η μακροεντολή «format!()» είναι ένας βολικός τρόπος για να δημιουργήσετε " +"μια ιδιόκτητη συμβολοσειρά από δυναμικές τιμές. Το\n" +" δέχεται την ίδια προδιαγραφή μορφής με το \"println!()\".\n" +" \n" +"* Μπορείτε να δανειστείτε κομμάτια «&str» από το «String» μέσω του «&» και " +"προαιρετικά επιλογής εύρους.\n" +" \n" +"* Για προγραμματιστές C++: σκεφτείτε το «&str» ως «const char*» από τη C++, " +"αλλά αυτό που δείχνει πάντα\n" +" σε μια έγκυρη συμβολοσειρά στη μνήμη. Το Rust «String» είναι ένα κατά " +"προσέγγιση ισοδύναμο του «std::string» από τη C++\n" +" (κύρια διαφορά: μπορεί να περιέχει μόνο byte με κωδικοποίηση UTF-8 και δεν " +"θα χρησιμοποιήσει ποτέ βελτιστοποίηση μικρής συμβολοσειράς).\n" +" \n" +"
" + +#: src/basic-syntax/functions.md:1 +#, fuzzy +msgid "# Functions" +msgstr "# Λειτουργίες" + +#: src/basic-syntax/functions.md:3 +#, fuzzy +msgid "" +"A Rust version of the famous [FizzBuzz](https://en.wikipedia.org/wiki/" +"Fizz_buzz) interview question:" +msgstr "" +"Μια έκδοση Rust της περίφημης ερώτησης συνέντευξης [FizzBuzz](https://en." +"wikipedia.org/wiki/Fizz_buzz):" + +#: src/basic-syntax/functions.md:5 +#, 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) -> () { // Χωρίς επιστροφή τιμής σημαίνει επιστροφή του " +"τύπου μονάδας `()`\n" +" αντιστοίχιση (is_divisible_by(n, 3), is_divisible_by(n, 5)) {\n" +" (αληθινό, αληθινό) => println!(\"fizzbuzz\"),\n" +" (αληθές, λάθος) => println!(\"fizz\"),\n" +" (ψευδές, αληθές) => println!(\"buzz\"),\n" +" (ψεύτικο, ψευδές) => println!(\"{n}\"),\n" +" }\n" +"}" + +#: src/basic-syntax/functions.md:35 +msgid "" +"* We refer in `main` to a function written below. Neither forward " +"declarations nor headers are necessary. \n" +"* Declaration parameters are followed by a type (the reverse of some " +"programming languages), then a return type.\n" +"* The last expression in a function body (or any block) becomes the return " +"value. Simply omit the `;` 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" +" " +msgstr "" + +#: src/basic-syntax/rustdoc.md:1 +#, fuzzy +msgid "# Rustdoc" +msgstr "# Γιατί Rust;" + +#: src/basic-syntax/rustdoc.md:3 +msgid "" +"All language items in Rust can be documented using special `///` syntax." +msgstr "" + +#: src/basic-syntax/rustdoc.md:5 +msgid "" +"```rust,editable\n" +"/// Determine whether the first argument is divisible by the second " +"argument.\n" +"///\n" +"/// If the second argument is zero, the result is false.\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" +"```" +msgstr "" + +#: src/basic-syntax/rustdoc.md:17 +msgid "" +"The contents are treated as Markdown. All published Rust library crates are\n" +"automatically documented at [`docs.rs`](https://docs.rs) using the\n" +"[rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It " +"is\n" +"idiomatic to document all public items in an API using this pattern." +msgstr "" + +#: src/basic-syntax/rustdoc.md:24 +msgid "" +"* Show students the generated docs for the `rand` crate at\n" +" [`docs.rs/rand`](https://docs.rs/rand).\n" +"\n" +"* This course does not include rustdoc on slides, just to save space, but " +"in\n" +" real code they should be present.\n" +"\n" +"* Inner doc comments are discussed later (in the page on modules) and need " +"not\n" +" be addressed here." +msgstr "" + +#: src/basic-syntax/methods.md:1 src/methods.md:1 +#, fuzzy +msgid "# Methods" +msgstr "# Μέθοδοι" + +#: 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:" +msgstr "" +"Το Rust έχει μεθόδους, είναι απλώς λειτουργίες που σχετίζονται με έναν " +"συγκεκριμένο τύπο. ο\n" +"Το πρώτο όρισμα μιας μεθόδου είναι ένα παράδειγμα του τύπου με το οποίο " +"σχετίζεται:" + +#: src/basic-syntax/methods.md:6 +msgid "" +"```rust,editable\n" +"struct Rectangle {\n" +" width: u32,\n" +" height: u32,\n" +"}\n" +"\n" +"impl Rectangle {\n" +" fn area(&self) -> u32 {\n" +" self.width * self.height\n" +" }\n" +"\n" +" fn inc_width(&mut self, delta: u32) {\n" +" self.width += delta;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut rect = Rectangle { width: 10, height: 5 };\n" +" println!(\"old area: {}\", rect.area());\n" +" rect.inc_width(5);\n" +" println!(\"new area: {}\", rect.area());\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/methods.md:30 +#, fuzzy +msgid "" +"* We will look much more at methods in today's exercise and in tomorrow's " +"class." +msgstr "" +"* Θα εξετάσουμε πολύ περισσότερο τις μεθόδους στη σημερινή άσκηση και στην " +"αυριανή τάξη." + +#: src/basic-syntax/functions-interlude.md:1 +#, fuzzy +msgid "# Function Overloading" +msgstr "# Λειτουργία Υπερφόρτωση" + +#: src/basic-syntax/functions-interlude.md:3 +#, fuzzy +msgid "Overloading is not supported:" +msgstr "Η υπερφόρτωση δεν υποστηρίζεται:" + +#: src/basic-syntax/functions-interlude.md:5 +#, fuzzy +msgid "" +"* Each function has a single implementation:\n" +" * Always takes a fixed number of parameters.\n" +" * Always takes a single set of parameter types.\n" +"* Default values are not supported:\n" +" * All call sites have the same number of arguments.\n" +" * Macros are sometimes used as an alternative." +msgstr "" +"* Κάθε συνάρτηση έχει μια ενιαία υλοποίηση:\n" +" * Λαμβάνει πάντα έναν σταθερό αριθμό παραμέτρων.\n" +" * Λαμβάνει πάντα ένα ενιαίο σύνολο τύπων παραμέτρων.\n" +"* Οι προεπιλεγμένες τιμές δεν υποστηρίζονται:\n" +" * Όλοι οι ιστότοποι κλήσεων έχουν τον ίδιο αριθμό ορισμάτων.\n" +" * Οι μακροεντολές χρησιμοποιούνται μερικές φορές ως εναλλακτική λύση." + +#: src/basic-syntax/functions-interlude.md:12 +#, fuzzy +msgid "However, function parameters can be generic:" +msgstr "Ωστόσο, οι παράμετροι συνάρτησης μπορεί να είναι γενικές:" + +#: src/basic-syntax/functions-interlude.md:14 +msgid "" +"```rust,editable\n" +"fn pick_one(a: T, b: T) -> T {\n" +" if std::process::id() % 2 == 0 { a } else { b }\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"coin toss: {}\", pick_one(\"heads\", \"tails\"));\n" +" println!(\"cash prize: {}\", pick_one(500, 1000));\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/functions-interlude.md:27 +#, fuzzy +msgid "" +"* When using generics, the standard library's `Into` can provide a kind " +"of limited\n" +" polymorphism on argument types. We will see more details in a later " +"section." +msgstr "" +"* Όταν χρησιμοποιείτε γενικά, το 'Into' της τυπικής βιβλιοθήκης μπορεί να " +"παρέχει ένα είδος περιορισμένου\n" +" πολυμορφισμός σε τύπους επιχειρημάτων. Θα δούμε περισσότερες λεπτομέρειες " +"σε επόμενη ενότητα." + +#: src/basic-syntax/functions-interlude.md:30 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/day-1/morning.md:1 +#, fuzzy +msgid "# Day 1: Morning Exercises" +msgstr "# Ημέρα 1: Πρωινές ασκήσεις" + +#: src/exercises/day-1/morning.md:3 +#, fuzzy +msgid "In these exercises, we will explore two parts of Rust:" +msgstr "Σε αυτές τις ασκήσεις, θα εξερευνήσουμε δύο μέρη του Rust:" + +#: src/exercises/day-1/morning.md:5 +#, fuzzy +msgid "" +"* Implicit conversions between types.\n" +"\n" +"* Arrays and `for` loops." +msgstr "* Σιωπηρές μετατροπές μεταξύ τύπων." + +#: src/exercises/day-1/morning.md:11 +#, fuzzy +msgid "A few things to consider while solving the exercises:" +msgstr "" +"Μερικά πράγματα που πρέπει να λάβετε υπόψη κατά την επίλυση των ασκήσεων:" + +#: src/exercises/day-1/morning.md:13 +#, fuzzy +msgid "" +"* Use a local Rust installation, if possible. This way you can get\n" +" auto-completion in your editor. See the page about [Using Cargo] for " +"details\n" +" on installing Rust.\n" +"\n" +"* Alternatively, use the Rust Playground." +msgstr "" +"* Χρησιμοποιήστε μια τοπική εγκατάσταση Rust, εάν είναι δυνατόν. Με αυτόν " +"τον τρόπο μπορείτε να αποκτήσετε\n" +" αυτόματη συμπλήρωση στον επεξεργαστή σας. Δείτε τη σελίδα σχετικά με το " +"[Using Cargo] για λεπτομέρειες\n" +" κατά την εγκατάσταση του Rust." + +#: src/exercises/day-1/morning.md:19 +#, fuzzy +msgid "" +"The code snippets are not editable on purpose: the inline code snippets " +"lose\n" +"their state if you navigate away from the page." +msgstr "" +"Τα αποσπάσματα κώδικα δεν είναι επεξεργάσιμα επίτηδες: τα ενσωματωμένα " +"αποσπάσματα κώδικα χάνονται\n" +"την κατάστασή τους εάν απομακρυνθείτε από τη σελίδα." + +#: 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 +#, fuzzy +msgid "" +"After looking at the exercises, you can look at the [solutions] provided." +msgstr "" +"Αφού δείτε τις ασκήσεις, μπορείτε να δείτε τις [λύσεις] που παρέχονται." + +#: src/exercises/day-1/implicit-conversions.md:1 +#, fuzzy +msgid "# Implicit Conversions" +msgstr "# Άμεσες μετατροπές" + +#: src/exercises/day-1/implicit-conversions.md:3 +#, fuzzy +msgid "" +"Rust will not automatically apply _implicit conversions_ between types " +"([unlike\n" +"C++][3]). You can see this in a program like this:" +msgstr "" +"Το Rust δεν θα εφαρμόσει αυτόματα _implicit conversions_ μεταξύ των τύπων " +"([σε αντίθεση με\n" +"C++][3]). Μπορείτε να το δείτε σε ένα πρόγραμμα όπως αυτό:" + +#: src/exercises/day-1/implicit-conversions.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"fn multiply(x: i16, y: i16) -> i16 {\n" +" x * y\n" +"}\n" +"\n" +"fn main() {\n" +" let x: i8 = 15;\n" +" let y: i16 = 1000;\n" +"\n" +" println!(\"{x} * {y} = {}\", multiply(x, y));\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/implicit-conversions.md:19 +#, fuzzy +msgid "" +"The Rust integer types all implement the [`From`][1] and [`Into`][2]\n" +"traits to let us convert between them. The `From` trait has a single " +"`from()`\n" +"method and similarly, the `Into` trait has a single `into()` method.\n" +"Implementing these traits is how a type expresses that it can be converted " +"into\n" +"another type." +msgstr "" +"Όλοι οι τύποι ακέραιου αριθμού Rust εφαρμόζουν τα [`From`][1] και " +"[`Into`][2]\n" +"χαρακτηριστικά για να μας αφήσουν να μετατρέψουμε μεταξύ τους. Το " +"χαρακτηριστικό \"From\" έχει ένα μόνο \"from()\".\n" +"μέθοδο και παρομοίως, το χαρακτηριστικό «Into» έχει μία μόνο μέθοδο " +"«into()».\n" +"Η εφαρμογή αυτών των χαρακτηριστικών είναι ο τρόπος με τον οποίο ένας τύπος " +"εκφράζει ότι μπορεί να μετατραπεί σε\n" +"άλλου τύπου." + +#: src/exercises/day-1/implicit-conversions.md:25 +#, fuzzy +msgid "" +"The standard library has an implementation of `From for i16`, which " +"means\n" +"that we can convert a variable `x` of type `i8` to an `i16` by calling \n" +"`i16::from(x)`. Or, simpler, with `x.into()`, because `From for i16`\n" +"implementation automatically create an implementation of `Into for i8`." +msgstr "" +"Η τυπική βιβλιοθήκη έχει μια υλοποίηση του «From για i16», που σημαίνει\n" +"ότι μπορούμε να μετατρέψουμε μια μεταβλητή «x» τύπου «i8» σε «i16» καλώντας\n" +"`i16::from(x)`. Ή, απλούστερα, με `x.into()`, επειδή `From για i16`\n" +"υλοποίηση δημιουργεί αυτόματα μια υλοποίηση του «Into για i8»." + +#: src/exercises/day-1/implicit-conversions.md:30 +#, fuzzy +msgid "" +"The same applies for your own `From` implementations for your own types, so " +"it is\n" +"sufficient to only implement `From` to get a respective `Into` " +"implementation automatically." +msgstr "" +"Το ίδιο ισχύει και για τις δικές σας υλοποιήσεις «Από» για τους δικούς σας " +"τύπους, έτσι είναι\n" +"αρκεί για να εφαρμοστεί μόνο το \"From\" για να ληφθεί αυτόματα μια " +"αντίστοιχη υλοποίηση \"Into\"." + +#: src/exercises/day-1/implicit-conversions.md:33 +#, fuzzy +msgid "" +"1. Execute the above program and look at the compiler error.\n" +"\n" +"2. Update the code above to use `into()` to do the conversion.\n" +"\n" +"3. Change the types of `x` and `y` to other things (such as `f32`, `bool`,\n" +" `i128`) to see which types you can convert to which other types. Try\n" +" converting small types to big types and the other way around. Check the\n" +" [standard library documentation][1] to see if `From` is implemented " +"for\n" +" the pairs you check." +msgstr "" +"3. Αλλάξτε τους τύπους \"x\" και \"y\" σε άλλα πράγματα (όπως \"f32\", " +"\"bool\",\n" +" `i128`) για να δείτε ποιους τύπους μπορείτε να μετατρέψετε σε ποιους " +"άλλους τύπους. Δοκιμάστε\n" +" μετατροπή μικρών τύπων σε μεγάλους τύπους και το αντίστροφο. Ελεγξε το\n" +" [τυπική τεκμηρίωση βιβλιοθήκης][1] για να δείτε εάν το \"From\" έχει " +"εφαρμοστεί για\n" +" τα ζευγάρια που ελέγχετε." + +#: src/exercises/day-1/for-loops.md:1 +#, fuzzy +msgid "# Arrays and `for` Loops" +msgstr "# Πίνακες και βρόχοι «για»." + +#: src/exercises/day-1/for-loops.md:3 +#, fuzzy +msgid "We saw that an array can be declared like this:" +msgstr "Είδαμε ότι ένας πίνακας μπορεί να δηλωθεί ως εξής:" + +#: src/exercises/day-1/for-loops.md:5 +msgid "" +"```rust\n" +"let array = [10, 20, 30];\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:9 +#, fuzzy +msgid "" +"You can print such an array by asking for its debug representation with `{:?}" +"`:" +msgstr "" +"Μπορείτε να εκτυπώσετε έναν τέτοιο πίνακα ζητώντας την αναπαράστασή του για " +"τον εντοπισμό σφαλμάτων με \"{:?}\":" + +#: src/exercises/day-1/for-loops.md:11 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" println!(\"array: {array:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:18 +#, fuzzy +msgid "" +"Rust lets you iterate over things like arrays and ranges using the `for`\n" +"keyword:" +msgstr "" +"Το Rust σάς επιτρέπει να επαναλαμβάνετε πράγματα όπως πίνακες και εύρη " +"χρησιμοποιώντας το \"για\".\n" +"λέξη-κλειδί:" + +#: src/exercises/day-1/for-loops.md:21 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" print!(\"Iterating over array:\");\n" +" for n in array {\n" +" print!(\" {n}\");\n" +" }\n" +" println!();\n" +"\n" +" print!(\"Iterating over range:\");\n" +" for i in 0..3 {\n" +" print!(\" {}\", array[i]);\n" +" }\n" +" println!();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:38 +#, fuzzy +msgid "" +"Use the above to write a function `pretty_print` which pretty-print a matrix " +"and\n" +"a function `transpose` which will transpose a matrix (turn rows into " +"columns):" +msgstr "" +"Χρησιμοποιήστε τα παραπάνω για να γράψετε μια συνάρτηση «pretty_print» που " +"εκτυπώνει όμορφα έναν πίνακα και\n" +"μια συνάρτηση \"transpose\" που θα μεταφέρει έναν πίνακα (μετατρέπει τις " +"γραμμές σε στήλες):" + +#: src/exercises/day-1/for-loops.md:41 +msgid "" +"```bob\n" +" ⎛⎡1 2 3⎤⎞ ⎡1 4 7⎤\n" +"\"transpose\"⎜⎢4 5 6⎥⎟ \"==\"⎢2 5 8⎥\n" +" ⎝⎣7 8 9⎦⎠ ⎣3 6 9⎦\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:47 +#, fuzzy +msgid "Hard-code both functions to operate on 3 × 3 matrices." +msgstr "" +"Σκληρός κώδικας και των δύο συναρτήσεων για λειτουργία σε πίνακες 3 × 3." + +#: src/exercises/day-1/for-loops.md:49 +#, fuzzy +msgid "" +"Copy the code below to and implement the\n" +"functions:" +msgstr "" +"Αντιγράψτε τον παρακάτω κώδικα στο και " +"εφαρμόστε το\n" +"λειτουργίες:" + +#: src/exercises/day-1/for-loops.md:52 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" unimplemented!()\n" +"}\n" +"\n" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" unimplemented!()\n" +"}\n" +"\n" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:80 +#, fuzzy +msgid "## Bonus Question" +msgstr "## Ερώτηση μπόνους" + +#: src/exercises/day-1/for-loops.md:82 +#, fuzzy +msgid "" +"Could you use `&[i32]` slices instead of hard-coded 3 × 3 matrices for your\n" +"argument and return types? Something like `&[&[i32]]` for a two-dimensional\n" +"slice-of-slices. Why or why not?" +msgstr "" +"Θα μπορούσατε να χρησιμοποιήσετε φέτες \"&[i32]\" αντί για σκληρούς " +"κωδικοποιημένους πίνακες 3 × 3 για\n" +"όρισμα και τύποι επιστροφής; Κάτι σαν \"&[&[i32]]\" για ένα δισδιάστατο\n" +"φέτα φέτες. Γιατί ή γιατί όχι?" + +#: src/exercises/day-1/for-loops.md:87 +#, fuzzy +msgid "" +"See the [`ndarray` crate](https://docs.rs/ndarray/) for a production " +"quality\n" +"implementation." +msgstr "" +"Δείτε το [`ndarray` crate](https://docs.rs/ndarray/) για ποιότητα παραγωγής\n" +"εκτέλεση." + +#: src/exercises/day-1/for-loops.md:92 +#, fuzzy +msgid "" +"The solution and the answer to the bonus section are available in the \n" +"[Solution](solutions-morning.md#arrays-and-for-loops) section." +msgstr "" +"Η λύση και η απάντηση στην ενότητα μπόνους είναι διαθέσιμες στο\n" +"Ενότητα [Λύση](solutions-morning.md#arrays-and-for-loops)." + +#: src/basic-syntax/variables.md:1 +#, fuzzy +msgid "# Variables" +msgstr "# Μεταβλητές" + +#: src/basic-syntax/variables.md:3 +#, fuzzy +msgid "" +"Rust provides type safety via static typing. Variable bindings are immutable " +"by\n" +"default:" +msgstr "" +"Το Rust παρέχει ασφάλεια τύπου μέσω στατικής πληκτρολόγησης. Οι δεσμεύσεις " +"μεταβλητών είναι αμετάβλητες κατά\n" +"Προκαθορισμένο:" + +#: src/basic-syntax/variables.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x: i32 = 10;\n" +" println!(\"x: {x}\");\n" +" // x = 20;\n" +" // println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/variables.md:17 +#, fuzzy +msgid "" +"* Due to type inference the `i32` is optional. We will gradually show the " +"types less and less as the course progresses.\n" +"* Note that since `println!` is a macro, `x` is not moved, even using the " +"function like syntax of `println!(\"x: {}\", x)`" +msgstr "" +"* Λόγω συμπερασμάτων τύπου, το «i32» είναι προαιρετικό. Σταδιακά θα " +"δείχνουμε τους τύπους όλο και λιγότερο όσο προχωρά ο τύπος.\n" +"* Σημειώστε ότι επειδή το \"println!\" είναι μακροεντολή, το \"x\" δεν " +"μετακινείται, ακόμη και χρησιμοποιώντας τη συνάρτηση όπως η σύνταξη του " +"\"println!(\"x: {}\", x)\"" + +#: src/basic-syntax/type-inference.md:1 +#, fuzzy +msgid "# Type Inference" +msgstr "# Τύπος Συμπερασματικά" + +#: src/basic-syntax/type-inference.md:3 +#, fuzzy +msgid "Rust will look at how the variable is _used_ to determine the type:" +msgstr "" +"Το Rust θα εξετάσει πώς χρησιμοποιείται η μεταβλητή για να προσδιορίσει τον " +"τύπο:" + +#: src/basic-syntax/type-inference.md:5 +msgid "" +"```rust,editable\n" +"fn takes_u32(x: u32) {\n" +" println!(\"u32: {x}\");\n" +"}\n" +"\n" +"fn takes_i8(y: i8) {\n" +" println!(\"i8: {y}\");\n" +"}\n" +"\n" +"fn main() {\n" +" let x = 10;\n" +" let y = 20;\n" +"\n" +" takes_u32(x);\n" +" takes_i8(y);\n" +" // takes_u32(y);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/type-inference.md:26 +msgid "" +"This slide demonstrates how the Rust compiler infers types based on " +"constraints given by variable declarations and usages." +msgstr "" + +#: src/basic-syntax/type-inference.md:28 +#, fuzzy +msgid "" +"It is very important to emphasize that variables declared like this are not " +"of some sort of dynamic \"any type\" that can\n" +"hold any data. The machine code generated by such declaration is identical " +"to the explicit declaration of a type.\n" +"The compiler does the job for us and helps us write more concise code." +msgstr "" +"Αυτή η διαφάνεια δείχνει πώς ο μεταγλωττιστής Rust συμπεραίνει τύπους με " +"βάση περιορισμούς που δίνονται από δηλώσεις και χρήσεις μεταβλητών.\n" +" \n" +"Είναι πολύ σημαντικό να τονίσουμε ότι οι μεταβλητές που δηλώνονται όπως αυτή " +"δεν είναι κάποιου είδους δυναμικού \"οποιουδήποτε τύπου\" που μπορεί\n" +"κρατήστε τυχόν δεδομένα. Ο κωδικός μηχανής που δημιουργείται από μια τέτοια " +"δήλωση είναι πανομοιότυπος με τη ρητή δήλωση ενός τύπου.\n" +"Ο μεταγλωττιστής κάνει τη δουλειά για εμάς και μας βοηθά να γράψουμε έναν " +"πιο συνοπτικό κώδικα." + +#: src/basic-syntax/type-inference.md:32 +#, fuzzy +msgid "" +"The following code tells the compiler to copy into a certain generic " +"container without the code ever explicitly specifying the contained type, " +"using `_` as a placeholder:" +msgstr "" +"Ο ακόλουθος κώδικας λέει στον μεταγλωττιστή να αντιγράψει σε ένα " +"συγκεκριμένο γενικό κοντέινερ χωρίς ποτέ ο κώδικας να προσδιορίζει ρητά τον " +"τύπο που περιέχεται, χρησιμοποιώντας το «_» ως σύμβολο κράτησης θέσης:" + +#: src/basic-syntax/type-inference.md:34 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut v = Vec::new();\n" +" v.push((10, false));\n" +" v.push((20, true));\n" +" println!(\"v: {v:?}\");\n" +"\n" +" let vv = v.iter().collect::>();\n" +" println!(\"vv: {vv:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/type-inference.md:46 +#, fuzzy +msgid "" +"[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator." +"html#method.collect) relies on `FromIterator`, which [`HashSet`](https://doc." +"rust-lang.org/std/iter/trait.FromIterator.html) implements." +msgstr "" +"Το [`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator." +"html#method.collect) βασίζεται στο `FromIterator`, το οποίο [`HashSet`]" +"(https:/ /doc.rust-lang.org/std/iter/trait.FromIterator.html) υλοποιεί." + +#: src/basic-syntax/static-and-const.md:1 +#, fuzzy +msgid "# Static and Constant Variables" +msgstr "# Στατικές και σταθερές μεταβλητές" + +#: src/basic-syntax/static-and-const.md:3 +#, fuzzy +msgid "Global state is managed with static and constant variables." +msgstr "" +"Η διαχείριση της παγκόσμιας κατάστασης γίνεται με στατικές και σταθερές " +"μεταβλητές." + +#: src/basic-syntax/static-and-const.md:5 +#, fuzzy +msgid "## `const`" +msgstr "## «const»." + +#: src/basic-syntax/static-and-const.md:7 +#, fuzzy +msgid "You can declare compile-time constants:" +msgstr "Μπορείτε να δηλώσετε σταθερές χρόνου μεταγλώττισης:" + +#: src/basic-syntax/static-and-const.md:9 +msgid "" +"```rust,editable\n" +"const DIGEST_SIZE: usize = 3;\n" +"const ZERO: Option = Some(42);\n" +"\n" +"fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {\n" +" let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];\n" +" for (idx, &b) in text.as_bytes().iter().enumerate() {\n" +" digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE]." +"wrapping_add(b);\n" +" }\n" +" digest\n" +"}\n" +"\n" +"fn main() {\n" +" let digest = compute_digest(\"Hello\");\n" +" println!(\"Digest: {digest:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/static-and-const.md:27 +#, fuzzy +msgid "According the the [Rust RFC Book][1] these are inlined upon use." +msgstr "Σύμφωνα με το [Rust RFC Book][1], αυτά ενσωματώνονται κατά τη χρήση." + +#: src/basic-syntax/static-and-const.md:29 +#, fuzzy +msgid "## `static`" +msgstr "## «στατικό»." + +#: src/basic-syntax/static-and-const.md:31 +#, fuzzy +msgid "You can also declare static variables:" +msgstr "Μπορείτε επίσης να δηλώσετε στατικές μεταβλητές:" + +#: src/basic-syntax/static-and-const.md:33 +msgid "" +"```rust,editable\n" +"static BANNER: &str = \"Welcome to RustOS 3.14\";\n" +"\n" +"fn main() {\n" +" println!(\"{BANNER}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/static-and-const.md:41 +#, fuzzy +msgid "" +"As noted in the [Rust RFC Book][1], these are not inlined upon use and have " +"an actual associated memory location. This is useful for unsafe and " +"embedded code, and the variable lives through the entirety of the program " +"execution." +msgstr "" +"Όπως σημειώνεται στο [Rust RFC Book][1], αυτά δεν είναι ενσωματωμένα κατά τη " +"χρήση και έχουν μια πραγματική συσχετισμένη θέση μνήμης. Αυτό είναι χρήσιμο " +"για μη ασφαλή και ενσωματωμένο κώδικα και η μεταβλητή ζει σε όλη την " +"εκτέλεση του προγράμματος." + +#: src/basic-syntax/static-and-const.md:44 +#, fuzzy +msgid "" +"We will look at mutating static data in the [chapter on Unsafe Rust](../" +"unsafe.md)." +msgstr "" +"Θα εξετάσουμε τη μετάλλαξη στατικών δεδομένων στο [κεφάλαιο για την Μη " +"ασφαλή σκουριά] (../unsafe.md)." + +#: src/basic-syntax/static-and-const.md:48 +#, fuzzy +msgid "" +"* Mention that `const` behaves semantically similar to C++'s `constexpr`.\n" +"* `static`, on the other hand, is much more similar to a `const` or mutable " +"global variable in C++.\n" +"* It isn't super common that one would need a runtime evaluated constant, " +"but it is helpful and safer than using a static." +msgstr "" +"* Αναφέρετε ότι το «const» συμπεριφέρεται σημασιολογικά παρόμοια με το " +"«constexpr» της C++.\n" +"* Το «static», από την άλλη πλευρά, μοιάζει πολύ περισσότερο με μια «const» " +"ή μεταβλητή καθολική μεταβλητή στη C++.\n" +"* Δεν είναι πολύ συνηθισμένο να χρειάζεται κάποιος μια σταθερά αξιολόγησης " +"χρόνου εκτέλεσης, αλλά είναι χρήσιμο και ασφαλέστερο από τη χρήση στατικού." + +#: src/basic-syntax/scopes-shadowing.md:1 +#, fuzzy +msgid "# Scopes and Shadowing" +msgstr "# Πεδίο εφαρμογής και σκίαση" + +#: src/basic-syntax/scopes-shadowing.md:3 +#, fuzzy +msgid "" +"You can shadow variables, both those from outer scopes and variables from " +"the\n" +"same scope:" +msgstr "" +"Μπορείτε να σκιάζετε μεταβλητές, τόσο αυτές από εξωτερικά πεδία όσο και " +"μεταβλητές από το\n" +"ίδιο εύρος:" + +#: src/basic-syntax/scopes-shadowing.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a = 10;\n" +" println!(\"before: {a}\");\n" +"\n" +" {\n" +" let a = \"hello\";\n" +" println!(\"inner scope: {a}\");\n" +"\n" +" let a = true;\n" +" println!(\"shadowed in inner scope: {a}\");\n" +" }\n" +"\n" +" println!(\"after: {a}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:25 +#, fuzzy +msgid "" +"* Definition: Shadowing is different from mutation, because after shadowing " +"both variable's memory locations exist at the same time. Both are available " +"under the same name, depending where you use it in the code. \n" +"* A shadowing variable can have a different type. \n" +"* Shadowing looks obscure at first, but is convenient for holding on to " +"values after `.unwrap()`.\n" +"* The following code demonstrates why the compiler can't simply reuse memory " +"locations when shadowing an immutable variable in a scope, even if the type " +"does not change." +msgstr "" +"* Ορισμός: Η σκίαση είναι διαφορετική από τη μετάλλαξη, γιατί μετά τη σκίαση " +"υπάρχουν και οι δύο θέσεις μνήμης της μεταβλητής ταυτόχρονα. Και τα δύο " +"είναι διαθέσιμα με το ίδιο όνομα, ανάλογα με το πού το χρησιμοποιείτε στον " +"κωδικό.\n" +"* Μια μεταβλητή σκίασης μπορεί να έχει διαφορετικό τύπο.\n" +"* Η σκίαση φαίνεται ασαφής στην αρχή, αλλά είναι βολική για να κρατάτε τις " +"τιμές μετά το «.unwrap()».\n" +"* Ο ακόλουθος κώδικας δείχνει γιατί ο μεταγλωττιστής δεν μπορεί απλώς να " +"επαναχρησιμοποιήσει θέσεις μνήμης όταν σκιάζει μια αμετάβλητη μεταβλητή σε " +"ένα εύρος, ακόμα κι αν ο τύπος δεν αλλάξει." + +#: src/basic-syntax/scopes-shadowing.md:30 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a = 1;\n" +" let b = &a;\n" +" let a = a + 1;\n" +" println!(\"{a} {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management.md:1 +#, fuzzy +msgid "# Memory Management" +msgstr "# Διαχείριση μνήμης" + +#: src/memory-management.md:3 +#, fuzzy +msgid "Traditionally, languages have fallen into two broad categories:" +msgstr "Παραδοσιακά, οι γλώσσες χωρίζονται σε δύο μεγάλες κατηγορίες:" + +#: src/memory-management.md:5 +#, fuzzy +msgid "" +"* Full control via manual memory management: C, C++, Pascal, ...\n" +"* Full safety via automatic memory management at runtime: Java, Python, Go, " +"Haskell, ..." +msgstr "" +"* Πλήρης έλεγχος μέσω χειροκίνητης διαχείρισης μνήμης: C, C++, Pascal, ...\n" +"* Πλήρης ασφάλεια μέσω αυτόματης διαχείρισης μνήμης κατά την εκτέλεση: Java, " +"Python, Go, Haskell, ..." + +#: src/memory-management.md:8 +#, fuzzy +msgid "Rust offers a new mix:" +msgstr "Η Rust προσφέρει ένα νέο μείγμα:" + +#: src/memory-management.md:10 +#, fuzzy +msgid "" +"> Full control *and* safety via compile time enforcement of correct memory\n" +"> management." +msgstr "" +"> Πλήρης έλεγχος *και* ασφάλεια μέσω επιβολής χρόνου μεταγλώττισης της " +"σωστής μνήμης\n" +"> διαχείριση." + +#: src/memory-management.md:13 +#, fuzzy +msgid "It does this with an explicit ownership concept." +msgstr "Το κάνει αυτό με μια ρητή έννοια ιδιοκτησίας." + +#: src/memory-management.md:15 +#, fuzzy +msgid "First, let's refresh how memory management works." +msgstr "Αρχικά, ας ανανεώσουμε τον τρόπο λειτουργίας της διαχείρισης μνήμης." + +#: src/memory-management/stack-vs-heap.md:1 +#, fuzzy +msgid "# The Stack vs The Heap" +msgstr "# The Stack vs The Heap" + +#: src/memory-management/stack-vs-heap.md:3 +#, fuzzy +msgid "" +"* Stack: Continuous area of memory for local variables.\n" +" * Values have fixed sizes known at compile time.\n" +" * Extremely fast: just move a stack pointer.\n" +" * Easy to manage: follows function calls.\n" +" * Great memory locality.\n" +"\n" +"* Heap: Storage of values outside of function calls.\n" +" * Values have dynamic sizes determined at runtime.\n" +" * Slightly slower than the stack: some book-keeping needed.\n" +" * No guarantee of memory locality." +msgstr "" +"* Στοίβα: Συνεχής περιοχή μνήμης για τοπικές μεταβλητές.\n" +" * Οι τιμές έχουν σταθερά μεγέθη γνωστά κατά το χρόνο μεταγλώττισης.\n" +" * Εξαιρετικά γρήγορο: απλώς μετακινήστε έναν δείκτη στοίβας.\n" +" * Εύκολο στη διαχείριση: ακολουθεί κλήσεις λειτουργιών.\n" +" * Μεγάλη τοποθεσία μνήμης." + +#: src/memory-management/stack.md:1 +#, fuzzy +msgid "# Stack Memory" +msgstr "# Στοίβα Μνήμη" + +#: src/memory-management/stack.md:3 +#, fuzzy +msgid "" +"Creating a `String` puts fixed-sized data on the stack and dynamically " +"sized\n" +"data on the heap:" +msgstr "" +"Η δημιουργία ενός \"String\" τοποθετεί δεδομένα σταθερού μεγέθους στη στοίβα " +"και δυναμικά μεγέθη\n" +"δεδομένα για το σωρό:" + +#: src/memory-management/stack.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1 = String::from(\"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:12 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | e | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:28 +msgid "" +"* Mention that a `String` is backed by a `Vec`, so it has a capacity and " +"length and can grow if mutable via reallocation on the heap.\n" +"\n" +"* If students ask about it, you can mention that the underlying memory is " +"heap allocated using the [System Allocator] and custom allocators can be " +"implemented using the [Allocator API]\n" +"\n" +"* We can inspect the memory layout with `unsafe` code. However, you should " +"point out that this is rightfully unsafe!\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could " +"lead to\n" +" // undefined behavior.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::" +"transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = " +"{capacity}\");\n" +" }\n" +" }\n" +" ```" +msgstr "" + +#: src/memory-management/manual.md:1 +#, fuzzy +msgid "# Manual Memory Management" +msgstr "# Χειροκίνητη διαχείριση μνήμης" + +#: src/memory-management/manual.md:3 +#, fuzzy +msgid "You allocate and deallocate heap memory yourself." +msgstr "Εκχωρείτε και εκχωρείτε τη μνήμη σωρού μόνοι σας." + +#: src/memory-management/manual.md:5 +#, fuzzy +msgid "" +"If not done with care, this can lead to crashes, bugs, security " +"vulnerabilities, and memory leaks." +msgstr "" +"Εάν δεν γίνει με προσοχή, αυτό μπορεί να οδηγήσει σε σφάλματα, σφάλματα, " +"ευπάθειες ασφαλείας και διαρροές μνήμης." + +#: src/memory-management/manual.md:7 +#, fuzzy +msgid "## C Example" +msgstr "## Γ Παράδειγμα" + +#: src/memory-management/manual.md:9 +#, fuzzy +msgid "You must call `free` on every pointer you allocate with `malloc`:" +msgstr "" +"Πρέπει να καλείτε \"δωρεάν\" σε κάθε δείκτη που εκχωρείτε με το \"malloc\":" + +#: src/memory-management/manual.md:11 +msgid "" +"```c\n" +"void foo(size_t n) {\n" +" int* int_array = (int*)malloc(n * sizeof(int));\n" +" //\n" +" // ... lots of code\n" +" //\n" +" free(int_array);\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/manual.md:21 +#, fuzzy +msgid "" +"Memory is leaked if the function returns early between `malloc` and `free`: " +"the\n" +"pointer is lost and we cannot deallocate the memory." +msgstr "" +"Η μνήμη διαρρέει εάν η συνάρτηση επιστρέψει νωρίς μεταξύ \"malloc\" και " +"\"free\": το\n" +"Ο δείκτης χάνεται και δεν μπορούμε να εκχωρήσουμε τη μνήμη." + +#: src/memory-management/scope-based.md:1 +#, fuzzy +msgid "# Scope-Based Memory Management" +msgstr "# Διαχείριση μνήμης βάσει εύρους" + +#: src/memory-management/scope-based.md:3 +#, fuzzy +msgid "" +"Constructors and destructors let you hook into the lifetime of an object." +msgstr "" +"Οι κατασκευαστές και οι καταστροφείς σάς επιτρέπουν να κολλήσετε στη " +"διάρκεια ζωής ενός αντικειμένου." + +#: src/memory-management/scope-based.md:5 +#, fuzzy +msgid "" +"By wrapping a pointer in an object, you can free memory when the object is\n" +"destroyed. The compiler guarantees that this happens, even if an exception " +"is\n" +"raised." +msgstr "" +"Τυλίγοντας έναν δείκτη σε ένα αντικείμενο, μπορείτε να ελευθερώσετε μνήμη " +"όταν το αντικείμενο βρίσκεται\n" +"καταστράφηκε από. Ο μεταγλωττιστής εγγυάται ότι αυτό συμβαίνει, ακόμα κι αν " +"υπάρχει εξαίρεση\n" +"ανυψώθηκε." + +#: src/memory-management/scope-based.md:9 +#, fuzzy +msgid "" +"This is often called _resource acquisition is initialization_ (RAII) and " +"gives\n" +"you smart pointers." +msgstr "" +"Αυτό συχνά ονομάζεται _απόκτηση πόρων είναι αρχικοποίηση_ (RAII) και δίνει\n" +"έξυπνοι δείκτες." + +#: src/memory-management/scope-based.md:12 +#, fuzzy +msgid "## C++ Example" +msgstr "## Παράδειγμα C++" + +#: src/memory-management/scope-based.md:14 +msgid "" +"```c++\n" +"void say_hello(std::unique_ptr person) {\n" +" std::cout << \"Hello \" << person->name << std::endl;\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/scope-based.md:20 +#, fuzzy +msgid "" +"* The `std::unique_ptr` object is allocated on the stack, and points to\n" +" memory allocated on the heap.\n" +"* At the end of `say_hello`, the `std::unique_ptr` destructor will run.\n" +"* The destructor frees the `Person` object it points to." +msgstr "" +"* Το αντικείμενο `std::unique_ptr` εκχωρείται στη στοίβα και δείχνει σε\n" +" μνήμη που εκχωρείται στο σωρό.\n" +"* Στο τέλος του «say_hello», θα εκτελεστεί ο καταστροφέας «std::" +"unique_ptr».\n" +"* Ο καταστροφέας ελευθερώνει το αντικείμενο «Person» στο οποίο δείχνει." + +#: src/memory-management/scope-based.md:25 +#, fuzzy +msgid "" +"Special move constructors are used when passing ownership to a function:" +msgstr "" +"Οι ειδικοί κατασκευαστές μετακίνησης χρησιμοποιούνται όταν μεταβιβάζεται η " +"ιδιοκτησία σε μια συνάρτηση:" + +#: src/memory-management/scope-based.md:27 +msgid "" +"```c++\n" +"std::unique_ptr person = find_person(\"Carla\");\n" +"say_hello(std::move(person));\n" +"```" +msgstr "" + +#: src/memory-management/garbage-collection.md:1 +#, fuzzy +msgid "# Automatic Memory Management" +msgstr "# Αυτόματη διαχείριση μνήμης" + +#: src/memory-management/garbage-collection.md:3 +#, fuzzy +msgid "" +"An alternative to manual and scope-based memory management is automatic " +"memory\n" +"management:" +msgstr "" +"Μια εναλλακτική λύση στη χειροκίνητη διαχείριση μνήμης και τη διαχείριση " +"μνήμης βάσει εύρους είναι η αυτόματη μνήμη\n" +"διαχείριση:" + +#: src/memory-management/garbage-collection.md:6 +#, fuzzy +msgid "" +"* The programmer never allocates or deallocates memory explicitly.\n" +"* A garbage collector finds unused memory and deallocates it for the " +"programmer." +msgstr "" +"* Ο προγραμματιστής ποτέ δεν εκχωρεί ή εκχωρεί μνήμη ρητά.\n" +"* Ένας συλλέκτης σκουπιδιών βρίσκει αχρησιμοποίητη μνήμη και την εκχωρεί " +"στον προγραμματιστή." + +#: src/memory-management/garbage-collection.md:9 +#, fuzzy +msgid "## Java Example" +msgstr "## Παράδειγμα Java" + +#: src/memory-management/garbage-collection.md:11 +#, fuzzy +msgid "The `person` object is not deallocated after `sayHello` returns:" +msgstr "" +"Το αντικείμενο \"person\" δεν εκχωρείται μετά την επιστροφή του \"sayHello\":" + +#: src/memory-management/garbage-collection.md:13 +msgid "" +"```java\n" +"void sayHello(Person person) {\n" +" System.out.println(\"Hello \" + person.getName());\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/rust.md:1 +#, fuzzy +msgid "# Memory Management in Rust" +msgstr "# Διαχείριση μνήμης σε Rust" + +#: src/memory-management/rust.md:3 +#, fuzzy +msgid "Memory management in Rust is a mix:" +msgstr "Η διαχείριση μνήμης στο Rust είναι ένας συνδυασμός:" + +#: src/memory-management/rust.md:5 +#, fuzzy +msgid "" +"* Safe and correct like Java, but without a garbage collector.\n" +"* Depending on which abstraction (or combination of abstractions) you " +"choose, can be a single unique pointer, reference counted, or atomically " +"reference counted.\n" +"* Scope-based like C++, but the compiler enforces full adherence.\n" +"* A Rust user can choose the right abstraction for the situation, some even " +"have no cost at runtime like C." +msgstr "" +"* Ασφαλές και σωστό όπως η Java, αλλά χωρίς σκουπιδοσυλλέκτη.\n" +"* Ανάλογα με το ποια αφαίρεση (ή συνδυασμό αφαιρέσεων) επιλέγετε, μπορεί να " +"είναι ένας μοναδικός δείκτης, να μετράται η αναφορά ή να μετράται ατομικά η " +"αναφορά.\n" +"* Βασίζεται στο πεδίο εφαρμογής όπως η C++, αλλά ο μεταγλωττιστής επιβάλλει " +"την πλήρη συμμόρφωση.\n" +"* Ένας χρήστης του Rust μπορεί να επιλέξει τη σωστή αφαίρεση για την " +"κατάσταση, μερικοί μάλιστα δεν έχουν κόστος κατά τη διάρκεια εκτέλεσης όπως " +"το C." + +#: src/memory-management/rust.md:10 +#, fuzzy +msgid "It achieves this by modeling _ownership_ explicitly." +msgstr "Αυτό το επιτυγχάνει διαμορφώνοντας ρητά την _ownership_." + +#: src/memory-management/rust.md:14 +#, fuzzy +msgid "" +"* If asked how at this point, you can mention that in Rust this is usually " +"handled by RAII wrapper types such as [Box], [Vec], [Rc], or [Arc]. These " +"encapsulate ownership and memory allocation via various means, and prevent " +"the potential errors in C.\n" +"\n" +"* You may be asked about destructors here, the [Drop] trait is the Rust " +"equivalent." +msgstr "" +"* Εάν ρωτήσετε πώς σε αυτό το σημείο, μπορείτε να αναφέρετε ότι στο Rust " +"αυτό συνήθως αντιμετωπίζεται από τύπους περιτυλίγματος RAII όπως [Box], " +"[Vec], [Rc] ή [Arc]. Αυτά ενσωματώνουν την ιδιοκτησία και την εκχώρηση " +"μνήμης με διάφορα μέσα και αποτρέπουν τα πιθανά σφάλματα στο C." + +#: src/memory-management/comparison.md:1 +#, fuzzy +msgid "# Comparison" +msgstr "# Σύγκριση" + +#: src/memory-management/comparison.md:3 +#, fuzzy +msgid "Here is a rough comparison of the memory management techniques." +msgstr "Ακολουθεί μια πρόχειρη σύγκριση των τεχνικών διαχείρισης μνήμης." + +#: src/memory-management/comparison.md:5 +#, fuzzy +msgid "## Pros of Different Memory Management Techniques" +msgstr "## Πλεονεκτήματα Διαφορετικών Τεχνικών Διαχείρισης Μνήμης" + +#: src/memory-management/comparison.md:7 +#, fuzzy +msgid "" +"* Manual like C:\n" +" * No runtime overhead.\n" +"* Automatic like Java:\n" +" * Fully automatic.\n" +" * Safe and correct.\n" +"* Scope-based like C++:\n" +" * Partially automatic.\n" +" * No runtime overhead.\n" +"* Compiler-enforced scope-based like Rust:\n" +" * Enforced by compiler.\n" +" * No runtime overhead.\n" +" * Safe and correct." +msgstr "" +"* Εγχειρίδιο όπως C:\n" +" * Χωρίς επιβάρυνση χρόνου εκτέλεσης.\n" +"* Αυτόματο όπως Java:\n" +" * Εντελώς αυτόματο.\n" +" * Ασφαλές και σωστό.\n" +"* Βασισμένο σε πεδίο εφαρμογής όπως η C++:\n" +" * Μερικώς αυτόματο.\n" +" * Χωρίς επιβάρυνση χρόνου εκτέλεσης.\n" +"* Βασισμένο σε εύρος με επιβολή μεταγλωττιστή όπως το Rust:\n" +" * Επιβάλλεται από τον μεταγλωττιστή.\n" +" * Χωρίς επιβάρυνση χρόνου εκτέλεσης.\n" +" * Ασφαλές και σωστό." + +#: src/memory-management/comparison.md:20 +#, fuzzy +msgid "## Cons of Different Memory Management Techniques" +msgstr "## Μειονεκτήματα των διαφορετικών τεχνικών διαχείρισης μνήμης" + +#: src/memory-management/comparison.md:22 +#, fuzzy +msgid "" +"* Manual like C:\n" +" * Use-after-free.\n" +" * Double-frees.\n" +" * Memory leaks.\n" +"* Automatic like Java:\n" +" * Garbage collection pauses.\n" +" * Destructor delays.\n" +"* Scope-based like C++:\n" +" * Complex, opt-in by programmer.\n" +" * Potential for use-after-free.\n" +"* Compiler-enforced and scope-based like Rust:\n" +" * Some upfront complexity.\n" +" * Can reject valid programs." +msgstr "" +"* Εγχειρίδιο όπως C:\n" +" * Χρήση-μετά-δωρεάν.\n" +" * Διπλό δωρεάν.\n" +" * Διαρροές μνήμης.\n" +"* Αυτόματο όπως Java:\n" +" * Παύσεις αποκομιδής σκουπιδιών.\n" +" * Καθυστερήσεις καταστροφέων.\n" +"* Βασισμένο σε πεδίο εφαρμογής όπως η C++:\n" +" * Σύνθετο, συμμετοχή από προγραμματιστή.\n" +" * Δυνατότητα χρήσης-μετά-δωρεάν.\n" +"* Επιβάλλεται από μεταγλωττιστή και βασίζεται σε εύρος όπως το Rust:\n" +" * Κάποια εκ των προτέρων πολυπλοκότητα.\n" +" * Μπορεί να απορρίψει έγκυρα προγράμματα." + +#: src/ownership.md:1 +#, fuzzy +msgid "# Ownership" +msgstr "# Ιδιοκτησία" + +#: src/ownership.md:3 +#, fuzzy +msgid "" +"All variable bindings have a _scope_ where they are valid and it is an error " +"to\n" +"use a variable outside its scope:" +msgstr "" +"Όλες οι δεσμεύσεις μεταβλητών έχουν _scope_ όπου είναι έγκυρες και είναι " +"σφάλμα\n" +"χρησιμοποιήστε μια μεταβλητή εκτός του πεδίου εφαρμογής της:" + +#: src/ownership.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" {\n" +" let p = Point(3, 4);\n" +" println!(\"x: {}\", p.0);\n" +" }\n" +" println!(\"y: {}\", p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership.md:18 +#, fuzzy +msgid "" +"* At the end of the scope, the variable is _dropped_ and the data is freed.\n" +"* A destructor can run here to free up resources.\n" +"* We say that the variable _owns_ the value." +msgstr "" +"* Στο τέλος του εύρους, η μεταβλητή _αποτέθηκε_ και τα δεδομένα " +"ελευθερώνονται.\n" +"* Ένας καταστροφέας μπορεί να τρέξει εδώ για να ελευθερώσει πόρους.\n" +"* Λέμε ότι η μεταβλητή _κατέχει_ την τιμή." + +#: src/ownership/move-semantics.md:1 +#, fuzzy +msgid "# Move Semantics" +msgstr "# Move Semantics" + +#: src/ownership/move-semantics.md:3 +#, fuzzy +msgid "An assignment will transfer ownership between variables:" +msgstr "Μια ανάθεση θα μεταβιβάσει την ιδιοκτησία μεταξύ μεταβλητών:" + +#: src/ownership/move-semantics.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Hello!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/move-semantics.md:14 +#, fuzzy +msgid "" +"* The assignment of `s1` to `s2` transfers ownership.\n" +"* The data was _moved_ from `s1` and `s1` is no longer accessible.\n" +"* When `s1` goes out of scope, nothing happens: it has no ownership.\n" +"* When `s2` goes out of scope, the string data is freed.\n" +"* There is always _exactly_ one variable binding which owns a value." +msgstr "" +"* Η εκχώρηση του `s1` στο `s2` μεταβιβάζει την ιδιοκτησία.\n" +"* Τα δεδομένα _μετακινήθηκαν_ από το `s1` και το `s1` δεν είναι πλέον " +"προσβάσιμο.\n" +"* Όταν το `s1` βγαίνει εκτός πεδίου εφαρμογής, δεν συμβαίνει τίποτα: δεν " +"έχει ιδιοκτησία.\n" +"* Όταν το `s2` βγαίνει εκτός εύρους, τα δεδομένα συμβολοσειράς " +"ελευθερώνονται.\n" +"* Υπάρχει πάντα _exactly_ μία δέσμευση μεταβλητής που κατέχει μια τιμή." + +#: src/ownership/move-semantics.md:22 +#, fuzzy +msgid "" +"* Mention that this is the opposite of the defaults in C++, which copies by " +"value unless you use `std::move` (and the move constructor is defined!).\n" +"\n" +"* In Rust, clones are explicit (by using `clone`)." +msgstr "" +"* Αναφέρετε ότι αυτό είναι το αντίθετο από τις προεπιλογές της C++, η οποία " +"αντιγράφει με βάση την τιμή, εκτός και αν χρησιμοποιήσετε το `std::move` " +"(και ορίζεται ο κατασκευαστής κίνησης!)." + +#: src/ownership/moved-strings-rust.md:1 +#, fuzzy +msgid "# Moved Strings in Rust" +msgstr "# Μετακινήθηκαν χορδές σε σκουριά" + +#: src/ownership/moved-strings-rust.md:3 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Rust\");\n" +" let s2: String = s1;\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:10 +#, fuzzy +msgid "" +"* The heap data from `s1` is reused for `s2`.\n" +"* When `s1` goes out of scope, nothing happens (it has been moved from)." +msgstr "" +"* Τα δεδομένα σωρού από το `s1` επαναχρησιμοποιούνται για το `s2`.\n" +"* Όταν το `s1` βγαίνει εκτός πεδίου εφαρμογής, δεν συμβαίνει τίποτα (έχει " +"μετακινηθεί από)." + +#: src/ownership/moved-strings-rust.md:13 +#, fuzzy +msgid "Before move to `s2`:" +msgstr "Πριν μεταβείτε στο `s2`:" + +#: src/ownership/moved-strings-rust.md:15 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| R | u | s | t | :\n" +": | len | 4 | : : +----+----+----+----+ :\n" +": | capacity | 4 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - -'\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:30 +#, fuzzy +msgid "After move to `s2`:" +msgstr "Μετά τη μετάβαση στο `s2`:" + +#: src/ownership/moved-strings-rust.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 \"(inaccessible)\" : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" +": | len | 4 | : | : +----+----+----+----+ :\n" +": | capacity | 4 | : | : :\n" +": +-----------+-------+ : | : :\n" +": : | `- - - - - - - - - - - - - -'\n" +": s2 : |\n" +": +-----------+-------+ : |\n" +": | ptr | o---+---+--'\n" +": | len | 4 | :\n" +": | capacity | 4 | :\n" +": +-----------+-------+ :\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:1 +#, fuzzy +msgid "# Double Frees in Modern C++" +msgstr "# Double Frees στη σύγχρονη C++" + +#: src/ownership/double-free-modern-cpp.md:3 +#, fuzzy +msgid "Modern C++ solves this differently:" +msgstr "Η σύγχρονη C++ το λύνει διαφορετικά:" + +#: src/ownership/double-free-modern-cpp.md:5 +msgid "" +"```c++\n" +"std::string s1 = \"Cpp\";\n" +"std::string s2 = s1; // Duplicate the data in s1.\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:10 +#, fuzzy +msgid "" +"* The heap data from `s1` is duplicated and `s2` gets its own independent " +"copy.\n" +"* When `s1` and `s2` go out of scope, they each free their own memory." +msgstr "" +"* Τα δεδομένα σωρού από το `s1` είναι διπλά και το `s2` αποκτά το δικό του " +"ανεξάρτητο αντίγραφο.\n" +"* Όταν τα «s1» και «s2» βγαίνουν εκτός πεδίου εφαρμογής, το καθένα " +"απελευθερώνει τη δική του μνήμη." + +#: src/ownership/double-free-modern-cpp.md:13 +#, fuzzy +msgid "Before copy-assignment:" +msgstr "Πριν την αντιγραφή-ανάθεση:" + +#: src/ownership/double-free-modern-cpp.md:16 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:30 +#, fuzzy +msgid "After copy-assignment:" +msgstr "Μετά την αντιγραφή-ανάθεση:" + +#: src/ownership/double-free-modern-cpp.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : : :\n" +": s2 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+-----+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:1 +#, fuzzy +msgid "# Moves in Function Calls" +msgstr "# Κινήσεις σε κλήσεις συναρτήσεων" + +#: src/ownership/moves-function-calls.md:3 +#, fuzzy +msgid "" +"When you pass a value to a function, the value is assigned to the function\n" +"parameter. This transfers ownership:" +msgstr "" +"Όταν μεταβιβάζετε μια τιμή σε μια συνάρτηση, η τιμή εκχωρείται στη " +"συνάρτηση\n" +"παράμετρος. Αυτό μεταβιβάζει την ιδιοκτησία:" + +#: src/ownership/moves-function-calls.md:6 +msgid "" +"```rust,editable\n" +"fn say_hello(name: String) {\n" +" println!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let name = String::from(\"Alice\");\n" +" say_hello(name);\n" +" // say_hello(name);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:20 +#, fuzzy +msgid "" +"* With the first call to `say_hello`, `main` gives up ownership of `name`. " +"Afterwards, `name` cannot be used anymore within `main`.\n" +"* The heap memory allocated for `name` will be freed at the end of the " +"`say_hello` function.\n" +"* `main` can retain ownership if it passes `name` as a reference (`&name`) " +"and if `say_hello` accepts a reference as a parameter.\n" +"* Alternatively, `main` can pass a clone of `name` in the first call (`name." +"clone()`).\n" +"* Rust makes it harder than C++ to inadvertently create copies by making " +"move semantics the default, and by forcing programmers to make clones " +"explicit." +msgstr "" +"* Με την πρώτη κλήση στο \"say_hello\", ο \"main\" παραιτείται από την " +"ιδιοκτησία του \"name\". Στη συνέχεια, το \"όνομα\" δεν μπορεί να " +"χρησιμοποιηθεί πλέον στο \"κύριο\".\n" +"* Η μνήμη σωρού που έχει εκχωρηθεί για το \"όνομα\" θα ελευθερωθεί στο τέλος " +"της συνάρτησης \"say_hello\".\n" +"* Το \"main\" μπορεί να διατηρήσει την ιδιοκτησία εάν μεταβιβάσει το " +"\"name\" ως αναφορά (\"&name\") και εάν το \"say_hello\" αποδεχτεί μια " +"αναφορά ως παράμετρο.\n" +"* Εναλλακτικά, το \"main\" μπορεί να περάσει έναν κλώνο του \"name\" στην " +"πρώτη κλήση (\"name.clone()\").\n" +"* Το Rust καθιστά δυσκολότερο από την C++ την ακούσια δημιουργία αντιγράφων " +"καθιστώντας τη σημασιολογία κίνησης ως προεπιλογή και αναγκάζοντας τους " +"προγραμματιστές να κάνουν τους κλώνους ξεκάθαρους." + +#: src/ownership/copy-clone.md:1 +#, fuzzy +msgid "# Copying and Cloning" +msgstr "# Αντιγραφή και κλωνοποίηση" + +#: src/ownership/copy-clone.md:3 +#, fuzzy +msgid "" +"While move semantics are the default, certain types are copied by default:" +msgstr "" +"Ενώ η σημασιολογία μετακίνησης είναι η προεπιλογή, ορισμένοι τύποι " +"αντιγράφονται από προεπιλογή:" + +#: src/ownership/copy-clone.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = 42;\n" +" let y = x;\n" +" println!(\"x: {x}\");\n" +" println!(\"y: {y}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:14 +#, fuzzy +msgid "These types implement the `Copy` trait." +msgstr "Αυτοί οι τύποι εφαρμόζουν το χαρακτηριστικό «Αντιγραφή»." + +#: src/ownership/copy-clone.md:16 +#, fuzzy +msgid "You can opt-in your own types to use copy semantics:" +msgstr "" +"Μπορείτε να επιλέξετε τους δικούς σας τύπους για χρήση σημασιολογίας " +"αντιγραφής:" + +#: src/ownership/copy-clone.md:18 +msgid "" +"```rust,editable\n" +"#[derive(Copy, Clone, Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = p1;\n" +" println!(\"p1: {p1:?}\");\n" +" println!(\"p2: {p2:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:30 +#, fuzzy +msgid "" +"* After the assignment, both `p1` and `p2` own their own data.\n" +"* We can also use `p1.clone()` to explicitly copy the data." +msgstr "" +"* Μετά την ανάθεση, τόσο το «p1» και το «p2» έχουν τα δικά τους δεδομένα.\n" +"* Μπορούμε επίσης να χρησιμοποιήσουμε το «p1.clone()» για να αντιγράψουμε " +"ρητά τα δεδομένα." + +#: src/ownership/copy-clone.md:35 +#, fuzzy +msgid "Copying and cloning are not the same thing:" +msgstr "Η αντιγραφή και η κλωνοποίηση δεν είναι το ίδιο πράγμα:" + +#: src/ownership/copy-clone.md:37 +#, fuzzy +msgid "" +"* Copying refers to bitwise copies of memory regions and does not work on " +"arbitrary objects.\n" +"* Copying does not allow for custom logic (unlike copy constructors in C+" +"+).\n" +"* Cloning is a more general operation and also allows for custom behavior by " +"implementing the `Clone` trait.\n" +"* Copying does not work on types that implement the `Drop` trait." +msgstr "" +"* Η αντιγραφή αναφέρεται σε αντίγραφα bitwise περιοχών μνήμης και δεν " +"λειτουργεί σε αυθαίρετα αντικείμενα.\n" +"* Η αντιγραφή δεν επιτρέπει προσαρμοσμένη λογική (σε αντίθεση με τους " +"κατασκευαστές αντιγραφής στη C++).\n" +"* Η κλωνοποίηση είναι μια πιο γενική λειτουργία και επιτρέπει επίσης " +"προσαρμοσμένη συμπεριφορά με την εφαρμογή του χαρακτηριστικού " +"«Κλωνοποίηση».\n" +"* Η αντιγραφή δεν λειτουργεί σε τύπους που εφαρμόζουν το χαρακτηριστικό " +"«Drop»." + +#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 +#, fuzzy +msgid "In the above example, try the following:" +msgstr "Στο παραπάνω παράδειγμα, δοκιμάστε τα εξής:" + +#: src/ownership/copy-clone.md:44 +#, fuzzy +msgid "" +"* Add a `String` field to `struct Point`. It will not compile because " +"`String` is not a `Copy` type.\n" +"* Remove `Copy` from the `derive` attribute. The compiler error is now in " +"the `println!` for `p1`.\n" +"* Show that it works if you clone `p1` instead." +msgstr "" +"* Προσθέστε ένα πεδίο «String» στο «struct Point». Δεν θα μεταγλωττιστεί " +"επειδή το \"String\" δεν είναι τύπος \"Αντιγραφή\".\n" +"* Καταργήστε το \"Copy\" από το χαρακτηριστικό \"derive\". Το σφάλμα " +"μεταγλωττιστή βρίσκεται τώρα στο «println!» για το «p1».\n" +"* Δείξτε ότι λειτουργεί εάν αντ' αυτού κλωνοποιήσετε το \"p1\"." + +#: src/ownership/copy-clone.md:48 +#, fuzzy +msgid "" +"If students ask about `derive`, it is sufficient to say that this is a way " +"to generate code in Rust\n" +"at compile time. In this case the default implementations of `Copy` and " +"`Clone` traits are generated." +msgstr "" +"Εάν οι μαθητές ρωτήσουν για το «derive», αρκεί να πούμε ότι αυτός είναι ένας " +"τρόπος δημιουργίας κώδικα στο Rust\n" +"την ώρα της μεταγλώττισης. Σε αυτήν την περίπτωση δημιουργούνται οι " +"προεπιλεγμένες υλοποιήσεις των χαρακτηριστικών «Αντιγραφή» και " +"«Κλωνοποίηση».\n" +" \n" +"" + +#: src/ownership/borrowing.md:1 +#, fuzzy +msgid "# Borrowing" +msgstr "#Δανεισμός" + +#: src/ownership/borrowing.md:3 +#, fuzzy +msgid "" +"Instead of transferring ownership when calling a function, you can let a\n" +"function _borrow_ the value:" +msgstr "" +"Αντί να μεταβιβάζετε την ιδιοκτησία κατά την κλήση μιας συνάρτησης, μπορείτε " +"να αφήσετε α\n" +"συνάρτηση _borrow_ την τιμή:" + +#: src/ownership/borrowing.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn add(p1: &Point, p2: &Point) -> Point {\n" +" Point(p1.0 + p2.0, p1.1 + p2.1)\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/borrowing.md:22 +#, fuzzy +msgid "" +"* The `add` function _borrows_ two points and returns a new point.\n" +"* The caller retains ownership of the inputs." +msgstr "" +"* Η συνάρτηση «προσθήκη» _δανείζεται_ δύο σημεία και επιστρέφει ένα νέο " +"σημείο.\n" +"* Ο καλών διατηρεί την κυριότητα των εισόδων." + +#: src/ownership/borrowing.md:27 +msgid "Notes on stack returns:" +msgstr "" + +#: src/ownership/borrowing.md:28 +msgid "" +"* Demonstrate that the return from `add` is cheap because the compiler can " +"eliminate the copy operation. Change the above code to print stack addresses " +"and run it on the [Playground]. In the \"DEBUG\" optimization level, the " +"addresses should change, while they stay the same when changing to the " +"\"RELEASE\" setting:\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn add(p1: &Point, p2: &Point) -> Point {\n" +" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" +" println!(\"&p.0: {:p}\", &p.0);\n" +" p\n" +" }\n" +"\n" +" fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"&p3.0: {:p}\", &p3.0);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +" }\n" +" ```\n" +"* The Rust compiler can do return value optimization (RVO).\n" +"* In C++, copy elision has to be defined in the language specification " +"because constructors can have side effects. In Rust, this is not an issue at " +"all. If RVO did not happen, Rust will always performs a simple and efficient " +"`memcpy` copy." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:1 +#, fuzzy +msgid "# Shared and Unique Borrows" +msgstr "# Κοινόχρηστα και μοναδικά δάνεια" + +#: src/ownership/shared-unique-borrows.md:3 +#, fuzzy +msgid "Rust puts constraints on the ways you can borrow values:" +msgstr "" +"Το Rust θέτει περιορισμούς στους τρόπους με τους οποίους μπορείτε να " +"δανειστείτε τιμές:" + +#: src/ownership/shared-unique-borrows.md:5 +#, fuzzy +msgid "" +"* You can have one or more `&T` values at any given time, _or_\n" +"* You can have exactly one `&mut T` value." +msgstr "" +"* Μπορείτε να έχετε μία ή περισσότερες τιμές \"&T\" ανά πάσα στιγμή, _ή_\n" +"* Μπορείτε να έχετε ακριβώς μία τιμή «&mut T»." + +#: src/ownership/shared-unique-borrows.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let mut a: i32 = 10;\n" +" let b: &i32 = &a;\n" +"\n" +" {\n" +" let c: &mut i32 = &mut a;\n" +" *c = 20;\n" +" }\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:25 +#, fuzzy +msgid "" +"* The above code does not compile because `a` is borrowed as mutable " +"(through `c`) and as immutable (through `b`) at the same time.\n" +"* Move the `println!` statement for `b` before the scope that introduces `c` " +"to make the code compile.\n" +"* After that change, the compiler realizes that `b` is only ever used before " +"the new mutable borrow of `a` through `c`. This is a feature of the borrow " +"checker called \"non-lexical lifetimes\"." +msgstr "" +"* Ο παραπάνω κώδικας δεν μεταγλωττίζεται επειδή το «a» δανείζεται ταυτόχρονα " +"ως mutable (μέσω «c») και ως αμετάβλητο (μέσω «b»).\n" +"* Μετακινήστε τη δήλωση «println!» για το «b» πριν από το εύρος που εισάγει " +"το «c» για να κάνετε μεταγλώττιση του κώδικα.\n" +"* Μετά από αυτήν την αλλαγή, ο μεταγλωττιστής συνειδητοποιεί ότι το \"b\" " +"χρησιμοποιείται μόνο πριν από το νέο μεταβλητό δάνειο του \"a\" έως το " +"\"c\". Αυτό είναι ένα χαρακτηριστικό του ελεγκτή δανεισμού που ονομάζεται " +"\"μη λεξιλογικές ζωές\"." + +#: src/ownership/lifetimes.md:1 +#, fuzzy +msgid "# Lifetimes" +msgstr "# Διάρκεια ζωής" + +#: src/ownership/lifetimes.md:3 +#, fuzzy +msgid "A borrowed value has a _lifetime_:" +msgstr "Μια δανεισμένη αξία έχει _διάρκεια ζωής_:" + +#: src/ownership/lifetimes.md:5 +msgid "" +"* The lifetime can be elided: `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." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:1 +#, fuzzy +msgid "# Lifetimes in Function Calls" +msgstr "# Διάρκεια ζωής σε κλήσεις συναρτήσεων" + +#: src/ownership/lifetimes-function-calls.md:3 +#, fuzzy +msgid "" +"In addition to borrowing its arguments, a function can return a borrowed " +"value:" +msgstr "" +"Εκτός από τον δανεισμό των ορισμάτων της, μια συνάρτηση μπορεί να επιστρέψει " +"μια δανεισμένη τιμή:" + +#: src/ownership/lifetimes-function-calls.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p2: Point = Point(20, 20);\n" +" let p3: &Point = left_most(&p1, &p2);\n" +" println!(\"left-most point: {:?}\", p3);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:21 +#, fuzzy +msgid "" +"* `'a` is a generic parameter, it is inferred by the compiler.\n" +"* Lifetimes start with `'` and `'a` is a typical default name.\n" +"* Read `&'a Point` as \"a borrowed `Point` which is valid for at least the\n" +" lifetime `a`\".\n" +" * The _at least_ part is important when parameters are in different scopes." +msgstr "" +"* Το `'a` είναι μια γενική παράμετρος, συνάγεται από τον μεταγλωττιστή.\n" +"* Οι διάρκειες ζωής ξεκινούν με \"\"\" και το \"a\" είναι ένα τυπικό " +"προεπιλεγμένο όνομα.\n" +"* Διαβάστε το '&'a Point' ως \"ένα δανεικό \"Point\" που ισχύει τουλάχιστον " +"για το\n" +" διάρκεια ζωής «α»».\n" +" * Το τμήμα _τουλάχιστον_ είναι σημαντικό όταν οι παράμετροι βρίσκονται σε " +"διαφορετικά πεδία." + +#: 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 code:\n" +" ```rust,ignore\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +" }\n" +"\n" +" fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p3: &Point;\n" +" {\n" +" let p2: Point = Point(20, 20);\n" +" p3 = left_most(&p1, &p2);\n" +" }\n" +" println!(\"left-most point: {:?}\", p3);\n" +" }\n" +" ```\n" +" Note how this does not compile since `p3` outlives `p2`.\n" +"\n" +"* Reset the workspace and change the function signature to `fn left_most<'a, " +"'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " +"because the relationship between the lifetimes `'a` and `'b` is unclear.\n" +"* Another way to explain it:\n" +" * 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" +" for longer than a variable from where the reference came from." +msgstr "" +"* Επαναφέρετε τον χώρο εργασίας και αλλάξτε την υπογραφή της συνάρτησης σε " +"`fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. Αυτό δεν " +"θα μεταγλωττιστεί επειδή η σχέση μεταξύ των χρόνων ζωής \"a\" και \"b\" " +"είναι ασαφής.\n" +"* Ένας άλλος τρόπος να το εξηγήσετε:\n" +" * Δύο αναφορές σε δύο τιμές δανείζονται από μια συνάρτηση και η συνάρτηση " +"επιστρέφει\n" +" άλλη αναφορά.\n" +" * Πρέπει να προέρχεται από μία από αυτές τις δύο εισόδους (ή από μια " +"καθολική μεταβλητή).\n" +" * Ποιο είναι απ 'όλα? Ο μεταγλωττιστής πρέπει να γνωρίζει, επομένως στον " +"ιστότοπο κλήσης δεν χρησιμοποιείται η επιστρεφόμενη αναφορά\n" +" για περισσότερο από μια μεταβλητή από την οποία προήλθε η αναφορά." + +#: src/ownership/lifetimes-data-structures.md:1 +#, fuzzy +msgid "# Lifetimes in Data Structures" +msgstr "# Διάρκεια ζωής σε δομές δεδομένων" + +#: src/ownership/lifetimes-data-structures.md:3 +#, fuzzy +msgid "" +"If a data type stores borrowed data, it must be annotated with a lifetime:" +msgstr "" +"Εάν ένας τύπος δεδομένων αποθηκεύει δανεισμένα δεδομένα, πρέπει να " +"σχολιάζεται με μια διάρκεια ζωής:" + +#: src/ownership/lifetimes-data-structures.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Highlight<'doc>(&'doc str);\n" +"\n" +"fn erase(text: String) {\n" +" println!(\"Bye {text}!\");\n" +"}\n" +"\n" +"fn main() {\n" +" let text = String::from(\"The quick brown fox jumps over the lazy dog." +"\");\n" +" let fox = Highlight(&text[4..19]);\n" +" let dog = Highlight(&text[35..43]);\n" +" // erase(text);\n" +" println!(\"{fox:?}\");\n" +" println!(\"{dog:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:25 +#, fuzzy +msgid "" +"* In the above example, the annotation on `Highlight` enforces that the data " +"underlying the contained `&str` lives at least as long as any instance of " +"`Highlight` that uses that data.\n" +"* If `text` is consumed before the end of the lifetime of `fox` (or `dog`), " +"the borrow checker throws an error.\n" +"* Types with borrowed data force users to hold on to the original data. This " +"can be useful for creating lightweight views, but it generally makes them " +"somewhat harder to use.\n" +"* When possible, make data structures own their data directly.\n" +"* Some structs with multiple references inside can have more than one " +"lifetime annotation. This can be necessary if there is a need to describe " +"lifetime relationships between the references themselves, in addition to the " +"lifetime of the struct itself. Those are very advanced use cases." +msgstr "" +"* Στο παραπάνω παράδειγμα, ο σχολιασμός στο \"Highlight\" επιβάλλει ότι τα " +"δεδομένα που βρίσκονται κάτω από το περιεχόμενο \"&str\" ζουν τουλάχιστον " +"για όσο χρονικό διάστημα οποιοδήποτε στιγμιότυπο του \"Highlight\" που " +"χρησιμοποιεί αυτά τα δεδομένα.\n" +"* Εάν το «κείμενο» καταναλωθεί πριν από το τέλος της διάρκειας ζωής του " +"«αλεπού» (ή του «σκύλου»), ο ελεγκτής δανείου κάνει ένα σφάλμα.\n" +"* Οι τύποι με δανεικά δεδομένα αναγκάζουν τους χρήστες να παραμείνουν στα " +"αρχικά δεδομένα. Αυτό μπορεί να είναι χρήσιμο για τη δημιουργία ελαφριών " +"προβολών, αλλά γενικά τις καθιστά κάπως πιο δύσκολες στη χρήση.\n" +"* Όταν είναι δυνατόν, κάντε τις δομές δεδομένων να κατέχουν απευθείας τα " +"δεδομένα τους.\n" +"* Ορισμένες δομές με πολλαπλές αναφορές στο εσωτερικό μπορεί να έχουν " +"περισσότερους από έναν σχολιασμούς διάρκειας ζωής. Αυτό μπορεί να είναι " +"απαραίτητο εάν υπάρχει ανάγκη να περιγραφούν σχέσεις διάρκειας ζωής μεταξύ " +"των ίδιων των αναφορών, επιπλέον της διάρκειας ζωής της ίδιας της δομής. " +"Είναι πολύ προηγμένες περιπτώσεις χρήσης.\n" +"" + +#: src/exercises/day-1/afternoon.md:1 +#, fuzzy +msgid "# Day 1: Afternoon Exercises" +msgstr "# Ημέρα 1: Απογευματινές Ασκήσεις" + +#: src/exercises/day-1/afternoon.md:3 +#, fuzzy +msgid "We will look at two things:" +msgstr "Θα δούμε δύο πράγματα:" + +#: src/exercises/day-1/afternoon.md:5 +#, fuzzy +msgid "" +"* A small book library,\n" +"\n" +"* Iterators and ownership (hard)." +msgstr "* Iterators και ιδιοκτησία (σκληρό)." + +#: src/exercises/day-1/book-library.md:1 +#, fuzzy +msgid "# Designing a Library" +msgstr "# Σχεδιάζοντας μια Βιβλιοθήκη" + +#: src/exercises/day-1/book-library.md:3 +#, fuzzy +msgid "" +"We will learn much more about structs and the `Vec` type tomorrow. For " +"now,\n" +"you just need to know part of its API:" +msgstr "" +"Θα μάθουμε πολλά περισσότερα για τις δομές και τον τύπο `Vec` αύριο. Προς " +"το παρόν,\n" +"απλά πρέπει να γνωρίζετε μέρος του API του:" + +#: src/exercises/day-1/book-library.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut vec = vec![10, 20];\n" +" vec.push(30);\n" +" println!(\"middle value: {}\", vec[vec.len() / 2]);\n" +" for item in vec.iter() {\n" +" println!(\"item: {item}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:17 +#, fuzzy +msgid "" +"Use this to create a library application. Copy the code below to\n" +" and update the types to make it compile:" +msgstr "" +"Χρησιμοποιήστε αυτό για να δημιουργήσετε μια εφαρμογή βιβλιοθήκης. " +"Αντιγράψτε τον παρακάτω κωδικό στο\n" +" και ενημερώστε τους τύπους για να γίνει " +"μεταγλώττιση:" + +#: src/exercises/day-1/book-library.md:20 +msgid "" +"```rust,should_panic\n" +"\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// 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" +"impl Library {\n" +" fn new() -> Library {\n" +" unimplemented!()\n" +" }\n" +"\n" +" //fn len(self) -> usize {\n" +" // unimplemented!()\n" +" //}\n" +"\n" +" //fn is_empty(self) -> bool {\n" +" // unimplemented!()\n" +" //}\n" +"\n" +" //fn add_book(self, book: Book) {\n" +" // unimplemented!()\n" +" //}\n" +"\n" +" //fn print_books(self) {\n" +" // unimplemented!()\n" +" //}\n" +"\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // unimplemented!()\n" +" //}\n" +"}\n" +"\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();\n" +"\n" +" //println!(\"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" +" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " +"1865));\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" +" //}\n" +" //\n" +" //println!(\"Our library has {} books\", library.len());\n" +" for book in library.books {\n" +" println!(\"{book}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:104 +#, fuzzy +msgid "[Solution](solutions-afternoon.md#designing-a-library)" +msgstr "" +"<λεπτομέρειες>\n" +" \n" +"[Λύση](solutions-afternoon.md#designing-a-library)" + +#: src/exercises/day-1/iterators-and-ownership.md:1 +#, fuzzy +msgid "# Iterators and Ownership" +msgstr "# Επαναληπτικοί και ιδιοκτησία" + +#: src/exercises/day-1/iterators-and-ownership.md:3 +#, fuzzy +msgid "" +"The ownership model of Rust affects many APIs. An example of this is the\n" +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and\n" +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator." +"html)\n" +"traits." +msgstr "" +"Το μοντέλο ιδιοκτησίας του Rust επηρεάζει πολλά API. Ένα παράδειγμα αυτού " +"είναι το\n" +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) και\n" +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator." +"html)\n" +"χαρακτηριστικά." + +#: src/exercises/day-1/iterators-and-ownership.md:8 +#, fuzzy +msgid "## `Iterator`" +msgstr "## «Iterator»." + +#: src/exercises/day-1/iterators-and-ownership.md:10 +#, fuzzy +msgid "" +"Traits are like interfaces: they describe behavior (methods) for a type. " +"The\n" +"`Iterator` trait simply says that you can call `next` until you get `None` " +"back:" +msgstr "" +"Τα γνωρίσματα είναι σαν διεπαφές: περιγράφουν τη συμπεριφορά (μέθοδοι) για " +"έναν τύπο. ο\n" +"Το χαρακτηριστικό «Iterator» λέει απλώς ότι μπορείτε να καλέσετε «επόμενο» " +"μέχρι να λάβετε πίσω το «Κανένα»:" + +#: src/exercises/day-1/iterators-and-ownership.md:13 +msgid "" +"```rust\n" +"pub trait Iterator {\n" +" type Item;\n" +" fn next(&mut self) -> Option;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:20 +#, fuzzy +msgid "You use this trait like this:" +msgstr "Χρησιμοποιείτε αυτό το χαρακτηριστικό ως εξής:" + +#: src/exercises/day-1/iterators-and-ownership.md:22 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" println!(\"v[0]: {:?}\", iter.next());\n" +" println!(\"v[1]: {:?}\", iter.next());\n" +" println!(\"v[2]: {:?}\", iter.next());\n" +" println!(\"No more items: {:?}\", iter.next());\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:34 +#, fuzzy +msgid "What is the type returned by the iterator? Test your answer here:" +msgstr "" +"Ποιος είναι ο τύπος που επιστρέφει ο επαναλήπτης; Δοκιμάστε την απάντησή σας " +"εδώ:" + +#: src/exercises/day-1/iterators-and-ownership.md:36 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:46 +#, fuzzy +msgid "Why is this type used?" +msgstr "Γιατί χρησιμοποιείται αυτός ο τύπος;" + +#: src/exercises/day-1/iterators-and-ownership.md:48 +#, fuzzy +msgid "## `IntoIterator`" +msgstr "## «IntoIterator»." + +#: src/exercises/day-1/iterators-and-ownership.md:50 +#, fuzzy +msgid "" +"The `Iterator` trait tells you how to _iterate_ once you have created an\n" +"iterator. The related trait `IntoIterator` tells you how to create the " +"iterator:" +msgstr "" +"Το χαρακτηριστικό \"Iterator\" σάς λέει πώς να _επανάληψη_ αφού " +"δημιουργήσετε ένα\n" +"επαναλήπτης. Το σχετικό χαρακτηριστικό «IntoIterator» σάς λέει πώς να " +"δημιουργήσετε τον επαναλήπτη:" + +#: src/exercises/day-1/iterators-and-ownership.md:53 +msgid "" +"```rust\n" +"pub trait IntoIterator {\n" +" type Item;\n" +" type IntoIter: Iterator;\n" +"\n" +" fn into_iter(self) -> Self::IntoIter;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:62 +#, fuzzy +msgid "" +"The syntax here means that every implementation of `IntoIterator` must\n" +"declare two types:" +msgstr "" +"Η σύνταξη εδώ σημαίνει ότι κάθε υλοποίηση του «IntoIterator» πρέπει\n" +"Δηλώστε δύο τύπους:" + +#: src/exercises/day-1/iterators-and-ownership.md:65 +#, fuzzy +msgid "" +"* `Item`: the type we iterate over, such as `i8`,\n" +"* `IntoIter`: the `Iterator` type returned by the `into_iter` method." +msgstr "" +"* \"Στοιχείο\": ο τύπος που επαναλαμβάνουμε, όπως \"i8\",\n" +"* «IntoIter»: ο τύπος «Iterator» που επιστρέφεται με τη μέθοδο «into_iter»." + +#: src/exercises/day-1/iterators-and-ownership.md:68 +#, fuzzy +msgid "" +"Note that `IntoIter` and `Item` are linked: the iterator must have the same\n" +"`Item` type, which means that it returns `Option`" +msgstr "" +"Σημειώστε ότι το \"IntoIter\" και το \"Item\" είναι συνδεδεμένα: ο " +"επαναλήπτης πρέπει να έχει το ίδιο\n" +"Τύπος «Στοιχείο», που σημαίνει ότι επιστρέφει «Επιλογή<Στοιχείο>»." + +#: src/exercises/day-1/iterators-and-ownership.md:71 +#, fuzzy +msgid "Like before, what is the type returned by the iterator?" +msgstr "Όπως και πριν, ποιος είναι ο τύπος που επιστρέφει ο επαναλήπτης;" + +#: src/exercises/day-1/iterators-and-ownership.md:73 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::" +"from(\"bar\")];\n" +" let mut iter = v.into_iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:83 +#, fuzzy +msgid "## `for` Loops" +msgstr "## Βρόχοι «για»." + +#: src/exercises/day-1/iterators-and-ownership.md:85 +#, fuzzy +msgid "" +"Now that we know both `Iterator` and `IntoIterator`, we can build `for` " +"loops.\n" +"They call `into_iter()` on an expression and iterates over the resulting\n" +"iterator:" +msgstr "" +"Τώρα που γνωρίζουμε και τα δύο \"Iterator\" και \"IntoIterator\", μπορούμε " +"να δημιουργήσουμε βρόχους \"for\".\n" +"Καλούν «into_iter()» σε μια έκφραση και επαναλαμβάνεται πάνω από το " +"αποτέλεσμα\n" +"επαναλήπτης:" + +#: src/exercises/day-1/iterators-and-ownership.md:89 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::" +"from(\"bar\")];\n" +"\n" +" for word in &v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"\n" +" for word in v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:103 +#, fuzzy +msgid "What is the type of `word` in each loop?" +msgstr "Ποιος είναι ο τύπος της λέξης σε κάθε βρόχο;" + +#: src/exercises/day-1/iterators-and-ownership.md:105 +#, fuzzy +msgid "" +"Experiment with the code above and then consult the documentation for " +"[`impl\n" +"IntoIterator for\n" +"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-" +"IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E)\n" +"and [`impl IntoIterator for\n" +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-" +"for-Vec%3CT%2C%20A%3E)\n" +"to check your answers." +msgstr "" +"Πειραματιστείτε με τον παραπάνω κώδικα και, στη συνέχεια, συμβουλευτείτε την " +"τεκμηρίωση για [`impl\n" +"IntoIterator για\n" +"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-" +"IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E)\n" +"και [`impl IntoIterator for\n" +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-" +"for-Vec%3CT%2C%20A%3E)\n" +"για να ελέγξετε τις απαντήσεις σας." + +#: src/welcome-day-2.md:1 +#, fuzzy +msgid "# Welcome to Day 2" +msgstr "# Καλώς ήρθατε στην Ημέρα 2" + +#: src/welcome-day-2.md:3 +#, fuzzy +msgid "Now that we have seen a fair amount of Rust, we will continue with:" +msgstr "Τώρα που είδαμε αρκετή ποσότητα Rust, θα συνεχίσουμε με:" + +#: src/welcome-day-2.md:5 +msgid "" +"* Structs, enums, methods.\n" +"\n" +"* Pattern matching: destructuring enums, structs, and arrays.\n" +"\n" +"* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, " +"and\n" +" `continue`.\n" +"\n" +"* The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, " +"`Rc`\n" +" and `Arc`.\n" +"\n" +"* Modules: visibility, paths, and filesystem hierarchy." +msgstr "" + +#: src/structs.md:1 +#, fuzzy +msgid "# Structs" +msgstr "# Κατασκευές" + +#: src/structs.md:3 +#, fuzzy +msgid "Like C and C++, Rust has support for custom structs:" +msgstr "Όπως η C και η C++, η Rust υποστηρίζει προσαρμοσμένες δομές:" + +#: src/structs.md:5 +msgid "" +"```rust,editable\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" peter.age = 28;\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" let jackie = Person {\n" +" name: String::from(\"Jackie\"),\n" +" ..peter\n" +" };\n" +" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" +"}\n" +"```" +msgstr "" + +#: src/structs.md:29 +#, fuzzy +msgid "" +"
\n" +"Key Points: " +msgstr "" +"<λεπτομέρειες>\n" +"Βασικά σημεία:" + +#: src/structs.md:32 +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" +" * Unlike in C++, there is no inheritance between structs.\n" +"* Methods are defined in an `impl` block, which we will see in following " +"slides.\n" +"* This may be a good time to let people know there are different types of " +"structs. \n" +" * Zero-sized structs `e.g., struct Foo;` might be used when implementing a " +"trait on some type but don’t have any data that you want to store in the " +"value itself. \n" +" * The next slide will introduce Tuple structs, used when the field names " +"are not important.\n" +"* The syntax `..peter` allows us to copy the majority of the fields from the " +"old struct without having to explicitly type it all out. It must always be " +"the last element." +msgstr "" + +#: src/structs/tuple-structs.md:1 +#, fuzzy +msgid "# Tuple Structs" +msgstr "# Πουπλές Κατασκευές" + +#: src/structs/tuple-structs.md:3 +#, fuzzy +msgid "If the field names are unimportant, you can use a tuple struct:" +msgstr "" +"Εάν τα ονόματα των πεδίων δεν είναι σημαντικά, μπορείτε να χρησιμοποιήσετε " +"μια δομή πλειάδας:" + +#: src/structs/tuple-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p = Point(17, 23);\n" +" println!(\"({}, {})\", p.0, p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:14 +#, fuzzy +msgid "This is often used for single-field wrappers (called newtypes):" +msgstr "" +"Αυτό χρησιμοποιείται συχνά για περιτυλίγματα ενός πεδίου (που ονομάζονται " +"νέοι τύποι):" + +#: src/structs/tuple-structs.md:16 +msgid "" +"```rust,editable,compile_fail\n" +"struct PoundOfForce(f64);\n" +"struct Newtons(f64);\n" +"\n" +"fn compute_thruster_force() -> PoundOfForce {\n" +" todo!(\"Ask a rocket scientist at NASA\")\n" +"}\n" +"\n" +"fn set_thruster_force(force: Newtons) {\n" +" // ...\n" +"}\n" +"\n" +"fn main() {\n" +" let force = compute_thruster_force();\n" +" set_thruster_force(force);\n" +"}\n" +"\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:37 +#, fuzzy +msgid "" +"* Newtypes are a great way to encode additional information about the value " +"in a primitive type, for example:\n" +" * The number is measured in some units: `Newtons` in the example above.\n" +" * The value passed some validation when it was created, so you no longer " +"have to validate it again at every use: 'PhoneNumber(String)` or " +"`OddNumber(u32)`.\n" +"* Demonstrate how to add a `f64` value to a `Newtons` type by accessing the " +"single field in the newtype.\n" +" * Rust generally doesn’t like inexplicit things, like automatic " +"unwrapping or for instance using booleans as integers.\n" +" * Operator overloading is discussed on Day 3 (generics). " +msgstr "" +"Οι νέοι τύποι είναι ένας πολύ καλός τρόπος για να κωδικοποιήσετε πρόσθετες " +"πληροφορίες σχετικά με την τιμή σε έναν πρωτόγονο τύπο, για παράδειγμα:\n" +" * Ο αριθμός μετριέται σε ορισμένες μονάδες: «Newtons» στο παραπάνω " +"παράδειγμα.\n" +" * Η τιμή πέρασε κάποια επικύρωση όταν δημιουργήθηκε, επομένως δεν " +"χρειάζεται πλέον να την επικυρώνετε ξανά σε κάθε χρήση: " +"«PhoneNumber(String)» ή «OddNumber(u32)».\n" +" \n" +"
" + +#: src/structs/field-shorthand.md:1 +#, fuzzy +msgid "# Field Shorthand Syntax" +msgstr "# Σύντομη σύνταξη πεδίου" + +#: src/structs/field-shorthand.md:3 +#, fuzzy +msgid "" +"If you already have variables with the right names, then you can create the\n" +"struct using a shorthand:" +msgstr "" +"Εάν έχετε ήδη μεταβλητές με τα σωστά ονόματα, τότε μπορείτε να δημιουργήσετε " +"τις\n" +"δόμηση χρησιμοποιώντας συντομογραφία:" + +#: src/structs/field-shorthand.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn new(name: String, age: u8) -> Person {\n" +" Person { name, age }\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person::new(String::from(\"Peter\"), 27);\n" +" println!(\"{peter:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/structs/field-shorthand.md:27 +msgid "" +"* The `new` function could be written using `Self` as a type, as it is " +"interchangeable with the struct type name\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Person {\n" +" fn new(name: String, age: u8) -> Self {\n" +" Self { name, age }\n" +" }\n" +" }\n" +" ``` \n" +"* Implement the `Default` trait for the struct. Define some fields and use " +"the default values for the other fields.\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Default for Person {\n" +" fn default() -> Person {\n" +" Person {\n" +" name: \"Bot\".to_string(),\n" +" age: 0,\n" +" }\n" +" }\n" +" }\n" +" fn create_default() {\n" +" let tmp = Person {\n" +" ..Default::default()\n" +" };\n" +" let tmp = Person {\n" +" name: \"Sam\".to_string(),\n" +" ..Default::default()\n" +" };\n" +" }\n" +" ```\n" +"\n" +"* Methods are defined in the `impl` block.\n" +"* Use struct update syntax to define a new structure using `peter`. Note " +"that the variable `peter` will no longer be accessible afterwards.\n" +"* Use `{:#?}` when printing structs to request the `Debug` representation." +msgstr "" + +#: src/enums.md:1 +#, fuzzy +msgid "# Enums" +msgstr "# Αριθμοί" + +#: src/enums.md:3 +#, fuzzy +msgid "" +"The `enum` keyword allows the creation of a type which has a few\n" +"different variants:" +msgstr "" +"Η λέξη-κλειδί «enum» επιτρέπει τη δημιουργία ενός τύπου που έχει λίγους\n" +"διαφορετικές παραλλαγές:" + +#: src/enums.md:6 +msgid "" +"```rust,editable\n" +"fn generate_random_number() -> i32 {\n" +" 4 // Chosen by fair dice roll. Guaranteed to be random.\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"enum CoinFlip {\n" +" Heads,\n" +" Tails,\n" +"}\n" +"\n" +"fn flip_coin() -> CoinFlip {\n" +" let random_number = generate_random_number();\n" +" if random_number % 2 == 0 {\n" +" return CoinFlip::Heads;\n" +" } else {\n" +" return CoinFlip::Tails;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"You got: {:?}\", flip_coin());\n" +"}\n" +"```" +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 "Βασικά σημεία:" + +#: src/enums.md:35 +#, fuzzy +msgid "" +"* Enumerations allow you to collect a set of values under one type\n" +"* This page offers an enum type `CoinFlip` with two variants `Heads` and " +"`Tail`. You might note the namespace when using variants.\n" +"* This might be a good time to compare Structs and Enums:\n" +" * In both, you can have a simple version without fields (unit struct) or " +"one with different types of fields (variant payloads). \n" +" * In both, associated functions are defined within an `impl` block.\n" +" * You could even implement the different variants of an enum with separate " +"structs but then they wouldn’t be the same type as they would if they were " +"all defined in an enum. " +msgstr "" +"* Οι απαριθμήσεις σάς επιτρέπουν να συλλέγετε ένα σύνολο τιμών κάτω από έναν " +"τύπο\n" +"* Αυτή η σελίδα προσφέρει έναν τύπο \"CoinFlip\" με δύο παραλλαγές \"Heads\" " +"και \"Tail\". Μπορείτε να σημειώσετε τον χώρο ονομάτων όταν χρησιμοποιείτε " +"παραλλαγές.\n" +"* Αυτή μπορεί να είναι μια καλή στιγμή για να συγκρίνετε Structs και Enums:\n" +" * Και στα δύο, μπορείτε να έχετε μια απλή έκδοση χωρίς πεδία (μονάδα " +"δομής) ή μια με διαφορετικούς τύπους πεδίων (ωφέλιμα φορτία παραλλαγής).\n" +" * Και στις δύο, οι συσχετισμένες συναρτήσεις ορίζονται μέσα σε ένα μπλοκ " +"«impl».\n" +" * Θα μπορούσατε ακόμη και να εφαρμόσετε τις διαφορετικές παραλλαγές ενός " +"enum με ξεχωριστές δομές, αλλά τότε δεν θα ήταν του ίδιου τύπου όπως θα ήταν " +"αν είχαν οριστεί όλες σε ένα enum.\n" +"" + +#: src/enums/variant-payloads.md:1 +#, fuzzy +msgid "# Variant Payloads" +msgstr "# Παραλλαγή ωφέλιμων φορτίων" + +#: src/enums/variant-payloads.md:3 +#, fuzzy +msgid "" +"You can define richer enums where the variants carry data. You can then use " +"the\n" +"`match` statement to extract the data from each variant:" +msgstr "" +"Μπορείτε να ορίσετε πλουσιότερους αριθμούς όπου οι παραλλαγές μεταφέρουν " +"δεδομένα. Στη συνέχεια, μπορείτε να χρησιμοποιήσετε το\n" +"Δήλωση «ταιριάσματος» για εξαγωγή των δεδομένων από κάθε παραλλαγή:" + +#: src/enums/variant-payloads.md:6 +msgid "" +"```rust,editable\n" +"enum WebEvent {\n" +" PageLoad, // Variant without payload\n" +" KeyPress(char), // Tuple struct variant\n" +" Click { x: i64, y: i64 }, // Full struct variant\n" +"}\n" +"\n" +"#[rustfmt::skip]\n" +"fn inspect(event: WebEvent) {\n" +" match event {\n" +" WebEvent::PageLoad => println!(\"page loaded\"),\n" +" WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" +" WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let load = WebEvent::PageLoad;\n" +" let press = WebEvent::KeyPress('x');\n" +" let click = WebEvent::Click { x: 20, y: 80 };\n" +"\n" +" inspect(load);\n" +" inspect(press);\n" +" inspect(click);\n" +"}\n" +"```" +msgstr "" + +#: src/enums/variant-payloads.md:35 +#, fuzzy +msgid "" +"* The values in the enum variants can only be accessed after being pattern " +"matched. The pattern binds references to the fields in the \"match arm\" " +"after the `=>`.\n" +" * The expression is matched against the patterns from top to bottom. There " +"is no fall-through like in C or C++.\n" +" * The match expression has a value. The value is the last expression in " +"the match arm which was executed.\n" +" * Starting from the top we look for what pattern matches the value then " +"run the code following the arrow. Once we find a match, we stop. \n" +"* Demonstrate what happens when the search is inexhaustive. Note the " +"advantage the Rust compiler provides by confirming when all cases are " +"handled. \n" +"* `match` inspects a hidden discriminant field in the `enum`.\n" +"* It is possible to retrieve the discriminant by calling `std::mem::" +"discriminant()`\n" +" * This is useful, for example, if implementing `PartialEq` for structs " +"where comparing field values doesn't affect equality.\n" +"* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::" +"Click(Click)` with a top level `struct Click { ... }`. The inlined version " +"cannot implement traits, for example. \n" +" " +msgstr "" +"* Στο παραπάνω παράδειγμα, η πρόσβαση στο \"char\" στο \"KeyPress\" ή στο " +"\"x\" και \"y\" στο \"Click\" λειτουργεί μόνο μέσα σε μια δήλωση " +"\"ταιριάζουν\".\n" +"* Το \"match\" επιθεωρεί ένα κρυφό πεδίο διάκρισης στο \"enum\".\n" +"* Το \"WebEvent::Click { ... }\" δεν είναι ακριβώς το ίδιο με το \"WebEvent::" +"Click(Click)\" με ένα ανώτερο επίπεδο \"struct Click { ... }\". Η " +"ενσωματωμένη έκδοση δεν μπορεί να εφαρμόσει χαρακτηριστικά, για παράδειγμα." + +#: src/enums/sizes.md:1 +#, fuzzy +msgid "# Enum Sizes" +msgstr "# Αριθμητικά μεγέθη" + +#: src/enums/sizes.md:3 +#, fuzzy +msgid "" +"Rust enums are packed tightly, taking constraints due to alignment into " +"account:" +msgstr "" +"Οι σκουριές συσκευάζονται σφιχτά, λαμβάνοντας υπόψη τους περιορισμούς λόγω " +"ευθυγράμμισης:" + +#: src/enums/sizes.md:5 +msgid "" +"```rust,editable\n" +"use std::mem::{align_of, size_of};\n" +"\n" +"macro_rules! dbg_size {\n" +" ($t:ty) => {\n" +" println!(\"{}: size {} bytes, align: {} bytes\",\n" +" stringify!($t), size_of::<$t>(), align_of::<$t>());\n" +" };\n" +"}\n" +"\n" +"enum Foo {\n" +" A,\n" +" B,\n" +"}\n" +"\n" +"fn main() {\n" +" dbg_size!(Foo);\n" +"}\n" +"```" +msgstr "" + +#: src/enums/sizes.md:25 +#, fuzzy +msgid "" +"* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout." +"html)." +msgstr "" +"* Δείτε το [Rust Reference](https://doc.rust-lang.org/reference/type-layout." +"html)." + +#: src/enums/sizes.md:31 +msgid "" +" * Internally Rust is using a field (discriminant) to keep track of the enum " +"variant.\n" +"\n" +" * You can control the discriminant if needed (e.g., for compatibility with " +"C):\n" +" \n" +" ```rust,editable\n" +" #[repr(u32)]\n" +" enum Bar {\n" +" A, // 0\n" +" B = 10000,\n" +" C, // 10001\n" +" }\n" +" \n" +" fn main() {\n" +" println!(\"A: {}\", Bar::A as u32);\n" +" println!(\"B: {}\", Bar::B as u32);\n" +" println!(\"C: {}\", Bar::C as u32);\n" +" }\n" +" ```\n" +"\n" +" Without `repr`, the discriminant type takes 2 bytes, because 10001 fits " +"2\n" +" bytes.\n" +"\n" +"\n" +" * Try out other types such as\n" +" \n" +" * `dbg_size!(bool)`: size 1 bytes, align: 1 bytes,\n" +" * `dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche " +"optimization, see below),\n" +" * `dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit " +"machine),\n" +" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer " +"optimization, see below).\n" +"\n" +" * Niche optimization: Rust will merge use unused bit patterns for the enum\n" +" discriminant.\n" +"\n" +" * Null pointer optimization: For [some\n" +" types](https://doc.rust-lang.org/std/option/#representation), Rust " +"guarantees\n" +" that `size_of::()` equals `size_of::>()`.\n" +"\n" +" Example code if you want to show how the bitwise representation *may* " +"look like in practice.\n" +" It's important to note that the compiler provides no guarantees " +"regarding this representation, therefore this is totally unsafe.\n" +"\n" +" ```rust,editable\n" +" use std::mem::transmute;\n" +"\n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, " +"$bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" println!(\"Bitwise representation of bool\");\n" +" dbg_bits!(false, u8);\n" +" dbg_bits!(true, u8);\n" +"\n" +" println!(\"Bitwise representation of Option\");\n" +" dbg_bits!(None::, u8);\n" +" dbg_bits!(Some(false), u8);\n" +" dbg_bits!(Some(true), u8);\n" +"\n" +" println!(\"Bitwise representation of Option>\");\n" +" dbg_bits!(Some(Some(false)), u8);\n" +" dbg_bits!(Some(Some(true)), u8);\n" +" dbg_bits!(Some(None::), u8);\n" +" dbg_bits!(None::>, u8);\n" +"\n" +" println!(\"Bitwise representation of Option<&i32>\");\n" +" dbg_bits!(None::<&i32>, usize);\n" +" dbg_bits!(Some(&0i32), usize);\n" +" }\n" +" }\n" +" ```\n" +"\n" +" More complex example if you want to discuss what happens when we chain " +"more than 256 `Option`s together.\n" +"\n" +" ```rust,editable\n" +" #![recursion_limit = \"1000\"]\n" +"\n" +" use std::mem::transmute;\n" +" \n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, " +"$bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" // Macro to wrap a value in 2^n Some() where n is the number of \"@\" " +"signs.\n" +" // Increasing the recursion limit is required to evaluate this macro.\n" +" macro_rules! many_options {\n" +" ($value:expr) => { Some($value) };\n" +" ($value:expr, @) => {\n" +" Some(Some($value))\n" +" };\n" +" ($value:expr, @ $($more:tt)+) => {\n" +" many_options!(many_options!($value, $($more)+), $($more)+)\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" assert_eq!(many_options!(false), Some(false));\n" +" assert_eq!(many_options!(false, @), Some(Some(false)));\n" +" assert_eq!(many_options!(false, @@), " +"Some(Some(Some(Some(false)))));\n" +"\n" +" println!(\"Bitwise representation of a chain of 128 Option's." +"\");\n" +" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" +" dbg_bits!(many_options!(true, @@@@@@@), u8);\n" +"\n" +" println!(\"Bitwise representation of a chain of 256 Option's." +"\");\n" +" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(true, @@@@@@@@), u16);\n" +"\n" +" println!(\"Bitwise representation of a chain of 257 Option's." +"\");\n" +" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" +" }\n" +" }\n" +" ```" +msgstr "" + +#: src/methods.md:3 +#, fuzzy +msgid "" +"Rust allows you to associate functions with your new types. You do this with " +"an\n" +"`impl` block:" +msgstr "" +"Το Rust σάς επιτρέπει να συσχετίζετε λειτουργίες με τους νέους τύπους σας. " +"Το κάνετε αυτό με ένα\n" +"μπλοκ \"impl\":" + +#: src/methods.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn say_hello(&self) {\n" +" println!(\"Hello, my name is {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" peter.say_hello();\n" +"}\n" +"```" +msgstr "" + +#: src/methods.md:31 +#, fuzzy +msgid "" +"* It can be helpful to introduce methods by comparing them to functions.\n" +" * Methods are called on an instance of a type (such as a struct or enum), " +"the first parameter represents the instance as `self`.\n" +" * Developers may choose to use methods to take advantage of method " +"receiver syntax and to help keep them more organized. By using methods we " +"can keep all the implementation code in one predictable place.\n" +"* Point out the use of the keyword `self`, a method receiver. \n" +" * Show that it is an abbreviated term for `self:&Self` and perhaps show " +"how the struct name could also be used. \n" +" * Explain that `Self` is a type alias for the type the `impl` block is in " +"and can be used elsewhere in the block.\n" +" * Note how `self` is used like other structs and dot notation can be used " +"to refer to individual fields.\n" +" * This might be a good time to demonstrate how the `&self` differs from " +"`self` by modifying the code and trying to run say_hello twice. \n" +"* We describe the distinction between method receivers next.\n" +" " +msgstr "" +"Βασικά σημεία:\n" +"* Μπορεί να είναι χρήσιμη η εισαγωγή μεθόδων συγκρίνοντάς τες με " +"συναρτήσεις.\n" +" * Οι μέθοδοι καλούνται σε μια παρουσία ενός τύπου (όπως μια δομή ή ένα " +"enum), η πρώτη παράμετρος αντιπροσωπεύει την παρουσία ως \"self\".\n" +" * Οι προγραμματιστές μπορούν να επιλέξουν να χρησιμοποιήσουν μεθόδους για " +"να επωφεληθούν από τη σύνταξη του δέκτη μεθόδων και να τους βοηθήσουν να " +"διατηρηθούν πιο οργανωμένοι. Χρησιμοποιώντας μεθόδους μπορούμε να " +"διατηρήσουμε όλο τον κώδικα υλοποίησης σε ένα προβλέψιμο μέρος.\n" +"* Επισημάνετε τη χρήση της λέξης-κλειδιού «self», ενός δέκτη μεθόδου.\n" +" * Δείξτε ότι είναι ένας συντομευμένος όρος για το \"self:&Self\" και ίσως " +"δείξετε πώς θα μπορούσε επίσης να χρησιμοποιηθεί το όνομα της δομής.\n" +" * Εξηγήστε ότι το Self είναι ένα ψευδώνυμο τύπου για τον τύπο στον οποίο " +"βρίσκεται το μπλοκ «impl» και μπορεί να χρησιμοποιηθεί αλλού στο μπλοκ.\n" +" * Σημειώστε πώς χρησιμοποιείται ο εαυτός όπως και άλλες δομές και ο " +"συμβολισμός κουκκίδων μπορεί να χρησιμοποιηθεί για αναφορά σε μεμονωμένα " +"πεδία.\n" +" * Αυτή μπορεί να είναι μια καλή στιγμή για να δείξετε πώς το \"&self\" " +"διαφέρει από το \"self\" τροποποιώντας τον κώδικα και προσπαθώντας να " +"εκτελέσετε το say_hello δύο φορές.\n" +"* Στη συνέχεια περιγράφουμε τη διάκριση μεταξύ των δεκτών μεθόδων.\n" +" \n" +"" + +#: src/methods/receiver.md:1 +#, fuzzy +msgid "# Method Receiver" +msgstr "# Μέθοδος Δέκτης" + +#: src/methods/receiver.md:3 +#, fuzzy +msgid "" +"The `&self` above indicates that the method borrows the object immutably. " +"There\n" +"are other possible receivers for a method:" +msgstr "" +"Το \"&self\" παραπάνω υποδεικνύει ότι η μέθοδος δανείζεται το αντικείμενο " +"αμετάβλητα. Εκεί\n" +"είναι άλλοι πιθανοί δέκτες για μια μέθοδο:" + +#: src/methods/receiver.md:6 +#, fuzzy +msgid "" +"* `&self`: borrows the object from the caller using a shared and immutable\n" +" reference. The object can be used again afterwards.\n" +"* `&mut self`: borrows the object from the caller using a unique and " +"mutable\n" +" reference. The object can be used again afterwards.\n" +"* `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" +"* No receiver: this becomes a static method on the struct. Typically used " +"to\n" +" create constructors which are called `new` by convention." +msgstr "" +"* «&self»: δανείζεται το αντικείμενο από τον καλούντα χρησιμοποιώντας ένα " +"κοινόχρηστο και αμετάβλητο\n" +" αναφορά. Το αντικείμενο μπορεί να χρησιμοποιηθεί ξανά μετά.\n" +"* \"&mut self\": δανείζεται το αντικείμενο από τον καλούντα χρησιμοποιώντας " +"ένα μοναδικό και ευμετάβλητο\n" +" αναφορά. Το αντικείμενο μπορεί να χρησιμοποιηθεί ξανά μετά.\n" +"* «self»: αναλαμβάνει την κυριότητα του αντικειμένου και το απομακρύνει από " +"τον καλούντα. ο\n" +" μέθοδος γίνεται ο ιδιοκτήτης του αντικειμένου. Το αντικείμενο θα " +"απορριφθεί (κατανεμηθεί)\n" +" όταν η μέθοδος επιστρέφει, εκτός εάν η ιδιοκτησία της είναι ρητά\n" +" μεταδόθηκε.\n" +"* `mut self`: όπως παραπάνω, αλλά ενώ η μέθοδος κατέχει το αντικείμενο, " +"μπορεί\n" +" μεταλλάξτε το και εσείς. Η πλήρης ιδιοκτησία δεν σημαίνει αυτόματα " +"μεταβλητότητα.\n" +"* Χωρίς δέκτη: αυτό γίνεται μια στατική μέθοδος στη δομή. Συνήθως " +"χρησιμοποιείται σε\n" +" δημιουργήστε κατασκευαστές που ονομάζονται «νέοι» κατά σύμβαση." + +#: src/methods/receiver.md:19 +#, fuzzy +msgid "" +"Beyond variants on `self`, there are also\n" +"[special wrapper types](https://doc.rust-lang.org/reference/special-types-" +"and-traits.html)\n" +"allowed to be receiver types, such as `Box`." +msgstr "" +"Πέρα από παραλλαγές στον «εαυτό», υπάρχουν επίσης\n" +"[ειδικοί τύποι περιτυλίγματος](https://doc.rust-lang.org/reference/special-" +"types-and-traits.html)\n" +"επιτρέπεται να είναι τύποι δεκτών, όπως \"Box\"." + +#: src/methods/receiver.md:25 +#, fuzzy +msgid "" +"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". " +"These constraints always come\n" +"together in Rust due to borrow checker rules, and `self` is no exception. It " +"isn't possible to\n" +"reference a struct from multiple locations and call a mutating (`&mut self`) " +"method on it." +msgstr "" +"<λεπτομέρειες>\n" +" \n" +"Εξετάστε το ενδεχόμενο να δώσετε έμφαση στο \"κοινόχρηστο και αμετάβλητο\" " +"και στο \"μοναδικό και μεταβλητό\". Αυτοί οι περιορισμοί έρχονται πάντα\n" +"μαζί στο Rust λόγω των κανόνων του ελεγκτή δανείου, και το \"self\" δεν " +"αποτελεί εξαίρεση. Δεν θα είναι δυνατόν\n" +"Αναφέρετε μια δομή από πολλές τοποθεσίες και καλέστε μια μέθοδο μεταλλάξεως " +"(`&mut self`) σε αυτήν.\n" +" \n" +"" + +#: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 +#, fuzzy +msgid "# Example" +msgstr "# Παράδειγμα" + +#: src/methods/example.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Race {\n" +" name: String,\n" +" laps: Vec,\n" +"}\n" +"\n" +"impl Race {\n" +" fn new(name: &str) -> Race { // No receiver, a static method\n" +" Race { name: String::from(name), laps: Vec::new() }\n" +" }\n" +"\n" +" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write " +"access to self\n" +" self.laps.push(lap);\n" +" }\n" +"\n" +" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" +" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" +" for (idx, lap) in self.laps.iter().enumerate() {\n" +" println!(\"Lap {idx}: {lap} sec\");\n" +" }\n" +" }\n" +"\n" +" fn finish(self) { // Exclusive ownership of self\n" +" let total = self.laps.iter().sum::();\n" +" println!(\"Race {} is finished, total lap time: {}\", self.name, " +"total);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut race = Race::new(\"Monaco Grand Prix\");\n" +" race.add_lap(70);\n" +" race.add_lap(68);\n" +" race.print_laps();\n" +" race.add_lap(71);\n" +" race.print_laps();\n" +" race.finish();\n" +" // race.add_lap(42);\n" +"}\n" +"```" +msgstr "" + +#: src/methods/example.md:47 +#, fuzzy +msgid "" +"* All four methods here use a different method receiver.\n" +" * You can point out how that changes what the function can do with the " +"variable values and if/how it can be used again in `main`.\n" +" * You can showcase the error that appears when trying to call `finish` " +"twice.\n" +"* Note that although the method receivers are different, the non-static " +"functions are called the same way in the main body. Rust enables automatic " +"referencing and dereferencing when calling methods. Rust automatically adds " +"in the `&`, `*`, `muts` so that that object matches the method signature.\n" +"* You might point out that `print_laps` is using a vector that is iterated " +"over. We describe vectors in more detail in the afternoon. " +msgstr "" +"<λεπτομέρειες>\n" +" \n" +"Βασικά σημεία:\n" +"* Και οι τέσσερις μέθοδοι εδώ χρησιμοποιούν διαφορετικό δέκτη μεθόδου.\n" +" * Μπορείτε να επισημάνετε πώς αλλάζει αυτό που μπορεί να κάνει η συνάρτηση " +"με τις τιμές των μεταβλητών και εάν/πώς μπορεί να χρησιμοποιηθεί ξανά στο " +"\"main\".\n" +" * Μπορείτε να επιδείξετε το σφάλμα που εμφανίζεται όταν προσπαθείτε να " +"καλέσετε το \"finish\" δύο φορές.\n" +"* Σημειώστε ότι παρόλο που οι δέκτες της μεθόδου είναι διαφορετικοί, οι μη " +"στατικές συναρτήσεις ονομάζονται με τον ίδιο τρόπο στο κύριο σώμα. Το Rust " +"επιτρέπει την αυτόματη αναφορά και αποαναφορά κατά την κλήση μεθόδων. Το " +"Rust προσθέτει αυτόματα τα \"&\", \"*\", \"muts\", έτσι ώστε αυτό το " +"αντικείμενο να ταιριάζει με την υπογραφή της μεθόδου.\n" +"* Μπορείτε να επισημάνετε ότι το \"print_laps\" χρησιμοποιεί ένα διάνυσμα " +"που επαναλαμβάνεται. Περιγράφουμε διανύσματα με περισσότερες λεπτομέρειες το " +"απόγευμα." + +#: src/pattern-matching.md:1 +#, fuzzy +msgid "# Pattern Matching" +msgstr "# Αντιστοίχιση προτύπων" + +#: src/pattern-matching.md:3 +#, fuzzy +msgid "" +"The `match` keyword let you match a value against one or more _patterns_. " +"The\n" +"comparisons are done from top to bottom and the first match wins." +msgstr "" +"Η λέξη-κλειδί \"αντιστοιχία\" σάς επιτρέπει να αντιστοιχίσετε μια τιμή με " +"ένα ή περισσότερα _patterns_. ο\n" +"Οι συγκρίσεις γίνονται από πάνω προς τα κάτω και ο πρώτος αγώνας κερδίζει." + +#: src/pattern-matching.md:6 +#, fuzzy +msgid "The patterns can be simple values, similarly to `switch` in C and C++:" +msgstr "" +"Τα μοτίβα μπορεί να είναι απλές τιμές, παρόμοια με το «switch» σε C και C++:" + +#: src/pattern-matching.md:8 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let input = 'x';\n" +"\n" +" match input {\n" +" 'q' => println!(\"Quitting\"),\n" +" 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" +" '0'..='9' => println!(\"Number input\"),\n" +" _ => println!(\"Something else\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching.md:21 +#, fuzzy +msgid "The `_` pattern is a wildcard pattern which matches any value." +msgstr "" +"Το μοτίβο `_` είναι ένα μοτίβο μπαλαντέρ που ταιριάζει με οποιαδήποτε τιμή." + +#: src/pattern-matching.md:26 +#, fuzzy +msgid "" +"* You might point out how some specific characters are being used when in a " +"pattern\n" +" * `|` as an `or`\n" +" * `..` can expand as much as it needs to be\n" +" * `1..=5` represents an inclusive range\n" +" * `_` is a wild card\n" +"* It can be useful to show how binding works, by for instance replacing a " +"wildcard character with a variable, or removing the quotes around `q`.\n" +"* You can demonstrate matching on a reference.\n" +"* This might be a good time to bring up the concept of irrefutable patterns, " +"as the term can show up in error messages.\n" +" " +msgstr "" +"<λεπτομέρειες>\n" +" \n" +"Βασικά σημεία:\n" +"* Θα μπορούσατε να επισημάνετε πώς χρησιμοποιούνται ορισμένοι συγκεκριμένοι " +"χαρακτήρες όταν βρίσκονται σε ένα δίπλωμα ευρεσιτεχνίας\n" +" * «|» ως «ή».\n" +" * Το «..» μπορεί να επεκταθεί όσο χρειάζεται\n" +" * Το \"1..=5\" αντιπροσωπεύει ένα εύρος που περιλαμβάνει\n" +" * Το `_` είναι μπαλαντέρ\n" +"* Μπορεί να είναι χρήσιμο να δείξετε πώς λειτουργεί το δεσμευτικό, για " +"παράδειγμα αντικαθιστώντας έναν χαρακτήρα μπαλαντέρ με μια μεταβλητή ή " +"αφαιρώντας τα εισαγωγικά γύρω από το `q`.\n" +"* Μπορείτε να επιδείξετε την αντιστοίχιση σε μια αναφορά.\n" +"* Αυτή μπορεί να είναι μια καλή στιγμή για να αναδείξετε την έννοια των " +"αδιαμφισβήτητων προτύπων, καθώς ο όρος μπορεί να εμφανίζεται σε μηνύματα " +"λάθους.\n" +" \n" +"" + +#: src/pattern-matching/destructuring-enums.md:1 +#, fuzzy +msgid "# Destructuring Enums" +msgstr "# Καταστροφή Αριθμών" + +#: src/pattern-matching/destructuring-enums.md:3 +#, fuzzy +msgid "" +"Patterns can also be used to bind variables to parts of your values. This is " +"how\n" +"you inspect the structure of your types. Let us start with a simple `enum` " +"type:" +msgstr "" +"Τα μοτίβα μπορούν επίσης να χρησιμοποιηθούν για τη σύνδεση μεταβλητών σε " +"μέρη των τιμών σας. Ετσι\n" +"επιθεωρείτε τη δομή των τύπων σας. Ας ξεκινήσουμε με έναν απλό τύπο «enum»:" + +#: src/pattern-matching/destructuring-enums.md:6 +msgid "" +"```rust,editable\n" +"enum Result {\n" +" Ok(i32),\n" +" Err(String),\n" +"}\n" +"\n" +"fn divide_in_two(n: i32) -> Result {\n" +" if n % 2 == 0 {\n" +" Result::Ok(n / 2)\n" +" } else {\n" +" Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let n = 100;\n" +" match divide_in_two(n) {\n" +" Result::Ok(half) => println!(\"{n} divided in two is {half}\"),\n" +" Result::Err(msg) => println!(\"sorry, an error happened: {msg}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:29 +#, fuzzy +msgid "" +"Here we have used the arms to _destructure_ the `Result` value. In the " +"first\n" +"arm, `half` is bound to the value inside the `Ok` variant. In the second " +"arm,\n" +"`msg` is bound to the error message." +msgstr "" +"Εδώ χρησιμοποιήσαμε τους βραχίονες για να _καταστρέψουμε_ την τιμή " +"\"Αποτέλεσμα\". Κατά την πρώτη\n" +"βραχίονα, το \"μισό\" είναι δεσμευμένο στην τιμή μέσα στην παραλλαγή \"Ok\". " +"Στο δεύτερο χέρι,\n" +"Το \"msg\" συνδέεται με το μήνυμα σφάλματος." + +#: src/pattern-matching/destructuring-enums.md:36 +#, fuzzy +msgid "" +"* The `if`/`else` expression is returning an enum that is later unpacked " +"with a `match`.\n" +"* You can try adding a third variant to the enum definition and displaying " +"the errors when running the code. Point out the places where your code is " +"now inexhaustive and how the compiler tries to give you hints." +msgstr "" +"Βασικά σημεία:\n" +"* Η έκφραση `if`/`else` επιστρέφει έναν αριθμό που αργότερα αποσυσκευάζεται " +"με ένα \"match\".\n" +"* Μπορείτε να δοκιμάσετε να προσθέσετε μια τρίτη παραλλαγή στον ορισμό enum " +"και να εμφανίσετε τα σφάλματα κατά την εκτέλεση του κώδικα. Επισημάνετε τα " +"σημεία όπου ο κώδικας σας είναι πλέον ανεξάντλητος και πώς ο μεταγλωττιστής " +"προσπαθεί να σας δώσει συμβουλές." + +#: src/pattern-matching/destructuring-structs.md:1 +#, fuzzy +msgid "# Destructuring Structs" +msgstr "# Κατασκευές καταστροφής" + +#: src/pattern-matching/destructuring-structs.md:3 +#, fuzzy +msgid "You can also destructure `structs`:" +msgstr "Μπορείτε επίσης να καταστρέψετε «structs»:" + +#: src/pattern-matching/destructuring-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Foo {\n" +" x: (u32, u32),\n" +" y: u32,\n" +"}\n" +"\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let foo = Foo { x: (1, 2), y: 3 };\n" +" match foo {\n" +" Foo { x: (1, b), y } => println!(\"x.0 = 1, b = {b}, y = {y}\"),\n" +" Foo { y: 2, x: i } => println!(\"y = 2, x = {i:?}\"),\n" +" Foo { y, .. } => println!(\"y = {y}, other fields were " +"ignored\"),\n" +" }\n" +"}\n" +"```" +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." +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:1 +#, fuzzy +msgid "# Destructuring Arrays" +msgstr "# Αποδιάρθρωση συστοιχιών" + +#: src/pattern-matching/destructuring-arrays.md:3 +#, fuzzy +msgid "" +"You can destructure arrays, tuples, and slices by matching on their elements:" +msgstr "" +"Μπορείτε να καταστρέψετε πίνακες, πλειάδες και φέτες ταιριάζοντας στα " +"στοιχεία τους:" + +#: src/pattern-matching/destructuring-arrays.md:5 +msgid "" +"```rust,editable\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let triple = [0, -2, 3];\n" +" println!(\"Tell me about {triple:?}\");\n" +" match triple {\n" +" [0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" [1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:21 +msgid "" +"* Destructuring of slices of unknown length also works with patterns of " +"fixed length.\n" +"\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" inspect(&[0, -2, 3]);\n" +" inspect(&[0, -2, 3, 4]);\n" +" }\n" +"\n" +" #[rustfmt::skip]\n" +" fn inspect(slice: &[i32]) {\n" +" println!(\"Tell me about {slice:?}\");\n" +" match slice {\n" +" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" &[1, ..] => println!(\"First is 1 and the rest were " +"ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +" }\n" +" ```\n" +" \n" +"* Create a new pattern using `_` to represent an element. \n" +"* Add more values to the array.\n" +"* Point out that how `..` will expand to account for different number of " +"elements.\n" +"* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`" +msgstr "" + +#: src/pattern-matching/match-guards.md:1 +#, fuzzy +msgid "# Match Guards" +msgstr "# Match Guards" + +#: src/pattern-matching/match-guards.md:3 +#, fuzzy +msgid "" +"When matching, you can add a _guard_ to a pattern. This is an arbitrary " +"Boolean\n" +"expression which will be executed if the pattern matches:" +msgstr "" +"Κατά την αντιστοίχιση, μπορείτε να προσθέσετε ένα _guard_ σε ένα μοτίβο. " +"Αυτό είναι ένα αυθαίρετο Boolean\n" +"έκφραση που θα εκτελεστεί εάν το μοτίβο ταιριάζει:" + +#: src/pattern-matching/match-guards.md:6 +msgid "" +"```rust,editable\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let pair = (2, -2);\n" +" println!(\"Tell me about {pair:?}\");\n" +" match pair {\n" +" (x, y) if x == y => println!(\"These are twins\"),\n" +" (x, y) if x + y == 0 => println!(\"Antimatter, kaboom!\"),\n" +" (x, _) if x % 2 == 1 => println!(\"The first one is odd\"),\n" +" _ => println!(\"No correlation...\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/match-guards.md:23 +#, fuzzy +msgid "" +"* Match guards as a separate syntax feature are important and necessary when " +"we wish to concisely express more complex ideas than patterns alone would " +"allow.\n" +"* They are not the same as separate `if` expression inside of the match arm. " +"An `if` expression inside of the branch block (after `=>`) happens after the " +"match arm is selected. Failing the `if` condition inside of that block won't " +"result in other arms\n" +"of the original `match` expression being considered. \n" +"* You can use the variables defined in the pattern in your if expression.\n" +"* The condition defined in the guard applies to every expression in a " +"pattern with an `|`." +msgstr "" +"Βασικά σημεία:\n" +"* Οι προστατευτικοί αγώνες ως ξεχωριστό συντακτικό χαρακτηριστικό είναι " +"σημαντικοί και απαραίτητοι.\n" +"* Δεν είναι ίδια με την ξεχωριστή έκφραση «αν» μέσα στο βραχίονα του αγώνα. " +"Μια έκφραση `if` μέσα στο μπλοκ διακλάδωσης (μετά από `=>`) εμφανίζεται μετά " +"την επιλογή του βραχίονα αντιστοίχισης. Η αποτυχία της συνθήκης \"αν\" μέσα " +"σε αυτό το μπλοκ δεν θα οδηγήσει σε άλλους βραχίονες\n" +"της αρχικής έκφρασης «ταιριάσματος» που εξετάζεται.\n" +"* Μπορείτε να χρησιμοποιήσετε τις μεταβλητές που ορίζονται στο μοτίβο στην " +"έκφραση if σας.\n" +"* Η συνθήκη που ορίζεται στο προστατευτικό ισχύει για κάθε έκφραση σε μοτίβο " +"με ένα `|`.\n" +"" + +#: src/exercises/day-2/morning.md:1 +#, fuzzy +msgid "# Day 2: Morning Exercises" +msgstr "# Ημέρα 2: Πρωινές ασκήσεις" + +#: src/exercises/day-2/morning.md:3 +#, fuzzy +msgid "We will look at implementing methods in two contexts:" +msgstr "Θα εξετάσουμε την εφαρμογή μεθόδων σε δύο πλαίσια:" + +#: src/exercises/day-2/morning.md:5 +#, fuzzy +msgid "" +"* Simple struct which tracks health statistics.\n" +"\n" +"* Multiple structs and enums for a drawing library." +msgstr "* Πολλαπλές δομές και αριθμοί για μια βιβλιοθήκη σχεδίων." + +#: src/exercises/day-2/health-statistics.md:1 +#, fuzzy +msgid "# Health Statistics" +msgstr "# Στατιστικά Υγείας" + +#: src/exercises/day-2/health-statistics.md:3 +#, fuzzy +msgid "" +"You're working on implementing a health-monitoring system. As part of that, " +"you\n" +"need to keep track of users' health statistics." +msgstr "" +"Εργάζεστε για την εφαρμογή ενός συστήματος παρακολούθησης της υγείας. Ως " +"μέρος αυτού, εσείς\n" +"πρέπει να παρακολουθεί τα στατιστικά στοιχεία υγείας των χρηστών." + +#: src/exercises/day-2/health-statistics.md:6 +#, fuzzy +msgid "" +"You'll start with some stubbed functions in an `impl` block as well as a " +"`User`\n" +"struct definition. Your goal is to implement the stubbed out methods on the\n" +"`User` `struct` defined in the `impl` block." +msgstr "" +"Θα ξεκινήσετε με ορισμένες αποκομμένες συναρτήσεις σε ένα μπλοκ \"impl\" " +"καθώς και σε ένα \"User\".\n" +"ορισμός κατασκευής. Ο στόχος σας είναι να εφαρμόσετε τις αποκομμένες " +"μεθόδους στο\n" +"Η δομή \"User\" ορίζεται στο μπλοκ \"impl\"." + +#: src/exercises/day-2/health-statistics.md:10 +#, fuzzy +msgid "" +"Copy the code below to and fill in the " +"missing\n" +"methods:" +msgstr "" +"Αντιγράψτε τον παρακάτω κώδικα στο και " +"συμπληρώστε τον κωδικό που λείπει\n" +"μέθοδοι:" + +#: src/exercises/day-2/health-statistics.md:13 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"struct User {\n" +" name: String,\n" +" age: u32,\n" +" weight: f32,\n" +"}\n" +"\n" +"impl User {\n" +" pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn name(&self) -> &str {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn age(&self) -> u32 {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn weight(&self) -> f32 {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn set_age(&mut self, new_age: u32) {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn set_weight(&mut self, new_weight: f32) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_weight() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.weight(), 155.2);\n" +"}\n" +"\n" +"#[test]\n" +"fn test_set_age() {\n" +" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.age(), 32);\n" +" bob.set_age(33);\n" +" assert_eq!(bob.age(), 33);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:1 +#, fuzzy +msgid "# Polygon Struct" +msgstr "# Πολυγωνική κατασκευή" + +#: src/exercises/day-2/points-polygons.md:3 +#, fuzzy +msgid "" +"We will create a `Polygon` struct which contain some points. Copy the code " +"below\n" +"to and fill in the missing methods to make " +"the\n" +"tests pass:" +msgstr "" +"Θα δημιουργήσουμε μια δομή «Πολύγωνο» που περιέχει μερικά σημεία. Αντιγράψτε " +"τον παρακάτω κωδικό\n" +"στο και συμπληρώστε τις μεθόδους που λείπουν " +"για να το κάνετε\n" +"οι δοκιμές περνούν:" + +#: src/exercises/day-2/points-polygons.md:7 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub struct Point {\n" +" // add fields\n" +"}\n" +"\n" +"impl Point {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Polygon {\n" +" // add fields\n" +"}\n" +"\n" +"impl Polygon {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Circle {\n" +" // add fields\n" +"}\n" +"\n" +"impl Circle {\n" +" // add methods\n" +"}\n" +"\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:117 +#, fuzzy +msgid "" +"Since the method signatures are missing from the problem statements, the key " +"part\n" +"of the exercise is to specify those correctly. You don't have to modify the " +"tests." +msgstr "" +"Δεδομένου ότι οι υπογραφές της μεθόδου λείπουν από τις δηλώσεις προβλημάτων, " +"το βασικό μέρος\n" +"της άσκησης είναι να τα προσδιορίσετε σωστά." + +#: src/exercises/day-2/points-polygons.md:120 +msgid "Other interesting parts of the exercise:" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:122 +#, fuzzy +msgid "" +"* Derive a `Copy` trait for some structs, as in tests the methods sometimes " +"don't borrow their arguments.\n" +"* Discover that `Add` trait must be implemented for two objects to be " +"addable via \"+\". Note that we do not discuss generics until Day 3." +msgstr "" +"Άλλα ενδιαφέροντα μέρη της άσκησης:\n" +" \n" +"* Εξάγετε ένα χαρακτηριστικό «Αντιγραφή» για ορισμένες δομές, καθώς στις " +"δοκιμές οι μέθοδοι μερικές φορές δεν δανείζονται τα επιχειρήματά τους.\n" +"* Ανακαλύψτε ότι το χαρακτηριστικό «Προσθήκη» πρέπει να εφαρμοστεί για δύο " +"αντικείμενα που μπορούν να προστεθούν μέσω του «+»." + +#: src/control-flow.md:1 +#, fuzzy +msgid "# Control Flow" +msgstr "# Έλεγχος ροής" + +#: src/control-flow.md:3 +#, fuzzy +msgid "" +"As we have seen, `if` is an expression in Rust. It is used to conditionally\n" +"evaluate one of two blocks, but the blocks can have a value which then " +"becomes\n" +"the value of the `if` expression. Other control flow expressions work " +"similarly\n" +"in Rust." +msgstr "" +"Όπως είδαμε, το «αν» είναι μια έκφραση στο Rust. Χρησιμοποιείται υπό όρους\n" +"αξιολογήστε ένα από τα δύο μπλοκ, αλλά τα μπλοκ μπορεί να έχουν μια τιμή που " +"στη συνέχεια γίνεται\n" +"την τιμή της έκφρασης «αν». Άλλες εκφράσεις ροής ελέγχου λειτουργούν " +"παρόμοια\n" +"στο Rust." + +#: src/control-flow/blocks.md:1 +#, fuzzy +msgid "# Blocks" +msgstr "# Μπλοκ" + +#: src/control-flow/blocks.md:3 +#, fuzzy +msgid "" +"A block in Rust has a value and a type: the value is the last expression of " +"the\n" +"block:" +msgstr "" +"Ένα μπλοκ στο Rust έχει μια τιμή και έναν τύπο: η τιμή είναι η τελευταία " +"έκφραση του\n" +"ΟΙΚΟΔΟΜΙΚΟ ΤΕΤΡΑΓΩΝΟ:" + +#: src/control-flow/blocks.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = {\n" +" let y = 10;\n" +" println!(\"y: {y}\");\n" +" let z = {\n" +" let w = {\n" +" 3 + 4\n" +" };\n" +" println!(\"w: {w}\");\n" +" y * w\n" +" };\n" +" println!(\"z: {z}\");\n" +" z - y\n" +" };\n" +" println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:25 +#, fuzzy +msgid "" +"The same rule is used for functions: the value of the function body is the\n" +"return value:" +msgstr "" +"Ο ίδιος κανόνας χρησιμοποιείται για τις συναρτήσεις: η τιμή του σώματος " +"συνάρτησης είναι το\n" +"επιστρεφόμενη τιμή:" + +#: src/control-flow/blocks.md:28 +msgid "" +"```rust,editable\n" +"fn double(x: i32) -> i32 {\n" +" x + x\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"doubled: {}\", double(7));\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:38 +msgid "" +"However if the last expression ends with `;`, then the resulting value and " +"type is `()`." +msgstr "" + +#: src/control-flow/blocks.md:43 +#, fuzzy +msgid "" +"* The point of this slide is to show that blocks have a type and value in " +"Rust. \n" +"* You can show how the value of the block changes by changing the last line " +"in the block. For instance, adding/removing a semicolon or using a " +"`return`.\n" +" " +msgstr "" +"Βασικά σημεία:\n" +"* Ο σκοπός αυτής της διαφάνειας είναι να δείξει ότι τα μπλοκ έχουν τύπο και " +"τιμή στο Rust.\n" +"* Μπορείτε να δείξετε πώς αλλάζει η τιμή του μπλοκ αλλάζοντας την τελευταία " +"γραμμή στο μπλοκ. Για παράδειγμα, προσθέτοντας/αφαιρώντας ένα ερωτηματικό ή " +"χρησιμοποιώντας ένα «return».\n" +" \n" +"" + +#: src/control-flow/if-expressions.md:1 +#, fuzzy +msgid "# `if` expressions" +msgstr "# εκφράσεις \"αν\"." + +#: src/control-flow/if-expressions.md:3 +#, fuzzy +msgid "You use `if` very similarly to how you would in other languages:" +msgstr "" +"Χρησιμοποιείτε το \"if\" πολύ παρόμοια με αυτό που θα κάνατε σε άλλες " +"γλώσσες:" + +#: src/control-flow/if-expressions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" if x % 2 == 0 {\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:16 +#, fuzzy +msgid "" +"In addition, you can use it as an expression. This does the same as above:" +msgstr "" +"Επιπλέον, μπορείτε να το χρησιμοποιήσετε ως έκφραση. Αυτό κάνει το ίδιο όπως " +"παραπάνω:" + +#: src/control-flow/if-expressions.md:18 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:31 +msgid "" +"Because `if` is an expression and must have a particular type, both of its " +"branch blocks must have the same type. Consider showing what happens if you " +"add `;` after `x / 2` in the second example." +msgstr "" + +#: src/control-flow/if-let-expressions.md:1 +#, fuzzy +msgid "# `if let` expressions" +msgstr "# εκφράσεις \"αν ας\"." + +#: 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 "" +"Εάν θέλετε να ταιριάξετε μια τιμή με ένα μοτίβο, μπορείτε να χρησιμοποιήσετε " +"το «αν επιτρέπεται»:" + +#: src/control-flow/if-let-expressions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let arg = std::env::args().next();\n" +" if let Some(value) = arg {\n" +" println!(\"Program name: {value}\");\n" +" } else {\n" +" println!(\"Missing name?\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-let-expressions.md:16 +#: src/control-flow/while-let-expressions.md:21 +#: src/control-flow/match-expressions.md:22 +#, fuzzy +msgid "" +"See [pattern matching](../pattern-matching.md) for more details on patterns " +"in\n" +"Rust." +msgstr "" +"Δείτε το [pattern matching](../pattern-matching.md) για περισσότερες " +"λεπτομέρειες σχετικά με τα μοτίβα στο\n" +"Σκουριά." + +#: src/control-flow/if-let-expressions.md:21 +#, fuzzy +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" +" * For the similar use case consider demonstrating a newly stabilized " +"[`let else`](https://github.com/rust-lang/rust/pull/93628) feature.\n" +"* A common usage is handling `Some` values when working with `Option`.\n" +"* Unlike `match`, `if let` does not support guard clauses for pattern " +"matching." +msgstr "" +"* Το «αν ας» μπορεί να είναι πιο συνοπτικό από το «ταίριασμα», π.χ., όταν " +"μόνο μία περίπτωση είναι ενδιαφέρουσα. Αντίθετα, το \"match\" απαιτεί να " +"καλύπτονται όλοι οι κλάδοι.\n" +" * Για παρόμοια περίπτωση χρήσης, εξετάστε το ενδεχόμενο να επιδείξετε " +"μια νέα σταθεροποιημένη λειτουργία [`let else`](https://github.com/rust-lang/" +"rust/pull/93628).\n" +"* Μια κοινή χρήση είναι ο χειρισμός των τιμών \"Μερικών\" όταν εργάζεστε με " +"το \"Option\".\n" +"* Σε αντίθεση με το \"match\", το \"if let\" δεν υποστηρίζει προστατευτικές " +"ρήτρες για την αντιστοίχιση μοτίβων." + +#: src/control-flow/while-expressions.md:1 +#, fuzzy +msgid "# `while` expressions" +msgstr "# εκφράσεις «ενώ»." + +#: src/control-flow/while-expressions.md:3 +#, fuzzy +msgid "The `while` keyword works very similar to other languages:" +msgstr "Η λέξη-κλειδί \"while\" λειτουργεί πολύ παρόμοια με άλλες γλώσσες:" + +#: src/control-flow/while-expressions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" while x != 1 {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/while-let-expressions.md:1 +#, fuzzy +msgid "# `while let` expressions" +msgstr "# εκφράσεις «ενώ ας»." + +#: 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:" +msgstr "" +"Όπως και με το \"if\", υπάρχει μια παραλλαγή \"while let\" που ελέγχει " +"επανειλημμένα μια τιμή\n" +"σε σχέση με ένα μοτίβο:" + +#: src/control-flow/while-let-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +"\n" +" while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/while-let-expressions.md:17 +#, fuzzy +msgid "" +"Here the iterator returned by `v.iter()` will return a `Option` on " +"every\n" +"call to `next()`. It returns `Some(x)` until it is done, after which it " +"will\n" +"return `None`. The `while let` lets us keep iterating through all items." +msgstr "" +"Εδώ ο επαναλήπτης που επιστρέφεται από το `v.iter()` θα επιστρέψει ένα " +"`Option` σε κάθε\n" +"κλήση στο `επόμενο()`. Επιστρέφει \"Some(x)\" μέχρι να ολοκληρωθεί, μετά από " +"αυτό θα γίνει\n" +"επιστροφή «Κανένα». Το \"while let\" μας επιτρέπει να συνεχίσουμε να " +"επαναλαμβάνουμε όλα τα στοιχεία." + +#: src/control-flow/while-let-expressions.md:27 +#, fuzzy +msgid "" +"* Point out that the `while let` loop will keep going as long as the value " +"matches the pattern.\n" +"* You could rewrite the `while let` loop as an infinite loop with an if " +"statement that breaks when there is no value to unwrap for `iter.next()`. " +"The `while let` provides syntactic sugar for the above scenario.\n" +" " +msgstr "" +"* Επισημάνετε ότι ο βρόχος \"while let\" θα συνεχίσει να λειτουργεί όσο η " +"τιμή ταιριάζει με το μοτίβο.\n" +"* Θα μπορούσατε να ξαναγράψετε τον βρόχο «while let» ως άπειρο βρόχο με μια " +"πρόταση if που διακόπτεται όταν δεν υπάρχει τιμή για ξετύλιγμα για το «iter." +"next()». Το \"while let\" παρέχει συντακτική ζάχαρη για το παραπάνω " +"σενάριο.\n" +" \n" +"" + +#: src/control-flow/for-expressions.md:1 +#, fuzzy +msgid "# `for` expressions" +msgstr "# εκφράσεις «για»." + +#: src/control-flow/for-expressions.md:3 +#, fuzzy +msgid "" +"The `for` expression is closely related to the `while let` expression. It " +"will\n" +"automatically call `into_iter()` on the expression and then iterate over it:" +msgstr "" +"Η έκφραση \"for\" σχετίζεται στενά με την έκφραση \"while let\". Θα\n" +"καλεί αυτόματα το «into_iter()» στην έκφραση και, στη συνέχεια, " +"επαναλαμβάνει πάνω από αυτήν:" + +#: src/control-flow/for-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +"\n" +" for x in v {\n" +" println!(\"x: {x}\");\n" +" }\n" +" \n" +" for i in (0..10).step_by(2) {\n" +" println!(\"i: {i}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/for-expressions.md:20 +#, fuzzy +msgid "You can use `break` and `continue` here as usual." +msgstr "" +"Μπορείτε να χρησιμοποιήσετε το «διάλειμμα» και το «συνέχεια» εδώ ως συνήθως." + +#: src/control-flow/for-expressions.md:24 +#, fuzzy +msgid "" +"* Index iteration is not a special syntax in Rust for just that case.\n" +"* `(0..10)` is a range that implements an `Iterator` trait. \n" +"* `step_by` is a method that returns another `Iterator` that skips every " +"other element. \n" +"* Modify the elements in the vector and explain the compiler errors. Change " +"vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." +msgstr "" +"<λεπτομέρειες>\n" +" \n" +"* Η επανάληψη ευρετηρίου δεν είναι ειδική σύνταξη στο Rust για αυτήν την " +"περίπτωση.\n" +"* Το \"(0..10)\" είναι μια περιοχή που υλοποιεί ένα χαρακτηριστικό " +"\"Iterator\".\n" +"* Το \"step_by\" είναι μια μέθοδος που επιστρέφει έναν άλλο \"Iterator\" που " +"παραλείπει κάθε άλλο στοιχείο.\n" +" \n" +"" + +#: src/control-flow/loop-expressions.md:1 +#, fuzzy +msgid "# `loop` expressions" +msgstr "# εκφράσεις «βρόχου»." + +#: 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:" +msgstr "" +"Τέλος, υπάρχει μια λέξη-κλειδί «βρόχος» που δημιουργεί έναν ατελείωτο βρόχο. " +"Εδώ πρέπει\n" +"είτε \"break\" είτε \"return\" για να σταματήσει ο βρόχος:" + +#: src/control-flow/loop-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" loop {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" if x == 1 {\n" +" break;\n" +" }\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/loop-expressions.md:25 +msgid "* Break the `loop` with a value (e.g. `break 8`) and print it out." +msgstr "" + +#: src/control-flow/match-expressions.md:1 +#, fuzzy +msgid "# `match` expressions" +msgstr "# «ταιριάζουν» εκφράσεις" + +#: 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:" +msgstr "" +"Η λέξη-κλειδί \"αντιστοιχία\" χρησιμοποιείται για την αντιστοίχιση μιας " +"τιμής με ένα ή περισσότερα μοτίβα. Σε\n" +"Με αυτή την έννοια, λειτουργεί σαν μια σειρά από εκφράσεις «αν ας»:" + +#: src/control-flow/match-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" match std::env::args().next().as_deref() {\n" +" Some(\"cat\") => println!(\"Will do cat things\"),\n" +" Some(\"ls\") => println!(\"Will ls some files\"),\n" +" Some(\"mv\") => println!(\"Let's move some files\"),\n" +" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" +" None => println!(\"Hmm, no program name?\"),\n" +" _ => println!(\"Unknown program name!\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/match-expressions.md:19 +#, fuzzy +msgid "" +"Like `if let`, each match arm must have the same type. The type is the last\n" +"expression of the block, if any. In the example above, the type is `()`." +msgstr "" +"Όπως το \"αν ας\", κάθε βραχίονας αγώνα πρέπει να έχει τον ίδιο τύπο. Ο " +"τύπος είναι ο τελευταίος\n" +"έκφραση του μπλοκ, εάν υπάρχει. Στο παραπάνω παράδειγμα, ο τύπος είναι `()`." + +#: src/control-flow/match-expressions.md:27 +msgid "" +"* Save the match expression to a variable and print it out.\n" +"* Remove `.as_deref()` and explain the error.\n" +" * `std::env::args().next()` returns an `Option`, but we cannot " +"match against `String`.\n" +" * `as_deref()` transforms an `Option` to `Option<&T::Target>`. In our " +"case, this turns `Option` into `Option<&str>`.\n" +" * We can now use pattern matching to match against the `&str` inside " +"`Option`." +msgstr "" + +#: src/control-flow/break-continue.md:1 +#, fuzzy +msgid "# `break` and `continue`" +msgstr "# «διάλειμμα» και «συνέχεια»." + +#: src/control-flow/break-continue.md:3 +#, 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:" +msgstr "" +"Εάν θέλετε να βγείτε νωρίς από έναν βρόχο, χρησιμοποιήστε το «διάλειμμα», " +"εάν θέλετε να ξεκινήσετε αμέσως\n" +"την επόμενη επανάληψη χρησιμοποιήστε «continue». Τόσο το \"continue\" και το " +"\"break\" μπορούν προαιρετικά\n" +"πάρτε ένα όρισμα ετικέτας που χρησιμοποιείται για να ξεφύγει από ένθετους " +"βρόχους:" + +#: src/control-flow/break-continue.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +" 'outer: while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" let mut i = 0;\n" +" while i < x {\n" +" println!(\"x: {x}, i: {i}\");\n" +" i += 1;\n" +" if i == 3 {\n" +" break 'outer;\n" +" }\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/break-continue.md:25 +#, fuzzy +msgid "" +"In this case we break the outer loop after 3 iterations of the inner loop." +msgstr "" +"Σε αυτή την περίπτωση σπάμε τον εξωτερικό βρόχο μετά από 3 επαναλήψεις του " +"εσωτερικού βρόχου." + +#: src/std.md:1 +#, fuzzy +msgid "# Standard Library" +msgstr "# Τυπική βιβλιοθήκη" + +#: src/std.md:3 +#, fuzzy +msgid "" +"Rust comes with a standard library which helps establish a set of common " +"types\n" +"used by Rust library and programs. This way, two libraries can work " +"together\n" +"smoothly because they both use the same `String` type." +msgstr "" +"Το Rust συνοδεύεται από μια τυπική βιβλιοθήκη που βοηθά στη δημιουργία ενός " +"συνόλου κοινών τύπων\n" +"χρησιμοποιείται από τη βιβλιοθήκη και τα προγράμματα της Rust. Με αυτόν τον " +"τρόπο, δύο βιβλιοθήκες μπορούν να συνεργαστούν\n" +"ομαλά γιατί και οι δύο χρησιμοποιούν τον ίδιο τύπο «String»." + +#: src/std.md:7 +#, fuzzy +msgid "The common vocabulary types include:" +msgstr "Οι συνήθεις τύποι λεξιλογίου περιλαμβάνουν:" + +#: src/std.md:9 +msgid "" +"* [`Option` and `Result`](std/option-result.md) types: used for optional " +"values\n" +" and [error handling](error-handling.md).\n" +"\n" +"* [`String`](std/string.md): the default string type used for owned data.\n" +"\n" +"* [`Vec`](std/vec.md): a standard extensible vector.\n" +"\n" +"* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" +" algorithm.\n" +"\n" +"* [`Box`](std/box.md): an owned pointer for heap-allocated data.\n" +"\n" +"* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated " +"data." +msgstr "" + +#: src/std.md:25 +#, fuzzy +msgid "" +" * In fact, Rust contains several layers of the Standard Library: `core`, " +"`alloc` and `std`. \n" +" * `core` includes the most basic types and functions that don't depend on " +"`libc`, allocator or\n" +" even the presence of an operating system. \n" +" * `alloc` includes types which require a global heap allocator, such as " +"`Vec`, `Box` and `Arc`.\n" +" * Embedded Rust applications often only use `core`, and sometimes `alloc`." +msgstr "" +"<λεπτομέρειες>\n" +" \n" +" * Στην πραγματικότητα, το Rust περιέχει πολλά επίπεδα της τυπικής " +"βιβλιοθήκης: «core», «alloc» και «std».\n" +" * Ο «πυρήνας» περιλαμβάνει τους πιο βασικούς τύπους και λειτουργίες που " +"δεν εξαρτώνται από το «libc», τον εκχωρητή ή\n" +" ακόμη και η παρουσία ενός λειτουργικού συστήματος.\n" +" * Το \"alloc\" περιλαμβάνει τύπους που απαιτούν καθολικό εκχωρητή σωρού, " +"όπως \"Vec\", \"Box\" και \"Arc\".\n" +" * Οι εφαρμογές Embedded Rust χρησιμοποιούν συχνά μόνο «core» και μερικές " +"φορές «alloc»." + +#: src/std/option-result.md:1 +#, fuzzy +msgid "# `Option` and `Result`" +msgstr "# «Επιλογή» και «Αποτέλεσμα»." + +#: src/std/option-result.md:3 +#, fuzzy +msgid "The types represent optional data:" +msgstr "Οι τύποι αντιπροσωπεύουν προαιρετικά δεδομένα:" + +#: src/std/option-result.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let numbers = vec![10, 20, 30];\n" +" let first: Option<&i8> = numbers.first();\n" +" println!(\"first: {first:?}\");\n" +"\n" +" let idx: Result = numbers.binary_search(&10);\n" +" println!(\"idx: {idx:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/option-result.md:18 +#, fuzzy +msgid "" +"* `Option` and `Result` are widely used not just in the standard library.\n" +"* `Option<&T>` has zero space overhead compared to `&T`.\n" +"* `Result` is the standard type to implement error handling as we will see " +"on Day 3.\n" +"* `binary_search` returns `Result`.\n" +" * If found, `Result::Ok` holds the index where the element is found.\n" +" * Otherwise, `Result::Err` contains the index where such an element should " +"be inserted." +msgstr "" +"* Η επιλογή «Επιλογή» και «Αποτέλεσμα» χρησιμοποιούνται ευρέως όχι μόνο στην " +"τυπική βιβλιοθήκη.\n" +"* Το \"Option<&T>\" έχει μηδενικό χώρο σε σύγκριση με το \"&T\".\n" +"* Το \"Αποτέλεσμα\" είναι ο τυπικός τύπος για την υλοποίηση του χειρισμού " +"σφαλμάτων, όπως θα δούμε την Ημέρα 3.\n" +"* Η \"δυαδική_αναζήτηση\" επιστρέφει \"Αποτέλεσμα<χρήση, χρήση>\".\n" +" * Εάν βρεθεί, το «Αποτέλεσμα::Οκ» διατηρεί το ευρετήριο όπου βρίσκεται το " +"στοιχείο.\n" +" * Διαφορετικά, το \"Αποτέλεσμα::Σφάλμα\" περιέχει το ευρετήριο όπου θα " +"πρέπει να εισαχθεί ένα τέτοιο στοιχείο." + +#: src/std/string.md:1 +#, fuzzy +msgid "# String" +msgstr "# Χορδή" + +#: src/std/string.md:3 +#, fuzzy +msgid "" +"[`String`][1] is the standard heap-allocated growable UTF-8 string buffer:" +msgstr "" +"Το [`String`][1] είναι το τυπικό buffer συμβολοσειρών UTF-8 που εκχωρείται " +"σε σωρό:" + +#: src/std/string.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut s1 = String::new();\n" +" s1.push_str(\"Hello\");\n" +" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());\n" +"\n" +" let mut s2 = String::with_capacity(s1.len() + 1);\n" +" s2.push_str(&s1);\n" +" s2.push('!');\n" +" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());\n" +"\n" +" let s3 = String::from(\"🇨🇭\");\n" +" println!(\"s3: len = {}, number of chars = {}\", s3.len(),\n" +" s3.chars().count());\n" +"}\n" +"```" +msgstr "" + +#: src/std/string.md:22 +#, fuzzy +msgid "" +"`String` implements [`Deref`][2], which means that you can " +"call all\n" +"`str` methods on a `String`." +msgstr "" +"Το `String` υλοποιεί [`Deref`][2], που σημαίνει ότι μπορείτε " +"να καλέσετε όλα\n" +"Μέθοδοι `str` σε μια συμβολοσειρά." + +#: src/std/string.md:30 +msgid "" +"* `String::new` returns a new empty string, use `String::with_capacity` when " +"you know how much data you want to push to the string.\n" +"* `String::len` returns the size of the `String` in bytes (which can be " +"different from its length in characters).\n" +"* `String::chars` returns an iterator over the actual characters. Note that " +"a `char` can be different from what a human will consider a \"character\" " +"due to [grapheme clusters](https://docs.rs/unicode-segmentation/latest/" +"unicode_segmentation/struct.Graphemes.html).\n" +"* When people refer to strings they could either be talking about `&str` or " +"`String`. \n" +"* When a type implements `Deref`, the compiler will let you " +"transparently call methods from `T`.\n" +" * `String` implements `Deref` which transparently gives it " +"access to `str`'s methods.\n" +" * 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." +msgstr "" + +#: src/std/vec.md:1 +#, fuzzy +msgid "# `Vec`" +msgstr "# «Vec»." + +#: src/std/vec.md:3 +#, fuzzy +msgid "[`Vec`][1] is the standard resizable heap-allocated buffer:" +msgstr "" +"Το [`Vec`][1] είναι το τυπικό buffer με δυνατότητα αλλαγής μεγέθους που " +"εκχωρείται σε σωρό:" + +#: src/std/vec.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut v1 = Vec::new();\n" +" v1.push(42);\n" +" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());\n" +"\n" +" let mut v2 = Vec::with_capacity(v1.len() + 1);\n" +" v2.extend(v1.iter());\n" +" v2.push(9999);\n" +" println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());\n" +"\n" +" // Canonical macro to initialize a vector with elements.\n" +" let mut v3 = vec![0, 0, 1, 2, 3, 4];\n" +"\n" +" // Retain only the even elements.\n" +" v3.retain(|x| x % 2 == 0);\n" +" println!(\"{v3:?}\");\n" +"\n" +" // Remove consecutive duplicates.\n" +" v3.dedup();\n" +" println!(\"{v3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/vec.md:29 +#, fuzzy +msgid "" +"`Vec` implements [`Deref`][2], which means that you can call " +"slice\n" +"methods on a `Vec`." +msgstr "" +"Το `Vec` υλοποιεί το [`Deref`][2], που σημαίνει ότι μπορείτε " +"να καλέσετε το slice\n" +"μεθόδους σε ένα «Vec»." + +#: src/std/vec.md:37 +msgid "" +"* `Vec` is a type of collection, along with `String` and `HashMap`. The data " +"it contains is stored\n" +" on the heap. This means the amount of data doesn't need to be known at " +"compile time. It can grow\n" +" or shrink at runtime.\n" +"* Notice how `Vec` is a generic type too, but you don't have to specify " +"`T` explicitly. As always\n" +" with Rust type inference, the `T` was established during the first `push` " +"call.\n" +"* `vec![...]` is a canonical macro to use instead of `Vec::new()` and it " +"supports adding initial\n" +" elements to the vector.\n" +"* To index the vector you use `[` `]`, but they will panic if out of bounds. " +"Alternatively, using\n" +" `get` will return an `Option`. The `pop` function will remove the last " +"element.\n" +"* Show iterating over a vector and mutating the value:\n" +" `for e in &mut v { *e += 50; }`" +msgstr "" + +#: src/std/hashmap.md:1 +#, fuzzy +msgid "# `HashMap`" +msgstr "# `HashMap`" + +#: src/std/hashmap.md:3 +#, fuzzy +msgid "Standard hash map with protection against HashDoS attacks:" +msgstr "Τυπικός χάρτης κατακερματισμού με προστασία από επιθέσεις HashDoS:" + +#: src/std/hashmap.md:5 +msgid "" +"```rust,editable\n" +"use std::collections::HashMap;\n" +"\n" +"fn main() {\n" +" let mut page_counts = HashMap::new();\n" +" page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), " +"207);\n" +" page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" +" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);\n" +"\n" +" if !page_counts.contains_key(\"Les Misérables\") {\n" +" println!(\"We know about {} books, but not Les Misérables.\",\n" +" page_counts.len());\n" +" }\n" +"\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in " +"Wonderland\"] {\n" +" match page_counts.get(book) {\n" +" Some(count) => println!(\"{book}: {count} pages\"),\n" +" None => println!(\"{book} is unknown.\")\n" +" }\n" +" }\n" +"\n" +" // Use the .entry() method to insert a value if nothing is found.\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in " +"Wonderland\"] {\n" +" let page_count: &mut i32 = page_counts.entry(book.to_string())." +"or_insert(0);\n" +" *page_count += 1;\n" +" }\n" +"\n" +" println!(\"{page_counts:#?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/hashmap.md:38 +msgid "" +"* `HashMap` is not defined in the prelude and needs to be brought into " +"scope.\n" +"* Try the following lines of code. The first line will see if a book is in " +"the hashmap and if not return an alternative value. The second line will " +"insert the alternative value in the hashmap if the book is not found.\n" +"\n" +" ```rust,ignore\n" +" let pc1 = page_counts\n" +" .get(\"Harry Potter and the Sorcerer's Stone \")\n" +" .unwrap_or(&336);\n" +" let pc2 = page_counts\n" +" .entry(\"The Hunger Games\".to_string())\n" +" .or_insert(374);\n" +" ```\n" +"* Unlike `vec!`, there is unfortunately no standard `hashmap!` macro.\n" +" * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], " +"which allows us to easily initialize a hash map from a literal array:\n" +"\n" +" ```rust,ignore\n" +" let page_counts = HashMap::from([\n" +" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" +" (\"The Hunger Games\".to_string(), 374),\n" +" ]);\n" +" ```\n" +"\n" +" * Alternatively HashMap can be built from any `Iterator` which yields key-" +"value tuples.\n" +"* We are showing `HashMap`, and avoid using `&str` as key to " +"make examples easier. Using references in collections can, of course, be " +"done,\n" +" but it can lead into complications with the borrow checker.\n" +" * Try removing `to_string()` from the example above and see if it still " +"compiles. Where do you think we might run into issues?" +msgstr "" + +#: src/std/box.md:1 +#, fuzzy +msgid "# `Box`" +msgstr "# «Κουτί»." + +#: src/std/box.md:3 +#, fuzzy +msgid "[`Box`][1] is an owned pointer to data on the heap:" +msgstr "Το [`Πλαίσιο`][1] είναι ένας ιδιόκτητος δείκτης σε δεδομένα στο σωρό:" + +#: src/std/box.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let five = Box::new(5);\n" +" println!(\"five: {}\", *five);\n" +"}\n" +"```" +msgstr "" + +#: src/std/box.md:13 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - -. .- - - - - - -.\n" +": : : :\n" +": five : : :\n" +": +-----+ : : +-----+ :\n" +": | o---|---+-----+-->| 5 | :\n" +": +-----+ : : +-----+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - -' `- - - - - - -'\n" +"```" +msgstr "" + +#: src/std/box.md:26 +#, fuzzy +msgid "" +"`Box` implements `Deref`, which means that you can [call " +"methods\n" +"from `T` directly on a `Box`][2]." +msgstr "" +"Το \"Box\" υλοποιεί το \"Deref\", που σημαίνει ότι μπορείτε " +"[μεθόδους κλήσης\n" +"από το \"T\" απευθείας σε ένα \"Box\"][2]." + +#: src/std/box.md:34 +msgid "" +"* `Box` is like `std::unique_ptr` in C++, except that it's guaranteed to be " +"not null. \n" +"* In the above example, you can even leave out the `*` in the `println!` " +"statement thanks to `Deref`. \n" +"* A `Box` can be useful when you:\n" +" * have a type whose size that can't be known at compile time, but the " +"Rust compiler wants to know an exact size.\n" +" * want to transfer ownership of a large amount of data. To avoid copying " +"large amounts of data on the stack, instead store the data on the heap in a " +"`Box` so only the pointer is moved." +msgstr "" + +#: src/std/box-recursive.md:1 +#, fuzzy +msgid "# Box with Recursive Data Structures" +msgstr "# Πλαίσιο με αναδρομικές δομές δεδομένων" + +#: src/std/box-recursive.md:3 +#, fuzzy +msgid "" +"Recursive data types or data types with dynamic sizes need to use a `Box`:" +msgstr "" +"Οι αναδρομικοί τύποι δεδομένων ή οι τύποι δεδομένων με δυναμικά μεγέθη " +"πρέπει να χρησιμοποιούν ένα «Πλαίσιο»:" + +#: src/std/box-recursive.md:5 src/std/box-niche.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"enum List {\n" +" Cons(T, Box>),\n" +" Nil,\n" +"}\n" +"\n" +"fn main() {\n" +" let list: List = List::Cons(1, Box::new(List::Cons(2, Box::" +"new(List::Nil))));\n" +" println!(\"{list:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/box-recursive.md:18 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - " +"- -.\n" +": : : :\n" +": " +"list : : :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----" +"+ :\n" +": | Cons | 1 | o--+----+-----+--->| Cons | 2 | o--+--->| Nil | // | // " +"| :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----" +"+ :\n" +": : : :\n" +": : : :\n" +"'- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - " +"- -'\n" +"```" +msgstr "" + +#: src/std/box-recursive.md:33 +msgid "" +"* If the `Box` was not used here and we attempted to embed a `List` directly " +"into the `List`,\n" +"the compiler would not compute a fixed size of the struct in memory, it " +"would look infinite.\n" +"\n" +"* `Box` solves this problem as it has the same size as a regular pointer and " +"just points at the next\n" +"element of the `List` in the heap.\n" +"\n" +"* Remove the `Box` in the List definition and show the compiler error. " +"\"Recursive with indirection\" is a hint you might want to use a Box or " +"reference of some kind, instead of storing a value directly. \n" +" " +msgstr "" + +#: src/std/box-niche.md:1 +#, fuzzy +msgid "# Niche Optimization" +msgstr "# Niche Optimization" + +#: src/std/box-niche.md:16 +#, fuzzy +msgid "" +"A `Box` cannot be empty, so the pointer is always valid and non-`null`. " +"This\n" +"allows the compiler to optimize the memory layout:" +msgstr "" +"Ένα «Πλαίσιο» δεν μπορεί να είναι κενό, επομένως ο δείκτης είναι πάντα " +"έγκυρος και μη «μηδενικός». Αυτό\n" +"επιτρέπει στον μεταγλωττιστή να βελτιστοποιήσει τη διάταξη της μνήμης:" + +#: src/std/box-niche.md:19 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - " +"-.\n" +": : : :\n" +": " +"list : : :\n" +": +----+----+ : : +----+----+ +----+------" +"+ :\n" +": | 1 | o--+-----------+-----+--->| 2 | o--+--->| // | null " +"| :\n" +": +----+----+ : : +----+----+ +----+------" +"+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - " +"-'\n" +"```" +msgstr "" + +#: src/std/rc.md:1 +#, fuzzy +msgid "# `Rc`" +msgstr "# «Rc»." + +#: src/std/rc.md:3 +#, fuzzy +msgid "" +"[`Rc`][1] is a reference-counted shared pointer. Use this when you need to " +"refer\n" +"to the same data from multiple places:" +msgstr "" +"Το [`Rc`][1] είναι ένας κοινόχρηστος δείκτης με μέτρηση αναφοράς. " +"Χρησιμοποιήστε το όταν πρέπει να ανατρέξετε\n" +"στα ίδια δεδομένα από πολλά μέρη:" + +#: src/std/rc.md:6 +msgid "" +"```rust,editable\n" +"use std::rc::Rc;\n" +"\n" +"fn main() {\n" +" let mut a = Rc::new(10);\n" +" let mut b = a.clone();\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/rc.md:18 +#, fuzzy +msgid "" +"* If you need to mutate the data inside an `Rc`, you will need to wrap the " +"data in\n" +" a type such as [`Cell` or `RefCell`][2].\n" +"* See [`Arc`][3] if you are in a multi-threaded context.\n" +"* You can *downgrade* a shared pointer into a [`Weak`][4] pointer to create " +"cycles\n" +" that will get dropped." +msgstr "" +"Εάν πρέπει να μεταλλάξετε τα δεδομένα μέσα σε ένα \"Rc\", θα πρέπει να " +"τυλίξετε τα δεδομένα μέσα\n" +"έναν τύπο όπως [`Cell` ή `RefCell`][2]. Ανατρέξτε στο [`Arc`][3] εάν " +"βρίσκεστε σε ένα multi-threaded\n" +"συμφραζόμενα." + +#: src/std/rc.md:31 +#, fuzzy +msgid "" +"* `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" +"* `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" +" create cycles that will be dropped properly (likely in combination with\n" +" `RefCell`)." +msgstr "" +"* Όπως το `std::shared_ptr` της C++.\n" +"* Το \"clone\" είναι φθηνό: δημιουργεί έναν δείκτη στην ίδια κατανομή και " +"αυξάνει το πλήθος αναφοράς.\n" +"* Το `make_mut` στην πραγματικότητα κλωνοποιεί την εσωτερική τιμή εάν είναι " +"απαραίτητο (\"clone-on-write\") και επιστρέφει μια μεταβλητή αναφορά." + +#: src/std/rc.md:41 +msgid "" +"```rust,editable\n" +"use std::rc::{Rc, Weak};\n" +"use std::cell::RefCell;\n" +"\n" +"#[derive(Debug)]\n" +"struct Node {\n" +" value: i64,\n" +" parent: Option>>,\n" +" children: Vec>>,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut root = Rc::new(RefCell::new(Node {\n" +" value: 42,\n" +" parent: None,\n" +" children: vec![],\n" +" }));\n" +" let child = Rc::new(RefCell::new(Node {\n" +" value: 43,\n" +" children: vec![],\n" +" parent: Some(Rc::downgrade(&root))\n" +" }));\n" +" root.borrow_mut().children.push(child);\n" +"\n" +" println!(\"graph: {root:#?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/modules.md:1 +#, fuzzy +msgid "# Modules" +msgstr "# Ενότητες" + +#: src/modules.md:3 +#, fuzzy +msgid "We have seen how `impl` blocks let us namespace functions to a type." +msgstr "" +"Είδαμε πώς τα μπλοκ «impl» μας επιτρέπουν να λειτουργεί ο χώρος ονομάτων σε " +"έναν τύπο." + +#: src/modules.md:5 +#, fuzzy +msgid "Similarly, `mod` lets us namespace types and functions:" +msgstr "Ομοίως, το «mod» μας επιτρέπει τύπους και συναρτήσεις ονομάτων:" + +#: src/modules.md:7 +msgid "" +"```rust,editable\n" +"mod foo {\n" +" pub fn do_something() {\n" +" println!(\"In the foo module\");\n" +" }\n" +"}\n" +"\n" +"mod bar {\n" +" pub fn do_something() {\n" +" println!(\"In the bar module\");\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" foo::do_something();\n" +" bar::do_something();\n" +"}\n" +"```" +msgstr "" + +#: src/modules.md:28 +msgid "" +"* Packages provide functionality and include a `Cargo.toml` file that " +"describes how to build a bundle of 1+ crates.\n" +"* Crates are a tree of modules, where a binary crate creates an executable " +"and a library crate compiles to a library.\n" +"* Modules define organization, scope, and are the focus of this section." +msgstr "" + +#: src/modules/visibility.md:1 +#, fuzzy +msgid "# Visibility" +msgstr "# Ορατότητα" + +#: src/modules/visibility.md:3 +#, fuzzy +msgid "Modules are a privacy boundary:" +msgstr "Οι ενότητες αποτελούν όριο απορρήτου:" + +#: src/modules/visibility.md:5 +#, fuzzy +msgid "" +"* Module items are private by default (hides implementation details).\n" +"* Parent and sibling items are always visible.\n" +"* In other words, if an item is visible in module `foo`, it's visible in all " +"the\n" +" descendants of `foo`." +msgstr "" +"* Τα στοιχεία της μονάδας είναι ιδιωτικά από προεπιλογή (αποκρύπτει τις " +"λεπτομέρειες υλοποίησης).\n" +"* Τα στοιχεία γονέα και αδελφών είναι πάντα ορατά." + +#: src/modules/visibility.md:10 +msgid "" +"```rust,editable\n" +"mod outer {\n" +" fn private() {\n" +" println!(\"outer::private\");\n" +" }\n" +"\n" +" pub fn public() {\n" +" println!(\"outer::public\");\n" +" }\n" +"\n" +" mod inner {\n" +" fn private() {\n" +" println!(\"outer::inner::private\");\n" +" }\n" +"\n" +" pub fn public() {\n" +" println!(\"outer::inner::public\");\n" +" super::private();\n" +" }\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" outer::public();\n" +"}\n" +"```" +msgstr "" + +#: src/modules/visibility.md:39 +msgid "* Use the `pub` keyword to make modules public." +msgstr "" + +#: src/modules/visibility.md:41 +msgid "" +"Additionally, there are advanced `pub(...)` specifiers to restrict the scope " +"of public visibility." +msgstr "" + +#: src/modules/visibility.md:43 +msgid "" +"* See the [Rust Reference](https://doc.rust-lang.org/reference/visibility-" +"and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself).\n" +"* Configuring `pub(crate)` visibility is a common pattern.\n" +"* Less commonly, you can give visibility to a specific path.\n" +"* In any case, visibility must be granted to an ancestor module (and all of " +"its descendants)." +msgstr "" + +#: src/modules/paths.md:1 +#, fuzzy +msgid "# Paths" +msgstr "# Μονοπάτια" + +#: src/modules/paths.md:3 +#, fuzzy +msgid "Paths are resolved as follows:" +msgstr "Οι διαδρομές επιλύονται ως εξής:" + +#: src/modules/paths.md:5 +#, fuzzy +msgid "" +"1. As a relative path:\n" +" * `foo` or `self::foo` refers to `foo` in the current module,\n" +" * `super::foo` refers to `foo` in the parent module.\n" +"\n" +"2. As an absolute path:\n" +" * `crate::foo` refers to `foo` in the root of the current crate,\n" +" * `bar::foo` refers to `foo` in the `bar` crate." +msgstr "" +"2. Ως απόλυτη διαδρομή:\n" +" * Το \"crate::foo\" αναφέρεται στο \"foo\" στη ρίζα του τρέχοντος " +"κιβωτίου,\n" +" * Το «bar::foo» αναφέρεται στο «foo» στο κιβώτιο «bar»." + +#: src/modules/filesystem.md:1 +#, fuzzy +msgid "# Filesystem Hierarchy" +msgstr "# Ιεραρχία συστήματος αρχείων" + +#: src/modules/filesystem.md:3 +#, fuzzy +msgid "The module content can be omitted:" +msgstr "Το περιεχόμενο της ενότητας μπορεί να παραλειφθεί:" + +#: src/modules/filesystem.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"mod garden;\n" +"```" +msgstr "" + +#: src/modules/filesystem.md:9 +#, fuzzy +msgid "The `garden` module content is found at:" +msgstr "Το περιεχόμενο της ενότητας «garden» βρίσκεται στη διεύθυνση:" + +#: src/modules/filesystem.md:11 +#, fuzzy +msgid "" +"* `src/garden.rs` (modern Rust 2018 style)\n" +"* `src/garden/mod.rs` (older Rust 2015 style)" +msgstr "" +"* `src/garden.rs` (μοντέρνο στυλ Rust 2018)\n" +"* `src/garden/mod.rs` (παλαιότερο στυλ Rust 2015)" + +#: src/modules/filesystem.md:14 +#, fuzzy +msgid "Similarly, a `garden::vegetables` module can be found at:" +msgstr "" +"Ομοίως, μια ενότητα «garden:: λαχανικά» μπορεί να βρεθεί στη διεύθυνση:" + +#: src/modules/filesystem.md:16 +#, fuzzy +msgid "" +"* `src/garden/vegetables.rs` (modern Rust 2018 style)\n" +"* `src/garden/vegetables/mod.rs` (older Rust 2015 style)" +msgstr "" +"* `src/garden/vegetables.rs` (μοντέρνο στυλ Rust 2018)\n" +"* `src/garden/vegetables/mod.rs` (παλαιότερο στυλ Rust 2015)" + +#: src/modules/filesystem.md:19 +#, fuzzy +msgid "The `crate` root is in:" +msgstr "Η ρίζα «κλουβί» βρίσκεται σε:" + +#: src/modules/filesystem.md:21 +#, fuzzy +msgid "" +"* `src/lib.rs` (for a library crate)\n" +"* `src/main.rs` (for a binary crate)" +msgstr "" +"* `src/lib.rs` (για κλουβί βιβλιοθήκης)\n" +"* `src/main.rs` (για δυαδικό κιβώτιο)" + +#: src/modules/filesystem.md:24 +msgid "" +"Modules defined in files can be documented, too, using \"inner doc " +"comments\".\n" +"These document the item that contains them -- in this case, a module." +msgstr "" + +#: src/modules/filesystem.md:27 +msgid "" +"```rust,editable,compile_fail\n" +"//! 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" +"\n" +"// Harvest the produce in the garden that is ready.\n" +"fn harvest(garden: &mut Garden) { todo!() }\n" +"```" +msgstr "" + +#: src/modules/filesystem.md:40 +msgid "" +"* The change from `module/mod.rs` to `module.rs` doesn't preclude the use of " +"submodules in Rust 2018.\n" +" (It was mandatory in Rust 2015.)\n" +"\n" +" The following is valid:\n" +"\n" +" ```ignore\n" +" src/\n" +" ├── main.rs\n" +" ├── top_module.rs\n" +" └── top_module/\n" +" └── sub_module.rs\n" +" ```\n" +"\n" +"* The main reason for the change is to prevent many files named `mod.rs`, " +"which can be hard\n" +" to distinguish in IDEs.\n" +"\n" +"* Rust will look for modules in `modulename/mod.rs` and `modulename.rs`, but " +"this can be changed\n" +" with a compiler directive:\n" +"\n" +" ```rust,ignore\n" +" #[path = \"some/path.rs\"]\n" +" mod some_module { }\n" +" ```\n" +"\n" +" This is useful, for example, if you would like to place tests for a module " +"in a file named\n" +" `some_module_test.rs`, similar to the convention in Go." +msgstr "" + +#: src/exercises/day-2/afternoon.md:1 +#, fuzzy +msgid "# Day 2: Afternoon Exercises" +msgstr "# Ημέρα 2: Απογευματινές Ασκήσεις" + +#: src/exercises/day-2/afternoon.md:3 +#, fuzzy +msgid "The exercises for this afternoon will focus on strings and iterators." +msgstr "" +"Οι ασκήσεις για σήμερα το απόγευμα θα επικεντρωθούν σε έγχορδα και " +"επαναλήπτες." + +#: src/exercises/day-2/luhn.md:1 +#, fuzzy +msgid "# Luhn Algorithm" +msgstr "# Αλγόριθμος Luhn" + +#: src/exercises/day-2/luhn.md:3 +#, fuzzy +msgid "" +"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used " +"to\n" +"validate credit card numbers. The algorithm takes a string as input and does " +"the\n" +"following to validate the credit card number:" +msgstr "" +"Ο [αλγόριθμος Luhn](https://en.wikipedia.org/wiki/Luhn_algorithm) " +"χρησιμοποιείται για\n" +"επικύρωση αριθμών πιστωτικών καρτών. Ο αλγόριθμος παίρνει μια συμβολοσειρά " +"ως είσοδο και κάνει το\n" +"παρακάτω για να επικυρώσετε τον αριθμό της πιστωτικής κάρτας:" + +#: src/exercises/day-2/luhn.md:7 +msgid "" +"* Ignore all spaces. Reject number with less than two digits.\n" +"\n" +"* Moving from right to left, double every second digit: for the number " +"`1234`,\n" +" we double `3` and `1`.\n" +"\n" +"* After doubling a digit, sum the digits. So doubling `7` becomes `14` " +"which\n" +" becomes `5`.\n" +"\n" +"* Sum all the undoubled and doubled digits.\n" +"\n" +"* The credit card number is valid if the sum ends with `0`." +msgstr "" + +#: src/exercises/day-2/luhn.md:19 +#, fuzzy +msgid "" +"Copy the following code to and implement the\n" +"function:" +msgstr "" +"Αντιγράψτε τον παρακάτω κώδικα στο και " +"εφαρμόστε το\n" +"λειτουργία:" + +#: src/exercises/day-2/luhn.md:23 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:1 +#, fuzzy +msgid "# Strings and Iterators" +msgstr "# Χορδές και επαναλήπτες" + +#: src/exercises/day-2/strings-iterators.md:3 +#, fuzzy +msgid "" +"In this exercise, you are implementing a routing component of a web server. " +"The\n" +"server is configured with a number of _path prefixes_ which are matched " +"against\n" +"_request paths_. The path prefixes can contain a wildcard character which\n" +"matches a full segment. See the unit tests below." +msgstr "" +"Σε αυτήν την άσκηση, υλοποιείτε ένα στοιχείο δρομολόγησης ενός διακομιστή " +"web. ο\n" +"Ο διακομιστής έχει ρυθμιστεί με έναν αριθμό προθεμάτων _διαδρομών_ με τα " +"οποία αντιστοιχίζονται\n" +"_αίτημα μονοπατιών_. Τα προθέματα διαδρομής μπορούν να περιέχουν έναν " +"χαρακτήρα μπαλαντέρ που\n" +"αντιστοιχεί σε ένα πλήρες τμήμα. Δείτε τις δοκιμές μονάδας παρακάτω." + +#: src/exercises/day-2/strings-iterators.md:8 +#, fuzzy +msgid "" +"Copy the following code to and make the tests\n" +"pass. Try avoiding allocating a `Vec` for your intermediate results:" +msgstr "" +"Αντιγράψτε τον παρακάτω κώδικα στο και κάντε " +"τις δοκιμές\n" +"πέρασμα. Προσπαθήστε να αποφύγετε να εκχωρήσετε ένα «Vec» για τα ενδιάμεσα " +"αποτελέσματά σας:" + +#: src/exercises/day-2/strings-iterators.md:12 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/" +"abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/" +"books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/" +"publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/" +"publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"```" +msgstr "" + +#: src/welcome-day-3.md:1 +#, fuzzy +msgid "# Welcome to Day 3" +msgstr "# Καλώς ήρθατε στην Ημέρα 3" + +#: src/welcome-day-3.md:3 +#, fuzzy +msgid "Today, we will cover some more advanced topics of Rust:" +msgstr "Σήμερα, θα καλύψουμε μερικά πιο προχωρημένα θέματα του Rust:" + +#: src/welcome-day-3.md:5 +msgid "" +"* Traits: deriving traits, default methods, and important standard library\n" +" traits.\n" +"\n" +"* Generics: generic data types, generic methods, monomorphization, and " +"trait\n" +" objects.\n" +"\n" +"* Error handling: panics, `Result`, and the try operator `?`.\n" +"\n" +"* Testing: unit tests, documentation tests, and integration tests.\n" +"\n" +"* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" +" functions." +msgstr "" + +#: src/traits.md:1 +#, fuzzy +msgid "# Traits" +msgstr "# Χαρακτηριστικά" + +#: src/traits.md:3 +#, fuzzy +msgid "" +"Rust lets you abstract over types with traits. They're similar to interfaces:" +msgstr "" +"Το Rust σάς επιτρέπει να αφηρείτε τους τύπους με χαρακτηριστικά. Είναι " +"παρόμοια με τις διεπαφές:" + +#: src/traits.md:5 +msgid "" +"```rust,editable\n" +"trait Pet {\n" +" fn name(&self) -> String;\n" +"}\n" +"\n" +"struct Dog {\n" +" name: String,\n" +"}\n" +"\n" +"struct Cat;\n" +"\n" +"impl Pet for Dog {\n" +" fn name(&self) -> String {\n" +" self.name.clone()\n" +" }\n" +"}\n" +"\n" +"impl Pet for Cat {\n" +" fn name(&self) -> String {\n" +" String::from(\"The cat\") // No name, cats won't respond to it " +"anyway.\n" +" }\n" +"}\n" +"\n" +"fn greet(pet: &impl Pet) {\n" +" println!(\"Who's a cutie? {} is!\", pet.name());\n" +"}\n" +"\n" +"fn main() {\n" +" let fido = Dog { name: \"Fido\".into() };\n" +" greet(&fido);\n" +"\n" +" let captain_floof = Cat;\n" +" greet(&captain_floof);\n" +"}\n" +"```" +msgstr "" + +#: src/traits.md:43 +msgid "" +"* Later sections will get into more detail on generic functions like " +"`greet`.\n" +" For now, students only need to know that `greet` will operate on a " +"reference\n" +" to anything that implements `Pet`." +msgstr "" + +#: src/traits/deriving-traits.md:1 +#, fuzzy +msgid "# Deriving Traits" +msgstr "# Απόκτηση γνωρισμάτων" + +#: src/traits/deriving-traits.md:3 +#, fuzzy +msgid "You can let the compiler derive a number of traits:" +msgstr "" +"Μπορείτε να αφήσετε τον μεταγλωττιστή να αντλήσει έναν αριθμό " +"χαρακτηριστικών:" + +#: src/traits/deriving-traits.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Clone, PartialEq, Eq, Default)]\n" +"struct Player {\n" +" name: String,\n" +" strength: u8,\n" +" hit_points: u8,\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Player::default();\n" +" let p2 = p1.clone();\n" +" println!(\"Is {:?}\\nequal to {:?}?\\nThe answer is {}!\", &p1, &p2,\n" +" if p1 == p2 { \"yes\" } else { \"no\" });\n" +"}\n" +"```" +msgstr "" + +#: src/traits/default-methods.md:1 +#, fuzzy +msgid "# Default Methods" +msgstr "# Προεπιλεγμένες μέθοδοι" + +#: src/traits/default-methods.md:3 +#, fuzzy +msgid "Traits can implement behavior in terms of other trait methods:" +msgstr "" +"Τα χαρακτηριστικά μπορούν να εφαρμόσουν τη συμπεριφορά σε σχέση με άλλες " +"μεθόδους χαρακτηριστικών:" + +#: src/traits/default-methods.md:5 +msgid "" +"```rust,editable\n" +"trait Equals {\n" +" fn equal(&self, other: &Self) -> bool;\n" +" fn not_equal(&self, other: &Self) -> bool {\n" +" !self.equal(other)\n" +" }\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"struct Centimeter(i16);\n" +"\n" +"impl Equals for Centimeter {\n" +" fn equal(&self, other: &Centimeter) -> bool {\n" +" self.0 == other.0\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let a = Centimeter(10);\n" +" let b = Centimeter(20);\n" +" println!(\"{a:?} equals {b:?}: {}\", a.equal(&b));\n" +" println!(\"{a:?} not_equals {b:?}: {}\", a.not_equal(&b));\n" +"}\n" +"```" +msgstr "" + +#: src/traits/important-traits.md:1 +#, fuzzy +msgid "# Important Traits" +msgstr "# Σημαντικά Χαρακτηριστικά" + +#: src/traits/important-traits.md:3 +#, fuzzy +msgid "" +"We will now look at some of the most common traits of the Rust standard " +"library:" +msgstr "" +"Θα δούμε τώρα μερικά από τα πιο κοινά χαρακτηριστικά της βασικής βιβλιοθήκης " +"Rust:" + +#: src/traits/important-traits.md:5 +#, fuzzy +msgid "" +"* [`Iterator`][1] and [`IntoIterator`][2] used in `for` loops,\n" +"* [`From`][3] and [`Into`][4] used to convert values,\n" +"* [`Read`][5] and [`Write`][6] used for IO,\n" +"* [`Add`][7], [`Mul`][8], ... used for operator overloading, and\n" +"* [`Drop`][9] used for defining destructors.\n" +"* [`Default`][10] used to construct a default instance of a type." +msgstr "" +"* «Iterator» και «IntoIterator» που χρησιμοποιούνται σε βρόχους «for»,\n" +"* Τα \"From\" και \"Into\" χρησιμοποιούνται για τη μετατροπή τιμών,\n" +"* «Read» και «Write» που χρησιμοποιούνται για IO,\n" +"* «Προσθήκη», «Mul», ... χρησιμοποιείται για υπερφόρτωση χειριστή και\n" +"* «Drop» που χρησιμοποιείται για τον ορισμό των καταστροφέων." + +#: src/traits/iterator.md:1 +#, fuzzy +msgid "# Iterators" +msgstr "# Επαναληπτικοί" + +#: src/traits/iterator.md:3 +#, fuzzy +msgid "You can implement the [`Iterator`][1] trait on your own types:" +msgstr "" +"Μπορείτε να εφαρμόσετε το χαρακτηριστικό «Iterator» στους δικούς σας τύπους:" + +#: src/traits/iterator.md:5 +msgid "" +"```rust,editable\n" +"struct Fibonacci {\n" +" curr: u32,\n" +" next: u32,\n" +"}\n" +"\n" +"impl Iterator for Fibonacci {\n" +" type Item = u32;\n" +"\n" +" fn next(&mut self) -> Option {\n" +" let new_next = self.curr + self.next;\n" +" self.curr = self.next;\n" +" self.next = new_next;\n" +" Some(self.curr)\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let fib = Fibonacci { curr: 0, next: 1 };\n" +" for (i, n) in fib.enumerate().take(5) {\n" +" println!(\"fib({i}): {n}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/traits/iterator.md:32 +msgid "" +"* The `Iterator` trait implements many common functional programming " +"operations over collections \n" +" (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can " +"find all the documentation\n" +" about them. In Rust these functions should produce the code as efficient " +"as equivalent imperative\n" +" implementations.\n" +" \n" +"* `IntoIterator` is the trait that makes for loops work. It is implemented " +"by collection types such as\n" +" `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also " +"implement it. This is why\n" +" you can iterate over a vector with `for i in some_vec { .. }` but\n" +" `some_vec.next()` doesn't exist." +msgstr "" + +#: src/traits/from-iterator.md:1 +#, fuzzy +msgid "# FromIterator" +msgstr "# FromIterator" + +#: src/traits/from-iterator.md:3 +#, fuzzy +msgid "" +"[`FromIterator`][1] lets you build a collection from an [`Iterator`][2]." +msgstr "" +"Το \"FromIterator\" σάς επιτρέπει να δημιουργήσετε μια συλλογή από ένα " +"\"Iterator\"." + +#: src/traits/from-iterator.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let primes = vec![2, 3, 5, 7];\n" +" let prime_squares = primes\n" +" .into_iter()\n" +" .map(|prime| prime * prime)\n" +" .collect::>();\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-iterator.md:17 +#, fuzzy +msgid "" +"`Iterator` implements\n" +"`fn collect(self) -> B\n" +"where\n" +" B: FromIterator,\n" +" Self: Sized`" +msgstr "" +"Το «Iterator» υλοποιεί\n" +"`fn collect(self) -> B\n" +"που\n" +" Β: FromIterator,\n" +" Self: Μέγεθος`" + +#: src/traits/from-iterator.md:23 +#, fuzzy +msgid "" +"There are also implementations which let you do cool things like convert an\n" +"`Iterator>` into a `Result, E>`." +msgstr "" +"Υπάρχουν επίσης υλοποιήσεις που σας επιτρέπουν να κάνετε καταπληκτικά " +"πράγματα όπως η μετατροπή ενός\n" +"\"Iterator>\" σε ένα \"Result, E>\"." + +#: src/traits/from-into.md:1 +#, fuzzy +msgid "# `From` and `Into`" +msgstr "# «Από» και «Μέσα»." + +#: src/traits/from-into.md:3 +#, fuzzy +msgid "" +"Types implement [`From`][1] and [`Into`][2] to facilitate type conversions:" +msgstr "" +"Οι τύποι εφαρμόζουν τα «Από» και «Μέσα» για να διευκολύνουν τις μετατροπές " +"τύπων:" + +#: src/traits/from-into.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s = String::from(\"hello\");\n" +" let addr = std::net::Ipv4Addr::from([127, 0, 0, 1]);\n" +" let one = i16::from(true);\n" +" let bigger = i32::from(123i16);\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-into.md:15 +#, fuzzy +msgid "" +"[`Into`][2] is automatically implemented when [`From`][1] is implemented:" +msgstr "Το \"Into\" υλοποιείται αυτόματα όταν υλοποιείται το \"From\":" + +#: src/traits/from-into.md:17 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s: String = \"hello\".into();\n" +" let addr: std::net::Ipv4Addr = [127, 0, 0, 1].into();\n" +" let one: i16 = true.into();\n" +" let bigger: i32 = 123i16.into();\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-into.md:29 +#, fuzzy +msgid "" +"* That's why it is common to only implement `From`, as your type will get " +"`Into` implementation too.\n" +"* When declaring a function argument input type like \"anything that can be " +"converted into a `String`\", the rule is opposite, you should use `Into`.\n" +" Your function will accept types that implement `From` and those that " +"_only_ implement `Into`.\n" +" " +msgstr "" +"<λεπτομέρειες>\n" +" \n" +"* Αυτός είναι ο λόγος για τον οποίο είναι σύνηθες να εφαρμόζετε μόνο το " +"\"From\", καθώς ο τύπος σας θα λάβει επίσης την εφαρμογή \"Into\".\n" +"* Όταν δηλώνετε έναν τύπο εισόδου ορίσματος συνάρτησης όπως \"οτιδήποτε " +"μπορεί να μετατραπεί σε \"Συμβολοσειρά\", ο κανόνας είναι αντίθετος, θα " +"πρέπει να χρησιμοποιήσετε το \"Into\".\n" +" Η συνάρτησή σας θα δέχεται τύπους που υλοποιούν το \"From\" και εκείνους " +"που _only_ υλοποιούν το \"Into\".\n" +" \n" +"" + +#: src/traits/read-write.md:1 +#, fuzzy +msgid "# `Read` and `Write`" +msgstr "# «Διαβάστε» και «Γράψτε»." + +#: src/traits/read-write.md:3 +#, fuzzy +msgid "" +"Using [`Read`][1] and [`BufRead`][2], you can abstract over `u8` sources:" +msgstr "" +"Χρησιμοποιώντας το \"Read\" και το \"BufRead\", μπορείτε να αφαιρέσετε τις " +"πηγές \"u8\":" + +#: src/traits/read-write.md:5 +msgid "" +"```rust,editable\n" +"use std::io::{BufRead, BufReader, Read, Result};\n" +"\n" +"fn count_lines(reader: R) -> usize {\n" +" let buf_reader = BufReader::new(reader);\n" +" buf_reader.lines().count()\n" +"}\n" +"\n" +"fn main() -> Result<()> {\n" +" let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" +" println!(\"lines in slice: {}\", count_lines(slice));\n" +"\n" +" let file = std::fs::File::open(std::env::current_exe()?)?;\n" +" println!(\"lines in file: {}\", count_lines(file));\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/read-write.md:23 +#, fuzzy +msgid "Similarly, [`Write`][3] lets you abstract over `u8` sinks:" +msgstr "" +"Παρομοίως, το «Write» σάς επιτρέπει να κάνετε αφηρήσεις πάνω από τα νεροχύτα " +"«u8»:" + +#: src/traits/read-write.md:25 +msgid "" +"```rust,editable\n" +"use std::io::{Result, Write};\n" +"\n" +"fn log(writer: &mut W, msg: &str) -> Result<()> {\n" +" writer.write_all(msg.as_bytes())?;\n" +" writer.write_all(\"\\n\".as_bytes())\n" +"}\n" +"\n" +"fn main() -> Result<()> {\n" +" let mut buffer = Vec::new();\n" +" log(&mut buffer, \"Hello\")?;\n" +" log(&mut buffer, \"World\")?;\n" +" println!(\"Logged: {:?}\", buffer);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/operators.md:1 +#, fuzzy +msgid "# `Add`, `Mul`, ..." +msgstr "# \"Προσθήκη\", \"Mul\", ..." + +#: src/traits/operators.md:3 +#, fuzzy +msgid "Operator overloading is implemented via traits in [`std::ops`][1]:" +msgstr "" +"Η υπερφόρτωση χειριστή υλοποιείται μέσω χαρακτηριστικών στο `std::ops`:" + +#: src/traits/operators.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Copy, Clone)]\n" +"struct Point { x: i32, y: i32 }\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self {\n" +" Self {x: self.x + other.x, y: self.y + other.y}\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point { x: 10, y: 20 };\n" +" let p2 = Point { x: 100, y: 200 };\n" +" println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" +"}\n" +"```" +msgstr "" + +#: src/traits/operators.md:26 src/traits/drop.md:34 +#, fuzzy +msgid "Discussion points:" +msgstr "Σημεία συζήτησης:" + +#: src/traits/operators.md:28 +#, fuzzy +msgid "" +"* You could implement `Add` for `&Point`. In which situations is that " +"useful? \n" +" * Answer: `Add:add` consumes `self`. If type `T` for which you are\n" +" 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" +" associated types (like `Output`) are controlled by the implementor " +"of a\n" +" trait." +msgstr "" +"* Θα μπορούσατε να εφαρμόσετε το \"Add\" για το \"&Point\". Σε ποιες " +"περιπτώσεις είναι χρήσιμο;\n" +" * Απάντηση: Το «Προσθήκη: Προσθήκη» καταναλώνει τον «εαυτό». Αν " +"πληκτρολογήστε `T` για το οποίο είστε\n" +" Η υπερφόρτωση του χειριστή δεν είναι «Αντιγραφή», θα πρέπει να " +"εξετάσετε την υπερφόρτωση\n" +" ο χειριστής για το «&T» επίσης. Αυτό αποφεύγει την περιττή " +"κλωνοποίηση στο\n" +" τοποθεσία κλήσης.\n" +"* Γιατί το \"Έξοδος\" είναι συσχετισμένος τύπος; Θα μπορούσε να γίνει " +"παράμετρος τύπου;\n" +" * Σύντομη απάντηση: Οι παράμετροι τύπου ελέγχονται από τον καλούντα, " +"αλλά\n" +" οι συσχετισμένοι τύποι (όπως \"Έξοδος\") ελέγχονται από τον " +"υλοποιητή του a\n" +" χαρακτηριστικό." + +#: src/traits/drop.md:1 +#, fuzzy +msgid "# The `Drop` Trait" +msgstr "# Το χαρακτηριστικό «Drop»." + +#: src/traits/drop.md:3 +#, fuzzy +msgid "" +"Values which implement [`Drop`][1] can specify code to run when they go out " +"of scope:" +msgstr "" +"Οι τιμές που εφαρμόζουν το \"Drop\" μπορούν να καθορίσουν τον κώδικα που θα " +"εκτελείται όταν εξέρχονται από το πεδίο εφαρμογής:" + +#: src/traits/drop.md:5 +msgid "" +"```rust,editable\n" +"struct Droppable {\n" +" name: &'static str,\n" +"}\n" +"\n" +"impl Drop for Droppable {\n" +" fn drop(&mut self) {\n" +" println!(\"Dropping {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let a = Droppable { name: \"a\" };\n" +" {\n" +" let b = Droppable { name: \"b\" };\n" +" {\n" +" let c = Droppable { name: \"c\" };\n" +" let d = Droppable { name: \"d\" };\n" +" println!(\"Exiting block B\");\n" +" }\n" +" println!(\"Exiting block A\");\n" +" }\n" +" drop(a);\n" +" println!(\"Exiting main\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/drop.md:36 +#, fuzzy +msgid "" +"* Why doesn't `Drop::drop` take `self`?\n" +" * Short-answer: If it did, `std::mem::drop` would be called at the end " +"of\n" +" the block, resulting in another call to `Drop::drop`, and a stack\n" +" overflow!\n" +"* Try replacing `drop(a)` with `a.drop()`." +msgstr "" +"* Γιατί το «Drop::drop» δεν σημαίνει «self»;\n" +" * Σύντομη απάντηση: Εάν συνέβαινε, το `std::mem::drop` θα καλούνταν στο " +"τέλος του\n" +" το μπλοκ, με αποτέλεσμα μια άλλη κλήση στο «Drop::drop» και μια " +"στοίβα\n" +" ξεχείλισμα!\n" +"* Δοκιμάστε να αντικαταστήσετε το «drop(a)» με το «a.drop()»." + +#: src/traits/default.md:1 +#, fuzzy +msgid "# The `Default` Trait" +msgstr "# Το χαρακτηριστικό «Drop»." + +#: src/traits/default.md:3 +msgid "[`Default`][1] trait provides a default implementation of a trait." +msgstr "" + +#: src/traits/default.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Default)]\n" +"struct Derived {\n" +" x: u32,\n" +" y: String,\n" +" z: Implemented,\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"struct Implemented(String);\n" +"\n" +"impl Default for Implemented {\n" +" fn default() -> Self {\n" +" Self(\"John Smith\".into())\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let default_struct: Derived = Default::default();\n" +" println!(\"{default_struct:#?}\");\n" +"\n" +" let almost_default_struct = Derived {\n" +" y: \"Y is set!\".into(),\n" +" ..Default::default()\n" +" };\n" +" println!(\"{almost_default_struct:#?}\");\n" +"\n" +" let nothing: Option = None;\n" +" println!(\"{:#?}\", nothing.unwrap_or_default());\n" +"}\n" +"\n" +"```" +msgstr "" + +#: src/traits/default.md:40 +msgid "" +" * It can be implemented directly or it can be derived via " +"`#[derive(Default)]`.\n" +" * Derived implementation will produce an instance where all fields are set " +"to their default values.\n" +" * This means all types in the struct must implement `Default` too.\n" +" * Standard Rust types often implement `Default` with reasonable values (e." +"g. `0`, `\"\"`, etc).\n" +" * The partial struct copy works nicely with default.\n" +" * Rust standard library is aware that types can implement `Default` and " +"provides convenience methods that use it." +msgstr "" + +#: src/generics.md:1 +#, fuzzy +msgid "# Generics" +msgstr "# Γενόσημα" + +#: src/generics.md:3 +#, fuzzy +msgid "" +"Rust support generics, which lets you abstract an algorithm (such as " +"sorting)\n" +"over the types used in the algorithm." +msgstr "" +"Γενικά υποστήριξη σκουριάς, που σας επιτρέπει να αφαιρέσετε έναν αλγόριθμο " +"(όπως ταξινόμηση)\n" +"πάνω από τους τύπους που χρησιμοποιούνται στον αλγόριθμο." + +#: src/generics/data-types.md:1 +msgid "# Generic Data Types" +msgstr "# Γενικοί τύποι δεδομένων" + +#: src/generics/data-types.md:3 +#, fuzzy +msgid "You can use generics to abstract over the concrete field type:" +msgstr "" +"Μπορείτε να χρησιμοποιήσετε γενικά για να αφαιρέσετε τον συγκεκριμένο τύπο " +"πεδίου:" + +#: src/generics/data-types.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point {\n" +" x: T,\n" +" y: T,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Point { x: 5, y: 10 };\n" +" let float = Point { x: 1.0, y: 4.0 };\n" +" println!(\"{integer:?} and {float:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/methods.md:1 +#, fuzzy +msgid "# Generic Methods" +msgstr "# Γενικές Μέθοδοι" + +#: src/generics/methods.md:3 +#, fuzzy +msgid "You can declare a generic type on your `impl` block:" +msgstr "Μπορείτε να δηλώσετε έναν γενικό τύπο στο μπλοκ `impl`:" + +#: src/generics/methods.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(T, T);\n" +"\n" +"impl Point {\n" +" fn x(&self) -> &T {\n" +" &self.0 // + 10\n" +" }\n" +"\n" +" // fn set_x(&mut self, x: T)\n" +"}\n" +"\n" +"fn main() {\n" +" let p = Point(5, 10);\n" +" println!(\"p.x = {}\", p.x());\n" +"}\n" +"```" +msgstr "" + +#: src/generics/methods.md:25 +#, fuzzy +msgid "" +"* *Q:* Why `T` is specified twice in `impl Point {}`? Isn't that " +"redundant?\n" +" * This is because it is a generic implementation section for generic " +"type. They are independently generic.\n" +" * It means these methods are defined for any `T`.\n" +" * It is possible to write `impl Point { .. }`. \n" +" * `Point` is still generic and you can use `Point`, but methods " +"in this block will only be available for `Point`." +msgstr "" +"* *Ε:* Γιατί το `T` καθορίζεται δύο φορές στο `impl Point {}`; Δεν " +"είναι περιττό;\n" +" * Αυτό συμβαίνει επειδή είναι μια γενική ενότητα υλοποίησης για γενικό " +"τύπο. Είναι ανεξάρτητα γενικά.\n" +" * Σημαίνει ότι αυτές οι μέθοδοι ορίζονται για οποιοδήποτε «T».\n" +" * Είναι δυνατό να γράψετε `impl Point { .. }`.\n" +" * Το \"Point\" εξακολουθεί να είναι γενικό και μπορείτε να " +"χρησιμοποιήσετε το \"Point\", αλλά οι μέθοδοι σε αυτό το μπλοκ θα είναι " +"διαθέσιμες μόνο για το \"Point\"." + +#: src/generics/trait-bounds.md:1 +#, fuzzy +msgid "# Trait Bounds" +msgstr "# Όρια χαρακτηριστικών" + +#: src/generics/trait-bounds.md:3 +#, fuzzy +msgid "" +"When working with generics, you often want to require the types to " +"implement\n" +"some trait, so that you can call this trait's methods." +msgstr "" +"Όταν εργάζεστε με γενόσημα, συχνά θέλετε να περιορίσετε τους τύπους. " +"Μπορείτε να το κάνετε αυτό\n" +"με \"T: Trait\" ή \"immpl Trait\":" + +#: src/generics/trait-bounds.md:6 +msgid "You can do this with `T: Trait` or `impl Trait`:" +msgstr "" + +#: src/generics/trait-bounds.md:8 +msgid "" +"```rust,editable\n" +"fn duplicate(a: T) -> (T, T) {\n" +" (a.clone(), a.clone())\n" +"}\n" +"\n" +"// Syntactic sugar for:\n" +"// fn add_42_millions>(x: T) -> i32 {\n" +"fn add_42_millions(x: impl Into) -> i32 {\n" +" x.into() + 42_000_000\n" +"}\n" +"\n" +"// struct NotClonable;\n" +"\n" +"fn main() {\n" +" let foo = String::from(\"foo\");\n" +" let pair = duplicate(foo);\n" +" println!(\"{pair:?}\");\n" +"\n" +" let many = add_42_millions(42_i8);\n" +" println!(\"{many}\");\n" +" let many_more = add_42_millions(10_000_000);\n" +" println!(\"{many_more}\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-bounds.md:35 +msgid "Show a `where` clause, students will encounter it when reading code." +msgstr "" + +#: src/generics/trait-bounds.md:37 +msgid "" +"```rust,ignore\n" +"fn duplicate(a: T) -> (T, T)\n" +"where\n" +" T: Clone,\n" +"{\n" +" (a.clone(), a.clone())\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-bounds.md:46 +#, fuzzy +msgid "" +"* It declutters the function signature if you have many parameters.\n" +"* It has additional features making it more powerful.\n" +" * If someone asks, the extra feature is that the type on the left of \":" +"\" can be arbitrary, like `Option`.\n" +" " +msgstr "" +"* Καταργεί την υπογραφή της συνάρτησης εάν έχετε πολλές παραμέτρους.\n" +"* Διαθέτει πρόσθετα χαρακτηριστικά που το κάνουν πιο ισχυρό.\n" +" * Εάν κάποιος ρωτήσει, το επιπλέον χαρακτηριστικό είναι ότι ο τύπος στα " +"αριστερά του \":\" μπορεί να είναι αυθαίρετος, όπως \"Επιλογή\".\n" +" \n" +"" + +#: src/generics/impl-trait.md:1 +#, fuzzy +msgid "# `impl Trait`" +msgstr "# `impl Trait`" + +#: src/generics/impl-trait.md:3 +#, fuzzy +msgid "" +"Similar to trait bounds, an `impl Trait` syntax can be used in function\n" +"arguments and return values:" +msgstr "" +"Παρόμοια με τα όρια χαρακτηριστικών, μια σύνταξη «impl Trait» μπορεί να " +"χρησιμοποιηθεί στη συνάρτηση\n" +"ορίσματα και τιμές επιστροφής:" + +#: src/generics/impl-trait.md:6 +msgid "" +"```rust,editable\n" +"use std::fmt::Display;\n" +"\n" +"fn get_x(name: impl Display) -> impl Display {\n" +" format!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let x = get_x(\"foo\");\n" +" println!(\"{x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/impl-trait.md:19 +#, fuzzy +msgid "* `impl Trait` allows you to work with types which you cannot name." +msgstr "" +"* Το \"impl Trait\" δεν μπορεί να χρησιμοποιηθεί με τη σύνταξη \"::<>\" " +"turbo fish.\n" +"* Το \"impl Trait\" σάς επιτρέπει να εργάζεστε με τύπους που δεν μπορείτε να " +"ονομάσετε." + +#: src/generics/impl-trait.md:23 +#, fuzzy +msgid "" +"The meaning of `impl Trait` is a bit different in the different positions." +msgstr "" +"Η έννοια του «impl Trait» είναι λίγο διαφορετική στις διαφορετικές θέσεις." + +#: src/generics/impl-trait.md:25 +#, fuzzy +msgid "" +"* For a parameter, `impl Trait` is like an anonymous generic parameter with " +"a trait bound.\n" +"\n" +"* For a return type, it means that the return type is some concrete type " +"that implements the trait,\n" +" without naming the type. This can be useful when you don't want to expose " +"the concrete type in a\n" +" public API.\n" +"\n" +" Inference is hard in return position. A function returning `impl Foo` " +"picks\n" +" the concrete type it returns, without writing it out in the source. A " +"function\n" +" returning a generic type like `collect() -> B` can return any type\n" +" satisfying `B`, and the caller may need to choose one, such as with `let " +"x:\n" +" Vec<_> = foo.collect()` or with the turbofish, `foo.collect::>()`." +msgstr "" +"* Για μια παράμετρο, το \"impl Trait\" είναι σαν μια ανώνυμη γενική " +"παράμετρος με δεσμευμένο χαρακτηριστικό.\n" +"* Για έναν τύπο επιστροφής, σημαίνει ότι ο τύπος επιστροφής είναι κάποιος " +"συγκεκριμένος τύπος που υλοποιεί το χαρακτηριστικό,\n" +" χωρίς να ονομάσουμε τον τύπο. Αυτό μπορεί να είναι χρήσιμο όταν δεν θέλετε " +"να εκθέσετε τον τύπο σκυροδέματος στο α\n" +" δημόσιο API." + +#: src/generics/impl-trait.md:37 +#, fuzzy +msgid "" +"This example is great, because it uses `impl Display` twice. It helps to " +"explain that\n" +"nothing here enforces that it is _the same_ `impl Display` type. If we used " +"a single \n" +"`T: Display`, it would enforce the constraint that input `T` and return `T` " +"type are the same type.\n" +"It would not work for this particular function, as the type we expect as " +"input is likely not\n" +"what `format!` returns. If we wanted to do the same via `: Display` syntax, " +"we'd need two\n" +"independent generic parameters." +msgstr "" +"Αυτό το παράδειγμα είναι υπέροχο, επειδή χρησιμοποιεί το \"immpl Display\" " +"δύο φορές. Βοηθά να το εξηγήσω\n" +"τίποτα εδώ δεν επιβάλλει ότι είναι _ο ίδιος_ τύπος \"impl Display\". Αν " +"χρησιμοποιούσαμε ένα μονό\n" +"«T: Εμφάνιση», θα επιβάλει τον περιορισμό ότι η είσοδος «T» και η επιστροφή " +"του τύπου «T» είναι του ίδιου τύπου.\n" +"Δεν θα λειτουργούσε για τη συγκεκριμένη λειτουργία, καθώς ο τύπος που " +"περιμένουμε ως είσοδο είναι πιθανό να μην είναι\n" +"τι «μορφή!» επιστρέφει. Αν θέλαμε να κάνουμε το ίδιο μέσω της σύνταξης `: " +"Display`, θα χρειαζόμασταν δύο\n" +"ανεξάρτητες γενικές παραμέτρους.\n" +" \n" +"" + +#: src/generics/closures.md:1 +#, fuzzy +msgid "# Closures" +msgstr "# Κλείσιμο" + +#: src/generics/closures.md:3 +#, fuzzy +msgid "" +"Closures or lambda expressions have types which cannot be named. However, " +"they\n" +"implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:" +msgstr "" +"Τα κλεισίματα ή οι εκφράσεις λάμδα έχουν τύπους που δεν μπορούν να " +"ονομαστούν. Ωστόσο, αυτοί\n" +"εφαρμογή ειδικού [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html) και\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) " +"χαρακτηριστικά:" + +#: src/generics/closures.md:8 +msgid "" +"```rust,editable\n" +"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" +" println!(\"Calling function on {input}\");\n" +" func(input)\n" +"}\n" +"\n" +"fn main() {\n" +" let add_3 = |x| x + 3;\n" +" let mul_5 = |x| x * 5;\n" +"\n" +" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" +" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" +"}\n" +"```" +msgstr "" + +#: src/generics/closures.md:25 +#, fuzzy +msgid "" +"If you have an `FnOnce`, you may only call it once. It might consume " +"captured values." +msgstr "" +"Εάν έχετε ένα \"FnOnce\", μπορείτε να το καλέσετε μόνο μία φορά. Μπορεί να " +"καταναλώσει καταγεγραμμένες τιμές." + +#: src/generics/closures.md:27 +#, fuzzy +msgid "" +"An `FnMut` might mutate captured values, so you can call it multiple times " +"but not concurrently." +msgstr "" +"Ένα \"FnMut\" μπορεί να μεταλλάξει τις καταγεγραμμένες τιμές, ώστε να " +"μπορείτε να το καλέσετε πολλές φορές αλλά όχι ταυτόχρονα." + +#: src/generics/closures.md:29 +#, fuzzy +msgid "" +"An `Fn` neither consumes nor mutates captured values, or perhaps captures " +"nothing at all, so it can\n" +"be called multiple times concurrently." +msgstr "" +"Ένα \"Fn\" ούτε καταναλώνει ούτε μεταλλάσσει τις καταγεγραμμένες τιμές ή " +"ίσως δεν καταγράφει τίποτα απολύτως, επομένως μπορεί\n" +"καλείται πολλές φορές ταυτόχρονα." + +#: src/generics/closures.md:32 +#, fuzzy +msgid "" +"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. " +"I.e. you can use an\n" +"`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever " +"an `FnMut` or `FnOnce`\n" +"is called for." +msgstr "" +"Το \"FnMut\" είναι ένας υποτύπος του \"FnOnce\". Το \"Fn\" είναι ένας " +"υποτύπος των \"FnMut\" και \"FnOnce\". Δηλ. μπορείτε να χρησιμοποιήσετε ένα\n" +"«FnMut» όπου ζητείται ένα «FnOnce» και μπορείτε να χρησιμοποιήσετε ένα «Fn» " +"όπου ένα «FnMut» ή «FnOnce»\n" +"καλείται." + +#: src/generics/closures.md:36 +#, fuzzy +msgid "`move` closures only implement `FnOnce`." +msgstr "Τα κλεισίματα «μετακίνησης» εφαρμόζουν μόνο το «FnOnce»." + +#: src/generics/monomorphization.md:1 +#, fuzzy +msgid "# Monomorphization" +msgstr "# Μονομορφοποίηση" + +#: src/generics/monomorphization.md:3 +#, fuzzy +msgid "Generic code is turned into non-generic code based on the call sites:" +msgstr "" +"Ο γενικός κώδικας μετατρέπεται σε μη γενικό κώδικα βάσει των τοποθεσιών " +"κλήσεων:" + +#: src/generics/monomorphization.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let integer = Some(5);\n" +" let float = Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:12 +#, fuzzy +msgid "behaves as if you wrote" +msgstr "συμπεριφέρεται σαν να έγραψες" + +#: src/generics/monomorphization.md:14 +msgid "" +"```rust,editable\n" +"enum Option_i32 {\n" +" Some(i32),\n" +" None,\n" +"}\n" +"\n" +"enum Option_f64 {\n" +" Some(f64),\n" +" None,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Option_i32::Some(5);\n" +" let float = Option_f64::Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:31 +#, fuzzy +msgid "" +"This is a zero-cost abstraction: you get exactly the same result as if you " +"had\n" +"hand-coded the data structures without the abstraction." +msgstr "" +"Αυτή είναι μια αφαίρεση μηδενικού κόστους: παίρνετε ακριβώς το ίδιο " +"αποτέλεσμα όπως αν είχατε\n" +"κωδικοποίησαν τις δομές δεδομένων χωρίς την αφαίρεση." + +#: src/generics/trait-objects.md:1 +#, fuzzy +msgid "# Trait Objects" +msgstr "# Αντικείμενα χαρακτηριστικών" + +#: src/generics/trait-objects.md:3 +#, fuzzy +msgid "We've seen how a function can take arguments which implement a trait:" +msgstr "" +"Είδαμε πώς μια συνάρτηση μπορεί να λάβει ορίσματα που υλοποιούν ένα " +"χαρακτηριστικό:" + +#: src/generics/trait-objects.md:5 +msgid "" +"```rust,editable\n" +"use std::fmt::Display;\n" +"\n" +"fn print(x: T) {\n" +" println!(\"Your value: {x}\");\n" +"}\n" +"\n" +"fn main() {\n" +" print(123);\n" +" print(\"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-objects.md:18 +#, fuzzy +msgid "" +"However, how can we store a collection of mixed types which implement " +"`Display`?" +msgstr "" +"Ωστόσο, πώς μπορούμε να αποθηκεύσουμε μια συλλογή μικτών τύπων που υλοποιούν " +"το \"Display\";" + +#: src/generics/trait-objects.md:20 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let displayables = vec![123, \"Hello\"];\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-objects.md:26 +#, fuzzy +msgid "For this, we need _trait objects_:" +msgstr "Για αυτό, χρειαζόμαστε _trait αντικείμενα_:" + +#: src/generics/trait-objects.md:28 +msgid "" +"```rust,editable\n" +"use std::fmt::Display;\n" +"\n" +"fn main() {\n" +" let displayables: Vec> = vec![Box::new(123), Box::" +"new(\"Hello\")];\n" +" for x in displayables {\n" +" println!(\"x: {x}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-objects.md:39 +#, fuzzy +msgid "Memory layout after allocating `displayables`:" +msgstr "Διάταξη μνήμης μετά την εκχώρηση «xs»:" + +#: src/generics/trait-objects.md:41 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - " +"- - -.\n" +": : : :\n" +": " +"displayables : : :\n" +": +-----------+-------+ : : +-----+-----" +"+ :\n" +": | ptr | o---+---+-----+-->| o o | o o " +"| :\n" +": | len | 2 | : : +-|-|-+-|-|-" +"+ :\n" +": | capacity | 2 | : : | | | | +----+----+----+----+----" +"+ :\n" +": +-----------+-------+ : : | | | '-->| H | e | l | l | o " +"| :\n" +": : : | | | +----+----+----+----+----" +"+ :\n" +"`- - - - - - - - - - - - - -' : | | " +"| :\n" +" : | | | " +"+-------------------------+ :\n" +" : | | '---->| \"::" +"fmt\" | :\n" +" : | | " +"+-------------------------+ :\n" +" : | " +"| :\n" +" : | | +----+----+----+----" +"+ :\n" +" : | '-->| 7b | 00 | 00 | 00 " +"| :\n" +" : | +----+----+----+----" +"+ :\n" +" : " +"| :\n" +" : | +-------------------------" +"+ :\n" +" : '---->| \"::fmt\" " +"| :\n" +" : +-------------------------" +"+ :\n" +" : :\n" +" : :\n" +" '- - - - - - - - - - - - - - - - - - - - - " +"- - -'\n" +"```" +msgstr "" + +#: src/generics/trait-objects.md:69 +#, fuzzy +msgid "" +"Similarly, you need a trait object if you want to return different types\n" +"implementing a trait:" +msgstr "" +"Ομοίως, χρειάζεστε ένα αντικείμενο χαρακτηριστικών εάν θέλετε να επιστρέψετε " +"διαφορετικές τιμές\n" +"υλοποίηση ενός χαρακτηριστικού:" + +#: src/generics/trait-objects.md:72 +msgid "" +"```rust,editable\n" +"fn numbers(n: i32) -> Box> {\n" +" if n > 0 {\n" +" Box::new(0..n)\n" +" } else {\n" +" Box::new((n..0).rev())\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"{:?}\", numbers(-5).collect::>());\n" +" println!(\"{:?}\", numbers(5).collect::>());\n" +"}\n" +"\n" +"```" +msgstr "" + +#: src/generics/trait-objects.md:90 +#, fuzzy +msgid "" +"* Types that implement a given trait may be of different sizes. This makes " +"it impossible to have things like `Vec` in the example above.\n" +"* `dyn Display` is a way to tell the compiler about a dynamically sized type " +"that implements `Display`.\n" +"* In the example, `displayables` holds *fat pointers* to objects that " +"implement `Display`. The fat pointer consists of two components, a pointer " +"to the actual object and a pointer to the virtual method table for the " +"`Display` implementation of that particular object.\n" +"* Compare these outputs in the above example:\n" +" ```rust,ignore\n" +"\t\t use std::fmt::Display;\n" +" println!(\"{}\", std::mem::size_of::());\n" +" println!(\"{}\", std::mem::size_of::<&u32>());\n" +" println!(\"{}\", std::mem::size_of::<&dyn Display>());\n" +" println!(\"{}\", std::mem::size_of::>());\n" +" ```" +msgstr "" +"* Τα χαρακτηριστικά μπορεί να προσδιορίζουν προ-εφαρμοσμένες " +"(προεπιλεγμένες) μεθόδους και μεθόδους που απαιτείται από τους χρήστες να " +"εφαρμόσουν οι ίδιοι. Οι μέθοδοι με προεπιλεγμένες υλοποιήσεις μπορούν να " +"βασίζονται στις απαιτούμενες μεθόδους.\n" +"* Οι τύποι που εφαρμόζουν ένα δεδομένο χαρακτηριστικό μπορεί να είναι " +"διαφορετικών μεγεθών. Αυτό καθιστά αδύνατο να υπάρχουν πράγματα όπως το " +"\"Vec\" στο παραπάνω παράδειγμα.\n" +"* Το \"dyn Greet\" είναι ένας τρόπος να πείτε στον μεταγλωττιστή έναν τύπο " +"δυναμικού μεγέθους που υλοποιεί το \"Greet\".\n" +"* Στο παράδειγμα, τα «κατοικίδια» κρατούν δείκτες λίπους σε αντικείμενα που " +"υλοποιούν το «Χαιρετισμός». Ο δείκτης λίπους αποτελείται από δύο στοιχεία, " +"έναν δείκτη προς το πραγματικό αντικείμενο και έναν δείκτη στον πίνακα " +"εικονικής μεθόδου για την υλοποίηση «Greet» του συγκεκριμένου αντικειμένου." + +#: src/exercises/day-3/morning.md:1 +#, fuzzy +msgid "# Day 3: Morning Exercises" +msgstr "# Ημέρα 3: Πρωινές ασκήσεις" + +#: src/exercises/day-3/morning.md:3 +#, fuzzy +msgid "We will design a classical GUI library traits and trait objects." +msgstr "" +"Θα σχεδιάσουμε μια κλασική βιβλιοθήκη GUI χαρακτηριστικά και αντικείμενα " +"χαρακτηριστικών." + +#: src/exercises/day-3/simple-gui.md:1 +#, fuzzy +msgid "# A Simple GUI Library" +msgstr "# Μια απλή βιβλιοθήκη GUI" + +#: src/exercises/day-3/simple-gui.md:3 +#, fuzzy +msgid "" +"Let us design a classical GUI library using our new knowledge of traits and\n" +"trait objects." +msgstr "" +"Ας σχεδιάσουμε μια κλασική βιβλιοθήκη GUI χρησιμοποιώντας τις νέες μας " +"γνώσεις για τα χαρακτηριστικά και\n" +"γνωρίσματα αντικειμένων." + +#: src/exercises/day-3/simple-gui.md:6 +#, fuzzy +msgid "We will have a number of widgets in our library:" +msgstr "Θα έχουμε έναν αριθμό γραφικών στοιχείων στη βιβλιοθήκη μας:" + +#: src/exercises/day-3/simple-gui.md:8 +#, fuzzy +msgid "" +"* `Window`: has a `title` and contains other widgets.\n" +"* `Button`: has a `label` and a callback function which is invoked when the\n" +" button is pressed.\n" +"* `Label`: has a `label`." +msgstr "" +"* «Παράθυρο»: έχει «τίτλο» και περιέχει άλλα γραφικά στοιχεία.\n" +"* «Κουμπί»: έχει μια «ετικέτα» και μια λειτουργία επανάκλησης που καλείται " +"όταν το\n" +" πατιέται το κουμπί.\n" +"* \"Ετικέτα\": έχει \"ετικέτα\"." + +#: src/exercises/day-3/simple-gui.md:13 +#, fuzzy +msgid "The widgets will implement a `Widget` trait, see below." +msgstr "" +"Τα γραφικά στοιχεία θα εφαρμόσουν ένα χαρακτηριστικό «Γραφικό στοιχείο», " +"δείτε παρακάτω." + +#: src/exercises/day-3/simple-gui.md:15 +#, fuzzy +msgid "" +"Copy the code below to , fill in the missing\n" +"`draw_into` methods so that you implement the `Widget` trait:" +msgstr "" +"Αντιγράψτε τον παρακάτω κώδικα στο , " +"συμπληρώστε τον κωδικό που λείπει\n" +"Μέθοδοι \"draw_into\", ώστε να εφαρμόσετε το χαρακτηριστικό \"Widget\":" + +#: src/exercises/day-3/simple-gui.md:18 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"}\n" +"\n" +"\n" +"impl Widget for Label {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Widget for Button {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo." +"\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:123 +#, fuzzy +msgid "The output of the above program can be something simple like this:" +msgstr "" +"Η έξοδος του παραπάνω προγράμματος μπορεί να είναι κάτι απλό όπως αυτό:" + +#: src/exercises/day-3/simple-gui.md:125 +msgid "" +"```text\n" +"========\n" +"Rust GUI Demo 1.23\n" +"========\n" +"\n" +"This is a small text GUI demo.\n" +"\n" +"| Click me! |\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:135 +#, fuzzy +msgid "" +"If you want to draw aligned text, you can use the\n" +"[fill/alignment](https://doc.rust-lang.org/std/fmt/index." +"html#fillalignment)\n" +"formatting operators. In particular, notice how you can pad with different\n" +"characters (here a `'/'`) and how you can control alignment:" +msgstr "" +"Εάν θέλετε να σχεδιάσετε στοιχισμένο κείμενο, μπορείτε να χρησιμοποιήσετε " +"το\n" +"[fill/alignment](https://doc.rust-lang.org/std/fmt/index." +"html#fillalignment)\n" +"τελεστές μορφοποίησης. Ειδικότερα, παρατηρήστε πώς μπορείτε να γεμίσετε " +"διαφορετικά\n" +"χαρακτήρες (εδώ ένα `'/'`) και πώς μπορείτε να ελέγξετε τη στοίχιση:" + +#: src/exercises/day-3/simple-gui.md:140 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let width = 10;\n" +" println!(\"left aligned: |{:/width$}|\", \"foo\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:149 +#, fuzzy +msgid "" +"Using such alignment tricks, you can for example produce output like this:" +msgstr "" +"Χρησιμοποιώντας τέτοια κόλπα ευθυγράμμισης, μπορείτε για παράδειγμα να " +"παράγετε έξοδο όπως αυτό:" + +#: src/exercises/day-3/simple-gui.md:151 +msgid "" +"```text\n" +"+--------------------------------+\n" +"| Rust GUI Demo 1.23 |\n" +"+================================+\n" +"| This is a small text GUI demo. |\n" +"| +-----------+ |\n" +"| | Click me! | |\n" +"| +-----------+ |\n" +"+--------------------------------+\n" +"```" +msgstr "" + +#: src/error-handling.md:1 +#, fuzzy +msgid "# Error Handling" +msgstr "# Χειρισμός σφαλμάτων" + +#: src/error-handling.md:3 +#, fuzzy +msgid "Error handling in Rust is done using explicit control flow:" +msgstr "" +"Ο χειρισμός σφαλμάτων στο Rust γίνεται χρησιμοποιώντας ρητή ροή ελέγχου:" + +#: src/error-handling.md:5 +#, fuzzy +msgid "" +"* Functions that can have errors list this in their return type,\n" +"* There are no exceptions." +msgstr "" +"* Οι συναρτήσεις που μπορεί να έχουν σφάλματα το αναφέρουν στον τύπο " +"επιστροφής τους,\n" +"* Δεν υπάρχουν εξαιρέσεις." + +#: src/error-handling/panics.md:1 +#, fuzzy +msgid "# Panics" +msgstr "# Πανικός" + +#: src/error-handling/panics.md:3 +#, fuzzy +msgid "Rust will trigger a panic if a fatal error happens at runtime:" +msgstr "" +"Το Rust θα προκαλέσει πανικό εάν συμβεί ένα μοιραίο σφάλμα κατά τη διάρκεια " +"της εκτέλεσης:" + +#: src/error-handling/panics.md:5 +msgid "" +"```rust,editable,should_panic\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" println!(\"v[100]: {}\", v[100]);\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/panics.md:12 +#, fuzzy +msgid "" +"* Panics are for unrecoverable and unexpected errors.\n" +" * Panics are symptoms of bugs in the program.\n" +"* Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." +msgstr "" +"* Οι πανικοί αφορούν μη αναστρέψιμα και απροσδόκητα σφάλματα.\n" +" * Οι πανικοί είναι συμπτώματα σφαλμάτων στο πρόγραμμα.\n" +"* Χρησιμοποιήστε API που δεν προκαλούν πανικό (όπως \"Vec::get\") εάν το " +"σφάλμα δεν είναι αποδεκτό." + +#: src/error-handling/panic-unwind.md:1 +#, fuzzy +msgid "# Catching the Stack Unwinding" +msgstr "# Αλίευση της στοίβας Ξετύλιγμα" + +#: src/error-handling/panic-unwind.md:3 +#, fuzzy +msgid "" +"By default, a panic will cause the stack to unwind. The unwinding can be " +"caught:" +msgstr "" +"Από προεπιλογή, ένας πανικός θα προκαλέσει το ξετύλιγμα της στοίβας. Το " +"ξετύλιγμα μπορεί να πιαστεί:" + +#: src/error-handling/panic-unwind.md:5 +msgid "" +"```rust\n" +"use std::panic;\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" println!(\"hello!\");\n" +"});\n" +"assert!(result.is_ok());\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" panic!(\"oh no!\");\n" +"});\n" +"assert!(result.is_err());\n" +"```" +msgstr "" + +#: src/error-handling/panic-unwind.md:19 +#, fuzzy +msgid "" +"* This can be useful in servers which should keep running even if a single\n" +" request crashes.\n" +"* This does not work if `panic = 'abort'` is set in your `Cargo.toml`." +msgstr "" +"* Αυτό μπορεί να είναι χρήσιμο σε διακομιστές που θα πρέπει να συνεχίσουν να " +"εκτελούνται ακόμα και αν είναι μόνοι\n" +" κολλάει το αίτημα.\n" +"* Αυτό δεν λειτουργεί εάν το \"panic = \"abort\" έχει οριστεί στο \"Cargo." +"toml\"." + +#: src/error-handling/result.md:1 +#, fuzzy +msgid "# Structured Error Handling with `Result`" +msgstr "# Χειρισμός δομημένου σφάλματος με «Αποτέλεσμα»." + +#: src/error-handling/result.md:3 +#, fuzzy +msgid "" +"We have already seen the `Result` enum. This is used pervasively when errors " +"are\n" +"expected as part of normal operation:" +msgstr "" +"Έχουμε ήδη δει τον αριθμό «Αποτέλεσμα». Αυτό χρησιμοποιείται ευρέως όταν " +"υπάρχουν σφάλματα\n" +"αναμένεται ως μέρος της κανονικής λειτουργίας:" + +#: src/error-handling/result.md:6 +msgid "" +"```rust\n" +"use std::fs::File;\n" +"use std::io::Read;\n" +"\n" +"fn main() {\n" +" let file = File::open(\"diary.txt\");\n" +" match file {\n" +" Ok(mut file) => {\n" +" let mut contents = String::new();\n" +" file.read_to_string(&mut contents);\n" +" println!(\"Dear diary: {contents}\");\n" +" },\n" +" Err(err) => {\n" +" println!(\"The diary could not be opened: {err}\");\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/result.md:27 +#, fuzzy +msgid "" +" * As with `Option`, the successful value sits inside of `Result`, forcing " +"the developer to\n" +" explicitly extract it. This encourages error checking. In the case where " +"an error should never happen,\n" +" `unwrap()` or `expect()` can be called, and this is a signal of the " +"developer intent too. \n" +" * `Result` documentation is a recommended read. Not during the course, but " +"it is worth mentioning. \n" +" It contains a lot of convenience methods and functions that help " +"functional-style programming. \n" +" " +msgstr "" +" * Όπως και με την \"Επιλογή\", η επιτυχημένη τιμή βρίσκεται μέσα στο " +"\"Αποτέλεσμα\", αναγκάζοντας τον προγραμματιστή να το κάνει\n" +" το εξάγετε ρητά. Αυτό ενθαρρύνει τον έλεγχο σφαλμάτων. Στην περίπτωση " +"που δεν πρέπει να συμβεί ποτέ λάθος,\n" +" Το \"unwrap()\" ή το \"expect()\" μπορεί να κληθεί, και αυτό είναι " +"επίσης ένα σήμα της πρόθεσης του προγραμματιστή.\n" +" * Η τεκμηρίωση «Αποτελέσματος» συνιστάται για ανάγνωση. Όχι κατά τη " +"διάρκεια του μαθήματος, αλλά αξίζει να αναφερθεί.\n" +" Περιέχει πολλές πρακτικές μεθόδους και λειτουργίες που βοηθούν τον " +"προγραμματισμό λειτουργικού στυλ.\n" +" \n" +"" + +#: src/error-handling/try-operator.md:1 +#, fuzzy +msgid "# Propagating Errors with `?`" +msgstr "# Σφάλματα διάδοσης με το \"?\"." + +#: src/error-handling/try-operator.md:3 +#, fuzzy +msgid "" +"The try-operator `?` is used to return errors to the caller. It lets you " +"turn\n" +"the common" +msgstr "" +"Ο τελεστής δοκιμής `?` χρησιμοποιείται για την επιστροφή σφαλμάτων στον " +"καλούντα. Σας αφήνει να στρίψετε\n" +"το κοινό" + +#: src/error-handling/try-operator.md:6 +msgid "" +"```rust,ignore\n" +"match some_expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(err),\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:13 +#, fuzzy +msgid "into the much simpler" +msgstr "στο πολύ πιο απλό" + +#: src/error-handling/try-operator.md:15 +msgid "" +"```rust,ignore\n" +"some_expression?\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:19 +#, fuzzy +msgid "We can use this to simplify our error handing code:" +msgstr "" +"Μπορούμε να το χρησιμοποιήσουμε για να απλοποιήσουμε τον κωδικό παράδοσης " +"σφαλμάτων:" + +#: src/error-handling/try-operator.md:21 +msgid "" +"```rust,editable\n" +"use std::fs;\n" +"use std::io::{self, Read};\n" +"\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" +" };\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" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"alice\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:52 +#: src/error-handling/converting-error-types-example.md:52 +#, fuzzy +msgid "" +"* The `username` variable can be either `Ok(string)` or `Err(error)`.\n" +"* Use the `fs::write` call to test out the different scenarios: no file, " +"empty file, file with username." +msgstr "" +"* Η μεταβλητή \"username\" μπορεί να είναι είτε \"Ok(string)\" είτε " +"\"Err(error)\".\n" +"* Χρησιμοποιήστε την κλήση `fs::write` για να δοκιμάσετε τα διαφορετικά " +"σενάρια: κανένα αρχείο, κενό αρχείο, αρχείο με όνομα χρήστη." + +#: src/error-handling/converting-error-types.md:1 +#: src/error-handling/converting-error-types-example.md:1 +#, fuzzy +msgid "# Converting Error Types" +msgstr "# Μετατροπή τύπων σφαλμάτων" + +#: src/error-handling/converting-error-types.md:3 +#, fuzzy +msgid "" +"The effective expansion of `?` is a little more complicated than previously " +"indicated:" +msgstr "" +"Η αποτελεσματική επέκταση του «?» είναι λίγο πιο περίπλοκη από ό,τι " +"αναφέρθηκε προηγουμένως:" + +#: src/error-handling/converting-error-types.md:5 +msgid "" +"```rust,ignore\n" +"expression?\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types.md:9 +#, fuzzy +msgid "works the same as" +msgstr "λειτουργεί το ίδιο με" + +#: src/error-handling/converting-error-types.md:11 +msgid "" +"```rust,ignore\n" +"match expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(From::from(err)),\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types.md:18 +#, fuzzy +msgid "" +"The `From::from` call here means we attempt to convert the error type to " +"the\n" +"type returned by the function:" +msgstr "" +"Η κλήση \"From::from\" εδώ σημαίνει ότι προσπαθούμε να μετατρέψουμε τον τύπο " +"σφάλματος στο\n" +"τύπος που επιστρέφεται από τη συνάρτηση:" + +#: src/error-handling/converting-error-types-example.md:3 +msgid "" +"```rust,editable\n" +"use std::error::Error;\n" +"use std::fmt::{self, Display, Formatter};\n" +"use std::fs::{self, File};\n" +"use std::io::{self, Read};\n" +"\n" +"#[derive(Debug)]\n" +"enum ReadUsernameError {\n" +" IoError(io::Error),\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"impl Error for ReadUsernameError {}\n" +"\n" +"impl Display for ReadUsernameError {\n" +" fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" +" match self {\n" +" Self::IoError(e) => write!(f, \"IO error: {}\", e),\n" +" Self::EmptyUsername(filename) => write!(f, \"Found no username " +"in {}\", filename),\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl From for ReadUsernameError {\n" +" fn from(err: io::Error) -> ReadUsernameError {\n" +" ReadUsernameError::IoError(err)\n" +" }\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:55 +#, fuzzy +msgid "" +"It is good practice for all error types to implement `std::error::Error`, " +"which requires `Debug` and\n" +"`Display`. It's generally helpful for them to implement `Clone` and `Eq` too " +"where possible, to make\n" +"life easier for tests and consumers of your library. In this case we can't " +"easily do so, because\n" +"`io::Error` doesn't implement them." +msgstr "" +"Είναι καλή πρακτική για όλους τους τύπους σφαλμάτων να εφαρμόζουν το \"std::" +"error::Error\", το οποίο απαιτεί \"Debug\" και\n" +"'Εμφάνιση'. Είναι γενικά χρήσιμο γι 'αυτούς να εφαρμόσουν το \"Clone\" και " +"το \"Eq\" όπου είναι δυνατόν\n" +"ευκολότερη ζωή για τα τεστ και τους καταναλωτές της βιβλιοθήκης σας. Σε αυτή " +"την περίπτωση δεν μπορούμε εύκολα να το κάνουμε, γιατί\n" +"Το `io::Error` δεν τα υλοποιεί." + +#: src/error-handling/deriving-error-enums.md:1 +#, fuzzy +msgid "# Deriving Error Enums" +msgstr "# Παραγωγή Αριθμών σφαλμάτων" + +#: src/error-handling/deriving-error-enums.md:3 +#, fuzzy +msgid "" +"The [thiserror](https://docs.rs/thiserror/) crate is a popular way to create " +"an\n" +"error enum like we did on the previous page:" +msgstr "" +"Το κιβώτιο [thiserror](https://docs.rs/thiserror/) είναι ένας δημοφιλής " +"τρόπος δημιουργίας\n" +"enum σφαλμάτων όπως κάναμε στην προηγούμενη σελίδα:" + +#: src/error-handling/deriving-error-enums.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"\n" +"#[derive(Debug, Error)]\n" +"enum ReadUsernameError {\n" +" #[error(\"Could not read: {0}\")]\n" +" IoError(#[from] io::Error),\n" +" #[error(\"Found no username in {0}\")]\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:39 +#, fuzzy +msgid "" +"`thiserror`'s derive macro automatically implements `std::error::Error`, and " +"optionally `Display`\n" +"(if the `#[error(...)]` attributes are provided) and `From` (if the " +"`#[from]` attribute is added).\n" +"It also works for structs." +msgstr "" +"Η μακροεντολή εξαγωγής \"thiserror\" εφαρμόζει αυτόματα το \"std::error::" +"Error\" και προαιρετικά το \"Display\"\n" +"(εάν παρέχονται τα χαρακτηριστικά \"#[σφάλμα(...)]\") και \"Από\" (αν " +"προστεθεί το χαρακτηριστικό \"#[από]\".\n" +"Λειτουργεί επίσης για δομές." + +#: src/error-handling/deriving-error-enums.md:43 +#, fuzzy +msgid "It doesn't affect your public API, which makes it good for libraries." +msgstr "" +"Δεν επηρεάζει το δημόσιο API σας, κάτι που το κάνει καλό για βιβλιοθήκες." + +#: src/error-handling/dynamic-errors.md:1 +#, fuzzy +msgid "# Dynamic Error Types" +msgstr "# Δυναμικοί τύποι σφαλμάτων" + +#: src/error-handling/dynamic-errors.md:3 +#, fuzzy +msgid "" +"Sometimes we want to allow any type of error to be returned without writing " +"our own enum covering\n" +"all the different possibilities. `std::error::Error` makes this easy." +msgstr "" +"Μερικές φορές θέλουμε να επιτρέψουμε την επιστροφή οποιουδήποτε τύπου " +"σφάλματος χωρίς να γράψουμε το δικό μας κάλυμμα enum\n" +"όλες τις διαφορετικές δυνατότητες. Το `std::error::Error` το καθιστά εύκολο." + +#: src/error-handling/dynamic-errors.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use std::fs::{self, File};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"use std::error::Error;\n" +"\n" +"#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" +"#[error(\"Found no username in {0}\")]\n" +"struct EmptyUsernameError(String);\n" +"\n" +"fn read_username(path: &str) -> Result> {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(EmptyUsernameError(String::from(path)).into());\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/dynamic-errors.md:36 +#, fuzzy +msgid "" +"This saves on code, but gives up the ability to cleanly handle different " +"error cases differently in\n" +"the program. As such it's generally not a good idea to use `Box` " +"in the public API of a\n" +"library, but it can be a good option in a program where you just want to " +"display the error message\n" +"somewhere." +msgstr "" +"Αυτό εξοικονομεί κώδικα, αλλά παραιτείται από τη δυνατότητα καθαρής " +"διαχείρισης διαφορετικών περιπτώσεων σφαλμάτων με διαφορετικό τρόπο\n" +"το πρόγραμμα. Ως εκ τούτου, γενικά δεν είναι καλή ιδέα να χρησιμοποιήσετε το " +"\"Box\" στο δημόσιο API ενός\n" +"βιβλιοθήκη, αλλά μπορεί να είναι μια καλή επιλογή σε ένα πρόγραμμα όπου " +"θέλετε απλώς να εμφανίσετε το μήνυμα σφάλματος\n" +"κάπου." + +#: src/error-handling/error-contexts.md:1 +#, fuzzy +msgid "# Adding Context to Errors" +msgstr "# Προσθήκη περιβάλλοντος στα σφάλματα" + +#: src/error-handling/error-contexts.md:3 +#, fuzzy +msgid "" +"The widely used [anyhow](https://docs.rs/anyhow/) crate can help you add\n" +"contextual information to your errors and allows you to have fewer\n" +"custom error types:" +msgstr "" +"Το ευρέως χρησιμοποιούμενο κιβώτιο [anyhow](https://docs.rs/anyhow/) μπορεί " +"να σας βοηθήσει να προσθέσετε\n" +"πληροφορίες για τα λάθη σας και σας επιτρέπει να έχετε λιγότερα\n" +"προσαρμοσμένοι τύποι σφαλμάτων:" + +#: src/error-handling/error-contexts.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use anyhow::{Context, Result, bail};\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)\n" +" .with_context(|| format!(\"Failed to open {path}\"))?\n" +" .read_to_string(&mut username)\n" +" .context(\"Failed to read\")?;\n" +" if username.is_empty() {\n" +" bail!(\"Found no username in {path}\");\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err:?}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/error-contexts.md:35 +#, fuzzy +msgid "" +"* `anyhow::Result` is a type alias for `Result`.\n" +"* `anyhow::Error` is essentially a wrapper around `Box`. As such " +"it's again generally not\n" +" a good choice for the public API of a library, but is widely used in " +"applications.\n" +"* Actual error type inside of it can be extracted for examination if " +"necessary.\n" +"* Functionality provided by `anyhow::Result` may be familiar to Go " +"developers, as it provides\n" +" similar usage patterns and ergonomics to `(T, error)` from Go." +msgstr "" +"* Το `ούτως ή άλλως::Αποτέλεσμα` είναι ένα ψευδώνυμο τύπου για το " +"\"Αποτέλεσμα\".\n" +"* Το \"anyhow::Error\" είναι ουσιαστικά ένα περιτύλιγμα γύρω από το " +"\"Box\". Ως τέτοιο και πάλι γενικά δεν είναι\n" +" μια καλή επιλογή για το δημόσιο API μιας βιβλιοθήκης, αλλά χρησιμοποιείται " +"ευρέως σε εφαρμογές.\n" +"* Ο πραγματικός τύπος σφάλματος στο εσωτερικό του μπορεί να εξαχθεί για " +"εξέταση εάν είναι απαραίτητο.\n" +"* Η λειτουργικότητα που παρέχεται από το \"anyhow::Result\" μπορεί να " +"είναι οικεία στους προγραμματιστές της Go, καθώς παρέχει\n" +" παρόμοια μοτίβα χρήσης και εργονομία με το «(T, error)» από το Go." + +#: src/testing.md:1 +#, fuzzy +msgid "# Testing" +msgstr "# Δοκιμές" + +#: src/testing.md:3 +#, fuzzy +msgid "Rust and Cargo come with a simple unit test framework:" +msgstr "Το Rust and Cargo συνοδεύεται από ένα απλό πλαίσιο δοκιμής μονάδας:" + +#: src/testing.md:5 +#, fuzzy +msgid "" +"* Unit tests are supported throughout your code.\n" +"\n" +"* Integration tests are supported via the `tests/` directory." +msgstr "* Οι δοκιμές ενσωμάτωσης υποστηρίζονται μέσω του καταλόγου «tests/»." + +#: src/testing/unit-tests.md:1 +#, fuzzy +msgid "# Unit Tests" +msgstr "# Δοκιμές μονάδων" + +#: src/testing/unit-tests.md:3 +#, fuzzy +msgid "Mark unit tests with `#[test]`:" +msgstr "Επισημάνετε τις δοκιμές μονάδας με «#[test]»:" + +#: src/testing/unit-tests.md:5 +msgid "" +"```rust,ignore\n" +"fn first_word(text: &str) -> &str {\n" +" match text.find(' ') {\n" +" Some(idx) => &text[..idx],\n" +" None => &text,\n" +" }\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty() {\n" +" assert_eq!(first_word(\"\"), \"\");\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_word() {\n" +" assert_eq!(first_word(\"Hello\"), \"Hello\");\n" +"}\n" +"\n" +"#[test]\n" +"fn test_multiple_words() {\n" +" assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/testing/unit-tests.md:29 +#, fuzzy +msgid "Use `cargo test` to find and run the unit tests." +msgstr "" +"Χρησιμοποιήστε τη «δοκιμή φορτίου» για να βρείτε και να εκτελέσετε τις " +"δοκιμές μονάδας." + +#: src/testing/test-modules.md:1 +#, fuzzy +msgid "# Test Modules" +msgstr "# Δοκιμαστικές Ενότητες" + +#: src/testing/test-modules.md:3 +#, fuzzy +msgid "" +"Unit tests are often put in a nested module (run tests on the\n" +"[Playground](https://play.rust-lang.org/)):" +msgstr "" +"Οι δοκιμές μονάδας τοποθετούνται συχνά σε μια ένθετη ενότητα (εκτελέστε " +"δοκιμές στο\n" +"[Παιδική χαρά](https://play.rust-lang.org/)):" + +#: src/testing/test-modules.md:6 +msgid "" +"```rust,editable\n" +"fn helper(a: &str, b: &str) -> String {\n" +" format!(\"{a} {b}\")\n" +"}\n" +"\n" +"pub fn main() {\n" +" println!(\"{}\", helper(\"Hello\", \"World\"));\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" #[test]\n" +" fn test_helper() {\n" +" assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/testing/test-modules.md:26 +#, fuzzy +msgid "" +"* This lets you unit test private helpers.\n" +"* The `#[cfg(test)]` attribute is only active when you run `cargo test`." +msgstr "" +"* Αυτό σας επιτρέπει να δοκιμάσετε ιδιωτικούς βοηθούς μονάδας.\n" +"* Το χαρακτηριστικό «#[cfg(test)]» είναι ενεργό μόνο όταν εκτελείτε «δοκιμή " +"φορτίου»." + +#: src/testing/doc-tests.md:1 +#, fuzzy +msgid "# Documentation Tests" +msgstr "# Δοκιμές τεκμηρίωσης" + +#: src/testing/doc-tests.md:3 +#, fuzzy +msgid "Rust has built-in support for documentation tests:" +msgstr "Το Rust έχει ενσωματωμένη υποστήριξη για δοκιμές τεκμηρίωσης:" + +#: src/testing/doc-tests.md:5 +msgid "" +"```rust\n" +"/// Shortens a string to the given length.\n" +"///\n" +"/// ```\n" +"/// use playground::shorten_string;\n" +"/// assert_eq!(shorten_string(\"Hello World\", 5), \"Hello\");\n" +"/// assert_eq!(shorten_string(\"Hello World\", 20), \"Hello World\");\n" +"/// ```\n" +"pub fn shorten_string(s: &str, length: usize) -> &str {\n" +" &s[..std::cmp::min(length, s.len())]\n" +"}\n" +"```" +msgstr "" + +#: src/testing/doc-tests.md:18 +#, fuzzy +msgid "" +"* Code blocks in `///` comments are automatically seen as Rust code.\n" +"* The code will be compiled and executed as part of `cargo test`.\n" +"* Test the above code on the [Rust Playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." +msgstr "" +"* Τα μπλοκ κώδικα στα σχόλια `///` εμφανίζονται αυτόματα ως κώδικας Rust.\n" +"* Ο κώδικας θα μεταγλωττιστεί και θα εκτελεστεί ως μέρος της «δοκιμής " +"φορτίου».\n" +"* Δοκιμάστε τον παραπάνω κώδικα στο [Rust Playground](https://play.rust-lang." +"org/?" +"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." + +#: src/testing/integration-tests.md:1 +#, fuzzy +msgid "# Integration Tests" +msgstr "# Δοκιμές ολοκλήρωσης" + +#: src/testing/integration-tests.md:3 +#, fuzzy +msgid "If you want to test your library as a client, use an integration test." +msgstr "" +"Εάν θέλετε να δοκιμάσετε τη βιβλιοθήκη σας ως πελάτη, χρησιμοποιήστε μια " +"δοκιμή ενοποίησης." + +#: src/testing/integration-tests.md:5 +#, fuzzy +msgid "Create a `.rs` file under `tests/`:" +msgstr "Δημιουργήστε ένα αρχείο «.rs» κάτω από το «tests/»:" + +#: src/testing/integration-tests.md:7 +msgid "" +"```rust,ignore\n" +"use my_library::init;\n" +"\n" +"#[test]\n" +"fn test_init() {\n" +" assert!(init().is_ok());\n" +"}\n" +"```" +msgstr "" + +#: src/testing/integration-tests.md:16 +#, fuzzy +msgid "These tests only have access to the public API of your crate." +msgstr "Αυτές οι δοκιμές έχουν πρόσβαση μόνο στο δημόσιο API του κλουβιού σας." + +#: src/unsafe.md:1 +#, fuzzy +msgid "# Unsafe Rust" +msgstr "# Μη ασφαλής Σκουριά" + +#: src/unsafe.md:3 +#, fuzzy +msgid "The Rust language has two parts:" +msgstr "Η γλώσσα Rust έχει δύο μέρη:" + +#: src/unsafe.md:5 +#, fuzzy +msgid "" +"* **Safe Rust:** memory safe, no undefined behavior possible.\n" +"* **Unsafe Rust:** can trigger undefined behavior if preconditions are " +"violated." +msgstr "" +"* **Safe Rust:** ασφαλής μνήμη, δεν είναι δυνατή η απροσδιόριστη " +"συμπεριφορά.\n" +"* **Μη ασφαλής σκουριά:** μπορεί να προκαλέσει απροσδιόριστη συμπεριφορά εάν " +"παραβιάζονται προϋποθέσεις." + +#: src/unsafe.md:8 +#, fuzzy +msgid "" +"We will be seeing mostly safe Rust in this course, but it's important to " +"know\n" +"what Unsafe Rust is." +msgstr "" +"Θα δούμε κυρίως ασφαλή Rust σε αυτό το μάθημα, αλλά είναι σημαντικό να το " +"γνωρίζουμε\n" +"τι είναι το Unsafe Rust." + +#: src/unsafe.md:11 +#, fuzzy +msgid "" +"Unsafe code is usually small and isolated, and its correctness should be " +"carefully\n" +"documented. It is usually wrapped in a safe abstraction layer." +msgstr "" +"Ο μη ασφαλής κώδικας είναι συνήθως μικρός και απομονωμένος και η ορθότητά " +"του θα πρέπει να γίνεται προσεκτικά\n" +"τεκμηριωμένη. Συνήθως είναι τυλιγμένο σε ένα ασφαλές στρώμα αφαίρεσης." + +#: src/unsafe.md:14 +#, fuzzy +msgid "Unsafe Rust gives you access to five new capabilities:" +msgstr "Το Unsafe Rust σάς δίνει πρόσβαση σε πέντε νέες δυνατότητες:" + +#: src/unsafe.md:16 +#, fuzzy +msgid "" +"* Dereference raw pointers.\n" +"* Access or modify mutable static variables.\n" +"* Access `union` fields.\n" +"* Call `unsafe` functions, including `extern` functions.\n" +"* Implement `unsafe` traits." +msgstr "" +"* Αναφορά ακατέργαστων δεικτών.\n" +"* Πρόσβαση ή τροποποίηση μεταβλητών στατικών μεταβλητών.\n" +"* Πρόσβαση στα πεδία «ένωση».\n" +"* Καλέστε «μη ασφαλείς» συναρτήσεις, συμπεριλαμβανομένων των «εξωτερικών» " +"συναρτήσεων.\n" +"* Εφαρμόστε «μη ασφαλή» χαρακτηριστικά." + +#: src/unsafe.md:22 +#, fuzzy +msgid "" +"We will briefly cover unsafe capabilities next. For full details, please " +"see\n" +"[Chapter 19.1 in the Rust Book](https://doc.rust-lang.org/book/ch19-01-" +"unsafe-rust.html)\n" +"and the [Rustonomicon](https://doc.rust-lang.org/nomicon/)." +msgstr "" +"Θα καλύψουμε εν συντομία τις μη ασφαλείς δυνατότητες στη συνέχεια. Για " +"πλήρεις λεπτομέρειες, δείτε\n" +"[Κεφάλαιο 19.1 στο βιβλίο της σκουριάς](https://doc.rust-lang.org/book/" +"ch19-01-unsafe-rust.html)\n" +"και το [Rustonomicon](https://doc.rust-lang.org/nomicon/)." + +#: src/unsafe.md:28 +#, fuzzy +msgid "" +"Unsafe Rust does not mean the code is incorrect. It means that developers " +"have\n" +"turned off the compiler safety features and have to write correct code by\n" +"themselves. It means the compiler no longer enforces Rust's memory-safety " +"rules." +msgstr "" +"Το Unsafe Rust δεν σημαίνει ότι ο κωδικός είναι εσφαλμένος. Σημαίνει ότι οι " +"προγραμματιστές έχουν\n" +"απενεργοποίησε τις δυνατότητες ασφαλείας του μεταγλωττιστή και πρέπει να " +"γράψει τον σωστό κώδικα από\n" +"τους εαυτούς τους. Σημαίνει ότι ο μεταγλωττιστής δεν επιβάλλει πλέον τους " +"κανόνες ασφαλείας της μνήμης του Rust." + +#: src/unsafe/raw-pointers.md:1 +#, fuzzy +msgid "# Dereferencing Raw Pointers" +msgstr "# Αποαναφορά ακατέργαστων δεικτών" + +#: src/unsafe/raw-pointers.md:3 +#, fuzzy +msgid "Creating pointers is safe, but dereferencing them requires `unsafe`:" +msgstr "" +"Η δημιουργία δεικτών είναι ασφαλής, αλλά η αποσύνδεσή τους απαιτεί \"μη " +"ασφαλή\":" + +#: src/unsafe/raw-pointers.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut num = 5;\n" +"\n" +" 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" +" // references or concurrently through any other pointers.\n" +" unsafe {\n" +" println!(\"r1 is: {}\", *r1);\n" +" *r1 = 10;\n" +" println!(\"r2 is: {}\", *r2);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/raw-pointers.md:26 +#, fuzzy +msgid "" +"It is good practice (and required by the Android Rust style guide) to write " +"a comment for each\n" +"`unsafe` block explaining how the code inside it satisfies the safety " +"requirements of the unsafe\n" +"operations it is doing." +msgstr "" +"Είναι καλή πρακτική (και απαιτείται από τον οδηγό στυλ Android Rust) να " +"γράψετε ένα σχόλιο για το καθένα\n" +"Μπλοκ \"μη ασφαλής\" που εξηγεί πώς ο κωδικός μέσα σε αυτό ικανοποιεί τις " +"απαιτήσεις ασφαλείας του μη ασφαλούς\n" +"λειτουργίες που κάνει." + +#: src/unsafe/raw-pointers.md:30 +#, fuzzy +msgid "" +"In the case of pointer dereferences, this means that the pointers must be\n" +"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), i.e.:" +msgstr "" +"Στην περίπτωση των αποαναφορών δείκτη, αυτό σημαίνει ότι οι δείκτες πρέπει " +"να είναι\n" +"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), π.χ.:" + +#: src/unsafe/raw-pointers.md:33 +#, fuzzy +msgid "" +" * The pointer must be non-null.\n" +" * The pointer must be _dereferenceable_ (within the bounds of a single " +"allocated object).\n" +" * The object must not have been deallocated.\n" +" * There must not be concurrent accesses to the same location.\n" +" * If the pointer was obtained by casting a reference, the underlying object " +"must be live and no\n" +" reference may be used to access the memory." +msgstr "" +" * Ο δείκτης δεν πρέπει να είναι μηδενικός.\n" +" * Ο δείκτης πρέπει να είναι _dereferenceable_ (εντός των ορίων ενός " +"μεμονωμένου αντικειμένου).\n" +" * Το αντικείμενο δεν πρέπει να έχει εκχωρηθεί.\n" +" * Δεν πρέπει να υπάρχουν ταυτόχρονες προσβάσεις στην ίδια τοποθεσία.\n" +" * Εάν ο δείκτης λήφθηκε με τη μετάδοση μιας αναφοράς, το υποκείμενο " +"αντικείμενο πρέπει να είναι ζωντανό και όχι\n" +" μπορεί να χρησιμοποιηθεί αναφορά για πρόσβαση στη μνήμη." + +#: src/unsafe/raw-pointers.md:40 +#, fuzzy +msgid "In most cases the pointer must also be properly aligned." +msgstr "" +"Στις περισσότερες περιπτώσεις ο δείκτης πρέπει επίσης να είναι σωστά " +"ευθυγραμμισμένος." + +#: src/unsafe/mutable-static-variables.md:1 +#, fuzzy +msgid "# Mutable Static Variables" +msgstr "# Μεταβλητές στατικές μεταβλητές" + +#: src/unsafe/mutable-static-variables.md:3 +#, fuzzy +msgid "It is safe to read an immutable static variable:" +msgstr "Είναι ασφαλές να διαβάσετε μια αμετάβλητη στατική μεταβλητή:" + +#: src/unsafe/mutable-static-variables.md:5 +msgid "" +"```rust,editable\n" +"static HELLO_WORLD: &str = \"Hello, world!\";\n" +"\n" +"fn main() {\n" +" println!(\"HELLO_WORLD: {HELLO_WORLD}\");\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:13 +#, fuzzy +msgid "" +"However, since data races can occur, it is unsafe to read and write mutable\n" +"static variables:" +msgstr "" +"Ωστόσο, δεδομένου ότι μπορεί να προκύψουν αγώνες δεδομένων, δεν είναι " +"ασφαλές να διαβάζετε και να γράφετε μεταβλητά\n" +"στατικές μεταβλητές:" + +#: src/unsafe/mutable-static-variables.md:16 +msgid "" +"```rust,editable\n" +"static mut COUNTER: u32 = 0;\n" +"\n" +"fn add_to_counter(inc: u32) {\n" +" unsafe { COUNTER += inc; } // Potential data race!\n" +"}\n" +"\n" +"fn main() {\n" +" add_to_counter(42);\n" +"\n" +" unsafe { println!(\"COUNTER: {COUNTER}\"); } // Potential data race!\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:32 +#, fuzzy +msgid "" +"Using a mutable static is generally a bad idea, but there are some cases " +"where it might make sense\n" +"in low-level `no_std` code, such as implementing a heap allocator or working " +"with some C APIs." +msgstr "" +"Η χρήση ενός μεταβλητού στατικού είναι γενικά κακή ιδέα, αλλά υπάρχουν " +"ορισμένες περιπτώσεις όπου μπορεί να έχει νόημα\n" +"σε κώδικα «no_std» χαμηλού επιπέδου, όπως η εφαρμογή ενός κατανεμητή σωρού ή " +"η εργασία με ορισμένα C API." + +#: src/unsafe/unions.md:1 +#, fuzzy +msgid "# Unions" +msgstr "# Σωματεία" + +#: src/unsafe/unions.md:3 +#, fuzzy +msgid "Unions are like enums, but you need to track the active field yourself:" +msgstr "" +"Τα συνδικάτα είναι σαν τα enums, αλλά πρέπει να παρακολουθείτε μόνοι σας το " +"ενεργό πεδίο:" + +#: src/unsafe/unions.md:5 +msgid "" +"```rust,editable\n" +"#[repr(C)]\n" +"union MyUnion {\n" +" i: u8,\n" +" b: bool,\n" +"}\n" +"\n" +"fn main() {\n" +" let u = MyUnion { i: 42 };\n" +" println!(\"int: {}\", unsafe { u.i });\n" +" println!(\"bool: {}\", unsafe { u.b }); // Undefined behavior!\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/unions.md:21 +#, fuzzy +msgid "" +"Unions are very rarely needed in Rust as you can usually use an enum. They " +"are occasionally needed\n" +"for interacting with C library APIs." +msgstr "" +"Οι ενώσεις χρειάζονται πολύ σπάνια στο Rust καθώς συνήθως μπορείτε να " +"χρησιμοποιήσετε ένα enum. Περιστασιακά χρειάζονται\n" +"για αλληλεπίδραση με API βιβλιοθήκης C." + +#: src/unsafe/unions.md:24 +#, fuzzy +msgid "" +"If you just want to reinterpret bytes as a different type, you probably " +"want\n" +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn." +"transmute.html) or a safe\n" +"wrapper such as the [`zerocopy`](https://crates.io/crates/zerocopy) crate." +msgstr "" +"Εάν θέλετε απλώς να ερμηνεύσετε ξανά τα byte ως διαφορετικού τύπου, μάλλον " +"θέλετε\n" +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn." +"transmute.html) ή χρηματοκιβώτιο\n" +"περιτύλιγμα όπως το κιβώτιο [`zerocopy`](https://crates.io/crates/zerocopy)." + +#: src/unsafe/calling-unsafe-functions.md:1 +#, fuzzy +msgid "# Calling Unsafe Functions" +msgstr "# Κλήση μη ασφαλών λειτουργιών" + +#: src/unsafe/calling-unsafe-functions.md:3 +#, fuzzy +msgid "" +"A function or method can be marked `unsafe` if it has extra preconditions " +"you\n" +"must uphold to avoid undefined behaviour:" +msgstr "" +"Μια συνάρτηση ή μια μέθοδος μπορεί να επισημανθεί ως «μη ασφαλής» εάν έχει " +"επιπλέον προϋποθέσεις\n" +"πρέπει να τηρεί για την αποφυγή απροσδιόριστης συμπεριφοράς:" + +#: src/unsafe/calling-unsafe-functions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let emojis = \"🗻∈🌏\";\n" +"\n" +" // Safe because the indices are in the correct order, within the bounds " +"of\n" +" // the string slice, and lie on UTF-8 sequence boundaries.\n" +" unsafe {\n" +" println!(\"emoji: {}\", emojis.get_unchecked(0..4));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(4..7));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(7..11));\n" +" }\n" +"\n" +" println!(\"char count: {}\", count_chars(unsafe { emojis." +"get_unchecked(0..7) }));\n" +"\n" +" // Not upholding the UTF-8 encoding requirement breaks memory safety!\n" +" // println!(\"emoji: {}\", unsafe { emojis.get_unchecked(0..3) });\n" +" // println!(\"char count: {}\", count_chars(unsafe { emojis." +"get_unchecked(0..3) }));\n" +"}\n" +"\n" +"fn count_chars(s: &str) -> usize {\n" +" s.chars().map(|_| 1).sum()\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:1 +#, fuzzy +msgid "# Writing Unsafe Functions" +msgstr "# Γράψιμο μη ασφαλών λειτουργιών" + +#: src/unsafe/writing-unsafe-functions.md:3 +#, fuzzy +msgid "" +"You can mark your own functions as `unsafe` if they require particular " +"conditions to avoid undefined\n" +"behaviour." +msgstr "" +"Μπορείτε να επισημάνετε τις δικές σας λειτουργίες ως \"μη ασφαλείς\" εάν " +"απαιτούν συγκεκριμένες συνθήκες για να αποφευχθούν απροσδιόριστες\n" +"η ΣΥΜΠΕΡΙΦΟΡΑ." + +#: src/unsafe/writing-unsafe-functions.md:6 +msgid "" +"```rust,editable\n" +"/// Swaps the values pointed to by the given pointers.\n" +"///\n" +"/// # Safety\n" +"///\n" +"/// The pointers must be valid and properly aligned.\n" +"unsafe fn swap(a: *mut u8, b: *mut u8) {\n" +" let temp = *a;\n" +" *a = *b;\n" +" *b = temp;\n" +"}\n" +"\n" +"fn main() {\n" +" let mut a = 42;\n" +" let mut b = 66;\n" +"\n" +" // Safe because ...\n" +" unsafe {\n" +" swap(&mut a, &mut b);\n" +" }\n" +"\n" +" println!(\"a = {}, b = {}\", a, b);\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:33 +#, fuzzy +msgid "" +"We wouldn't actually use pointers for this because it can be done safely " +"with references." +msgstr "" +"Στην πραγματικότητα δεν θα χρησιμοποιούσαμε δείκτες για αυτό, επειδή μπορεί " +"να γίνει με ασφάλεια με αναφορές." + +#: src/unsafe/writing-unsafe-functions.md:35 +#, fuzzy +msgid "" +"Note that unsafe code is allowed within an unsafe function without an " +"`unsafe` block. We can\n" +"prohibit this with `#[deny(unsafe_op_in_unsafe_fn)]`. Try adding it and see " +"what happens." +msgstr "" +"Σημειώστε ότι ο μη ασφαλής κωδικός επιτρέπεται σε μια μη ασφαλή συνάρτηση " +"χωρίς μπλοκ \"μη ασφαλής\". Μπορούμε\n" +"απαγορεύστε αυτό με \"#[deny(unsafe_op_in_unsafe_fn)]\". Δοκιμάστε να το " +"προσθέσετε και δείτε τι θα συμβεί." + +#: src/unsafe/extern-functions.md:1 +#, fuzzy +msgid "# Calling External Code" +msgstr "# Κλήση εξωτερικού κωδικού" + +#: src/unsafe/extern-functions.md:3 +#, fuzzy +msgid "" +"Functions from other languages might violate the guarantees of Rust. " +"Calling\n" +"them is thus unsafe:" +msgstr "" +"Λειτουργίες από άλλες γλώσσες ενδέχεται να παραβιάζουν τις εγγυήσεις του " +"Rust. Κλήση\n" +"είναι επομένως ανασφαλείς:" + +#: src/unsafe/extern-functions.md:6 +msgid "" +"```rust,editable\n" +"extern \"C\" {\n" +" fn abs(input: i32) -> i32;\n" +"}\n" +"\n" +"fn main() {\n" +" unsafe {\n" +" // Undefined behavior if abs misbehaves.\n" +" println!(\"Absolute value of -3 according to C: {}\", abs(-3));\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/extern-functions.md:21 +#, fuzzy +msgid "" +"This is usually only a problem for extern functions which do things with " +"pointers which might\n" +"violate Rust's memory model, but in general any C function might have " +"undefined behaviour under any\n" +"arbitrary circumstances." +msgstr "" +"Αυτό είναι συνήθως ένα πρόβλημα μόνο για εξωτερικές συναρτήσεις που κάνουν " +"πράγματα με δείκτες που μπορεί\n" +"παραβιάζουν το μοντέλο μνήμης του Rust, αλλά γενικά οποιαδήποτε συνάρτηση C " +"μπορεί να έχει απροσδιόριστη συμπεριφορά κάτω από οποιαδήποτε\n" +"αυθαίρετες περιστάσεις." + +#: src/unsafe/extern-functions.md:25 +msgid "" +"The `\"C\"` in this example is the ABI;\n" +"[other ABIs are available too](https://doc.rust-lang.org/reference/items/" +"external-blocks.html)." +msgstr "" + +#: src/unsafe/unsafe-traits.md:1 +#, fuzzy +msgid "# Implementing Unsafe Traits" +msgstr "# Εφαρμογή μη ασφαλών χαρακτηριστικών" + +#: src/unsafe/unsafe-traits.md:3 +#, fuzzy +msgid "" +"Like with functions, you can mark a trait as `unsafe` if the implementation " +"must guarantee\n" +"particular conditions to avoid undefined behaviour." +msgstr "" +"Όπως και με τις συναρτήσεις, μπορείτε να επισημάνετε ένα χαρακτηριστικό ως " +"\"μη ασφαλές\", εάν η υλοποίηση πρέπει να είναι εγγυημένη\n" +"συγκεκριμένες συνθήκες για την αποφυγή απροσδιόριστης συμπεριφοράς." + +#: src/unsafe/unsafe-traits.md:6 +#, fuzzy +msgid "" +"For example, the `zerocopy` crate has an unsafe trait that looks\n" +"[something like this](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes." +"html):" +msgstr "" +"Για παράδειγμα, το κιβώτιο «zerocopy» έχει ένα μη ασφαλές χαρακτηριστικό που " +"φαίνεται\n" +"[κάτι σαν αυτό](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" + +#: src/unsafe/unsafe-traits.md:9 +#, fuzzy +msgid "" +"```rust,editable\n" +"use std::mem::size_of_val;\n" +"use std::slice;\n" +"\n" +"/// ...\n" +"/// # Safety\n" +"/// The type must have a defined representation and no padding.\n" +"pub unsafe trait AsBytes {\n" +" fn as_bytes(&self) -> &[u8] {\n" +" unsafe {\n" +" slice::from_raw_parts(self as *const Self as *const u8, " +"size_of_val(self))\n" +" }\n" +" }\n" +"}\n" +"\n" +"// Safe because u32 has a defined representation and no padding.\n" +"unsafe impl AsBytes for u32 {}\n" +"```" +msgstr "" +"///...\n" +"/// # Ασφάλεια\n" +"/// Ο τύπος πρέπει να έχει καθορισμένη αναπαράσταση και χωρίς γέμιση.\n" +"μη ασφαλές χαρακτηριστικό παμπ AsBytes {\n" +" fn as_bytes(&self) -> &[u8] {\n" +" μη ασφαλές {\n" +" slice::from_raw_parts(self as *const Self as *const u8, " +"size_of_val(self))\n" +" }\n" +" }\n" +"}" + +#: src/unsafe/unsafe-traits.md:30 +#, fuzzy +msgid "" +"There should be a `# Safety` section on the Rustdoc for the trait explaining " +"the requirements for\n" +"the trait to be safely implemented." +msgstr "" +"Θα πρέπει να υπάρχει μια ενότητα «# Ασφάλεια» στο Rustdoc για το " +"χαρακτηριστικό που εξηγεί τις απαιτήσεις για\n" +"το χαρακτηριστικό που πρέπει να εφαρμοστεί με ασφάλεια." + +#: src/unsafe/unsafe-traits.md:33 +#, fuzzy +msgid "" +"The actual safety section for `AsBytes` is rather longer and more " +"complicated." +msgstr "" +"Η πραγματική ενότητα ασφάλειας για τα \"AsBytes\" είναι μάλλον μεγαλύτερη " +"και πιο περίπλοκη." + +#: src/unsafe/unsafe-traits.md:35 +#, fuzzy +msgid "The built-in `Send` and `Sync` traits are unsafe." +msgstr "" +"Τα ενσωματωμένα χαρακτηριστικά «Αποστολή» και «Συγχρονισμός» δεν είναι " +"ασφαλή." + +#: src/exercises/day-3/afternoon.md:1 +#, fuzzy +msgid "# Day 3: Afternoon Exercises" +msgstr "# Ημέρα 3: Απογευματινές Ασκήσεις" + +#: src/exercises/day-3/afternoon.md:3 +#, fuzzy +msgid "Let us build a safe wrapper for reading directory content!" +msgstr "" +"Ας δημιουργήσουμε ένα ασφαλές περιτύλιγμα για την ανάγνωση περιεχομένου " +"καταλόγου!" + +#: src/exercises/day-3/afternoon.md:7 +#, fuzzy +msgid "After looking at the exercise, you can look at the [solution] provided." +msgstr "Αφού δείτε την άσκηση, μπορείτε να δείτε τη [λύση] που παρέχεται." + +#: src/exercises/day-3/safe-ffi-wrapper.md:1 +#, fuzzy +msgid "# Safe FFI Wrapper" +msgstr "# Ασφαλές περιτύλιγμα FFI" + +#: src/exercises/day-3/safe-ffi-wrapper.md:3 +#, fuzzy +msgid "" +"Rust has great support for calling functions through a _foreign function\n" +"interface_ (FFI). We will use this to build a safe wrapper for the `libc`\n" +"functions you would use from C to read the filenames of a directory." +msgstr "" +"Το Rust έχει μεγάλη υποστήριξη για την κλήση συναρτήσεων μέσω μιας " +"συνάρτησης _foreign\n" +"διεπαφή_ (FFI). Θα το χρησιμοποιήσουμε για να δημιουργήσουμε ένα ασφαλές " +"περιτύλιγμα για το `libc`\n" +"συναρτήσεις που θα χρησιμοποιούσατε από το C για να διαβάσετε τα ονόματα " +"αρχείων ενός καταλόγου." + +#: src/exercises/day-3/safe-ffi-wrapper.md:7 +#, fuzzy +msgid "You will want to consult the manual pages:" +msgstr "Θα θελήσετε να συμβουλευτείτε τις σελίδες του εγχειριδίου:" + +#: src/exercises/day-3/safe-ffi-wrapper.md:9 +#, fuzzy +msgid "" +"* [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)\n" +"* [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)\n" +"* [`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)" +msgstr "" +"* [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)\n" +"* [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)\n" +"* [`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." +msgstr "" +"Θα θέλετε επίσης να περιηγηθείτε στη λειτουργική μονάδα [`std::ffi`], ειδικά " +"για το [`CStr`]\n" +"και τύπους [`CString`] που χρησιμοποιούνται για τη διατήρηση συμβολοσειρών " +"με τερματισμό NUL που προέρχονται από\n" +"Γ. Το [Nomicon] έχει επίσης ένα πολύ χρήσιμο κεφάλαιο για το FFI." + +#: src/exercises/day-3/safe-ffi-wrapper.md:22 +#, fuzzy +msgid "" +"Copy the code below to and fill in the " +"missing\n" +"functions and methods:" +msgstr "" +"Αντιγράψτε τον παρακάτω κώδικα στο και " +"συμπληρώστε τον κωδικό που λείπει\n" +"λειτουργίες και μέθοδοι:" + +#: src/exercises/day-3/safe-ffi-wrapper.md:25 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::" +"PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-" +"gnu.\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}\n" +"\n" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/welcome-day-4.md:1 +#, fuzzy +msgid "# Welcome to Day 4" +msgstr "# Καλώς ήρθατε στην Ημέρα 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 "# Ατρόμητος Συγχρονισμός" + +#: src/concurrency.md:3 +#, fuzzy +msgid "" +"Rust has full support for concurrency using OS threads with mutexes and\n" +"channels." +msgstr "" +"Το Rust έχει πλήρη υποστήριξη για ταυτόχρονη χρήση νημάτων λειτουργικού " +"συστήματος με mutexes και\n" +"καναλιών." + +#: 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 "" +"Το σύστημα τύπου Rust παίζει σημαντικό ρόλο στη δημιουργία πολλών σφαλμάτων " +"συγχρονισμού\n" +"μεταγλώττιση χρονικών σφαλμάτων. Αυτό αναφέρεται συχνά ως _ατρόμητος " +"συγχρονισμός_ αφού εσείς\n" +"μπορεί να βασιστεί στον μεταγλωττιστή για να διασφαλίσει την ορθότητα κατά " +"το χρόνο εκτέλεσης." + +#: src/concurrency/threads.md:1 +#, fuzzy +msgid "# Threads" +msgstr "# Νήματα" + +#: src/concurrency/threads.md:3 +#, fuzzy +msgid "Rust threads work similarly to threads in other languages:" +msgstr "Τα νήματα σκουριάς λειτουργούν παρόμοια με τα νήματα σε άλλες γλώσσες:" + +#: 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 "" +"* Τα νήματα είναι όλα νήματα δαίμονα, το κύριο νήμα δεν τα περιμένει.\n" +"* Οι πανικοί των νημάτων είναι ανεξάρτητοι ο ένας από τον άλλο.\n" +" * Οι πανικοί μπορούν να μεταφέρουν ένα ωφέλιμο φορτίο, το οποίο μπορεί να " +"αποσυμπιεστεί με το «downcast_ref»." + +#: 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 "# Νήματα με εμβέλεια" + +#: src/concurrency/scoped-threads.md:3 +#, fuzzy +msgid "Normal threads cannot borrow from their environment:" +msgstr "Τα κανονικά νήματα δεν μπορούν να δανειστούν από το περιβάλλον τους:" + +#: 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 "Ωστόσο, μπορείτε να χρησιμοποιήσετε ένα [νήμα εμβέλειας][1] για αυτό:" + +#: 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 "" +"<λεπτομέρειες>\n" +" \n" +"* Ο λόγος για αυτό είναι ότι όταν ολοκληρωθεί η συνάρτηση `thread::scope`, " +"όλα τα νήματα είναι εγγυημένα ότι θα ενωθούν, ώστε να μπορούν να επιστρέψουν " +"τα δεδομένα που έχουν δανειστεί.\n" +"* Ισχύουν οι κανονικοί κανόνες δανεισμού Rust: μπορείτε είτε να δανειστείτε " +"μεταλλάξιμα με ένα νήμα ή αμετάβλητα με οποιονδήποτε αριθμό νημάτων.\n" +" \n" +"" + +#: src/concurrency/channels.md:1 +#, fuzzy +msgid "# Channels" +msgstr "# Κανάλια" + +#: 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 έχουν δύο μέρη: ένα \"Αποστολέας\" και ένα \"Δέκτης\". " +"Τα δύο μέρη\n" +"συνδέονται μέσω του καναλιού, αλλά βλέπετε μόνο τα τελικά σημεία." + +#: 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» σημαίνει Multi-Producer, Single-Consumer. Το \"Sender\" και το " +"\"SyncSender\" υλοποιούν το \"Clone\" (έτσι\n" +" μπορείτε να δημιουργήσετε πολλούς παραγωγούς) αλλά ο «Δέκτης» όχι.\n" +"* Το \"send()\" και το \"recv()\" επιστρέφουν \"Αποτέλεσμα\". Εάν " +"επιστρέψουν \"Err\", σημαίνει το αντίστοιχο \"Αποστολέας\" ή\n" +" Ο \"δέκτης\" πέφτει και το κανάλι είναι κλειστό." + +#: src/concurrency/channels/unbounded.md:1 +#, fuzzy +msgid "# Unbounded Channels" +msgstr "# Κανάλια χωρίς περιορισμούς" + +#: src/concurrency/channels/unbounded.md:3 +#, fuzzy +msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" +msgstr "Λαμβάνετε ένα απεριόριστο και ασύγχρονο κανάλι με `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 "# Οριοθετημένα κανάλια" + +#: src/concurrency/channels/bounded.md:3 +#, fuzzy +msgid "Bounded and synchronous channels make `send` block the current thread:" +msgstr "" +"Τα περιορισμένα και τα σύγχρονα κανάλια κάνουν το \"send\" να μπλοκάρει το " +"τρέχον νήμα:" + +#: 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 "# Κοινό κράτος" + +#: 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 χρησιμοποιεί το σύστημα τύπων για να επιβάλει το συγχρονισμό των " +"κοινόχρηστων δεδομένων. Αυτό είναι\n" +"γίνεται κυρίως μέσω δύο τύπων:" + +#: 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], η ατομική αναφορά μετράται ως \"T\": χειρίζεται την κοινή " +"χρήση μεταξύ νημάτων και\n" +" φροντίζει να κατανείμει το \"T\" όταν απορριφθεί η τελευταία αναφορά,\n" +"* [`Mutex`][2]: εξασφαλίζει αμοιβαία αποκλειστική πρόσβαση στην τιμή " +"\"T\"." + +#: src/concurrency/shared_state/arc.md:1 +#, fuzzy +msgid "# `Arc`" +msgstr "# «Τόξο»." + +#: src/concurrency/shared_state/arc.md:3 +#, fuzzy +msgid "[`Arc`][1] allows shared read-only access via its `clone` method:" +msgstr "" +"Το [`Arc`][1] επιτρέπει την κοινόχρηστη πρόσβαση μόνο για ανάγνωση μέσω " +"της μεθόδου \"clone\" του:" + +#: 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\" σημαίνει \"Atomic Reference Counted\", μια ασφαλής έκδοση " +"νημάτων του \"Rc\" που χρησιμοποιεί ατομική\n" +" επιχειρήσεις.\n" +"* Το \"Arc\" υλοποιεί το \"Clone\" είτε το κάνει το \"T\" είτε όχι. " +"Εφαρμόζει «Αποστολή» και «Συγχρονισμός» αν «T».\n" +" τα εφαρμόζει και τα δύο.\n" +"* Το \"Arc::clone()\" έχει το κόστος των ατομικών λειτουργιών που " +"εκτελούνται, αλλά μετά από αυτό η χρήση του\n" +" Το \"T\" είναι δωρεάν.\n" +"* Προσοχή στους κύκλους αναφοράς, το «Arc» δεν χρησιμοποιεί συλλέκτη " +"σκουπιδιών για να τους εντοπίσει.\n" +" * Το `std::sync::Weak` μπορεί να βοηθήσει." + +#: 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] διασφαλίζει την αμοιβαία εξαίρεση _και_ επιτρέπει τη " +"μεταβλητή πρόσβαση στο \"T\"\n" +"πίσω από μια διεπαφή μόνο για ανάγνωση:" + +#: 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 "" +"Παρατηρήστε πώς έχουμε μια κουβέρτα [`impl Sync for Mutex`][2]\n" +"εκτέλεση." + +#: 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 "" +"<λεπτομέρειες>\n" +" \n" +"* Το \"Mutex\" στο Rust μοιάζει με μια συλλογή με ένα μόνο στοιχείο - τα " +"προστατευμένα δεδομένα.\n" +" * Δεν είναι δυνατό να ξεχάσετε να αποκτήσετε το mutex πριν αποκτήσετε " +"πρόσβαση στα προστατευμένα δεδομένα.\n" +"* Μπορείτε να πάρετε ένα «&mut T» από ένα «&Mutex» παίρνοντας την " +"κλειδαριά. Το «MutexGuard» διασφαλίζει ότι το\n" +" Το \"&mut T\" δεν ξεπερνά την κλειδαριά που κρατιέται.\n" +"* Το \"Mutex\" υλοποιεί και το \"Send\" και το \"Sync\" εάν το \"T\" " +"υλοποιεί το \"Send\".\n" +"* Ένα αντίστοιχο κλείδωμα ανάγνωσης-εγγραφής - «RwLock».\n" +"* Γιατί το «lock()» επιστρέφει ένα «Αποτέλεσμα»;\n" +" * Εάν το νήμα που συγκρατούσε το \"Mutex\" πανικοβλήθηκε, το \"Mutex\" " +"γίνεται \"δηλητηριασμένο\" για να σηματοδοτήσει ότι\n" +" τα δεδομένα που προστατεύει ενδέχεται να είναι σε ασυνεπή κατάσταση. " +"Κλήση «lock()» σε ένα δηλητηριασμένο mutex\n" +" αποτυγχάνει με ένα [`PoisonError`]. Μπορείτε να καλέσετε το " +"«into_inner()» στο σφάλμα για να ανακτήσετε τα δεδομένα\n" +" Ανεξάρτητα." + +#: src/concurrency/shared_state/example.md:3 +#, fuzzy +msgid "Let us see `Arc` and `Mutex` in action:" +msgstr "Ας δούμε τα \"Arc\" και \"Mutex\" σε δράση:" + +#: 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\" είναι τυλιγμένο και σε \"Arc\" και \"Mutex\", επειδή οι ανησυχίες " +"τους είναι ορθογώνιες.\n" +" * Το τύλιγμα ενός \"Mutex\" σε ένα \"Arc\" είναι ένα συνηθισμένο μοτίβο " +"για κοινή χρήση μεταβλητής κατάστασης μεταξύ των νημάτων.\n" +"* Το `v: Το Arc<_>` πρέπει να κλωνοποιηθεί ως `v2` για να μπορέσει να " +"μετακινηθεί σε άλλο νήμα. Η σημείωση \"move\" προστέθηκε στην υπογραφή " +"λάμδα.\n" +"* Τα μπλοκ εισάγονται για να περιορίσουν όσο το δυνατόν περισσότερο το πεδίο " +"εφαρμογής του \"LockGuard\".\n" +"* Πρέπει ακόμα να αποκτήσουμε το «Mutex» για να εκτυπώσουμε το «Vec» μας." + +#: src/concurrency/send-sync.md:1 +#, fuzzy +msgid "# `Send` and `Sync`" +msgstr "# «Αποστολή» και «Συγχρονισμός»." + +#: 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 "" +"Πώς γνωρίζει η Rust ότι απαγορεύει την κοινόχρηστη πρόσβαση σε όλα τα " +"νήματα; Η απάντηση είναι σε δύο χαρακτηριστικά:" + +#: 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 "" +"* [\"Αποστολή\"][1]: ένας τύπος \"T\" είναι \"Αποστολή\" εάν είναι ασφαλές " +"να μετακινήσετε ένα \"T\" σε ένα νήμα\n" +" Όριο.\n" +"* [\"Συγχρονισμός\"][2]: ένας τύπος \"T\" είναι \"Συγχρονισμός\" εάν είναι " +"ασφαλές να μετακινήσετε ένα \"&T\" σε ένα νήμα\n" +" Όριο." + +#: 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 "" +"Η \"Αποστολή\" και η \"Συγχρονισμός\" είναι [μη ασφαλή χαρακτηριστικά][3]. Ο " +"μεταγλωττιστής θα τα παράγει αυτόματα για τους τύπους σας\n" +"εφόσον περιέχουν μόνο τύπους «Αποστολή» και «Συγχρονισμός». Μπορείτε επίσης " +"να τα εφαρμόσετε χειροκίνητα όταν το κάνετε\n" +"να ξέρεις ότι ισχύει." + +#: 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 "" +"* Κάποιος μπορεί να σκεφτεί αυτά τα χαρακτηριστικά ως δείκτες ότι ο τύπος " +"έχει ορισμένες ιδιότητες ασφαλείας νήματος.\n" +"* Μπορούν να χρησιμοποιηθούν στους γενικούς περιορισμούς ως φυσιολογικά " +"χαρακτηριστικά.\n" +" \n" +"" + +#: src/concurrency/send-sync/send.md:1 +#, fuzzy +msgid "# `Send`" +msgstr "# «Αποστολή»." + +#: 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 "" +"> Ένας τύπος `T` είναι [`Αποστολή`][1] εάν είναι ασφαλές να μετακινήσετε μια " +"τιμή `T` σε άλλο νήμα." + +#: 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 "" +"Το αποτέλεσμα της μετακίνησης ιδιοκτησίας σε άλλο νήμα είναι ότι οι " +"_destructors_ θα εκτελεστούν\n" +"σε αυτό το νήμα. Το ερώτημα λοιπόν είναι πότε μπορείτε να εκχωρήσετε μια " +"τιμή σε ένα νήμα\n" +"και να το διαθέσει σε άλλο." + +#: src/concurrency/send-sync/sync.md:1 +#, fuzzy +msgid "# `Sync`" +msgstr "# `Συγχρονισμός`" + +#: 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 "" +"> Ένας τύπος `T` είναι [`Συγχρονισμός`][1] εάν είναι ασφαλής η πρόσβαση σε " +"μια τιμή `T` από πολλαπλές\n" +"> νήματα ταυτόχρονα." + +#: src/concurrency/send-sync/sync.md:6 +#, fuzzy +msgid "More precisely, the definition is:" +msgstr "Πιο συγκεκριμένα, ο ορισμός είναι:" + +#: src/concurrency/send-sync/sync.md:8 +#, fuzzy +msgid "> `T` is `Sync` if and only if `&T` is `Send`" +msgstr "" +"> Το \"T\" είναι \"Συγχρονισμός\" εάν και μόνο εάν το \"&T\" είναι " +"\"Αποστολή\"." + +#: 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 "" +"Αυτή η δήλωση είναι ουσιαστικά ένας συνοπτικός τρόπος για να πούμε ότι εάν " +"ένας τύπος είναι ασφαλής ως προς το νήμα για κοινόχρηστη χρήση, είναι επίσης " +"ασφαλές για το νήμα να μεταβιβάζονται οι αναφορές του στα νήματα." + +#: 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 "" +"Αυτό συμβαίνει επειδή εάν ένας τύπος είναι Sync σημαίνει ότι μπορεί να " +"κοινοποιηθεί σε πολλά νήματα χωρίς τον κίνδυνο φυλών δεδομένων ή άλλων " +"προβλημάτων συγχρονισμού, επομένως είναι ασφαλές να τον μετακινήσετε σε άλλο " +"νήμα. Μια αναφορά στον τύπο είναι επίσης ασφαλής να μετακινηθεί σε άλλο " +"νήμα, επειδή τα δεδομένα που παραπέμπει είναι προσβάσιμα από οποιοδήποτε " +"νήμα με ασφάλεια." + +#: src/concurrency/send-sync/examples.md:1 +#, fuzzy +msgid "# Examples" +msgstr "# Παραδείγματα" + +#: src/concurrency/send-sync/examples.md:3 +#, fuzzy +msgid "## `Send + Sync`" +msgstr "## «Αποστολή + Συγχρονισμός»." + +#: src/concurrency/send-sync/examples.md:5 +#, fuzzy +msgid "Most types you come across are `Send + Sync`:" +msgstr "Οι περισσότεροι τύποι που συναντάτε είναι «Αποστολή + Συγχρονισμός»:" + +#: 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 "" +"Οι γενικοί τύποι είναι συνήθως «Αποστολή + Συγχρονισμός» όταν οι παράμετροι " +"τύπου είναι\n" +"«Αποστολή + Συγχρονισμός»." + +#: src/concurrency/send-sync/examples.md:17 +#, fuzzy +msgid "## `Send + !Sync`" +msgstr "## `Αποστολή + !Συγχρονισμός`" + +#: 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 "" +"Αυτοί οι τύποι μπορούν να μετακινηθούν σε άλλα νήματα, αλλά δεν είναι " +"ασφαλείς για νήματα.\n" +"Τυπικά λόγω της εσωτερικής μεταβλητότητας:" + +#: src/concurrency/send-sync/examples.md:22 +#, fuzzy +msgid "" +"* `mpsc::Sender`\n" +"* `mpsc::Receiver`\n" +"* `Cell`\n" +"* `RefCell`" +msgstr "" +"* `mpsc::Αποστολέας`\n" +"* `mpsc::Δέκτης`\n" +"* `Κελλί`\n" +"* `RefCell`" + +#: src/concurrency/send-sync/examples.md:27 +#, fuzzy +msgid "## `!Send + Sync`" +msgstr "## `!Αποστολή + Συγχρονισμός`" + +#: src/concurrency/send-sync/examples.md:29 +#, fuzzy +msgid "" +"These types are thread-safe, but they cannot be moved to another thread:" +msgstr "" +"Αυτοί οι τύποι είναι ασφαλείς για νήμα, αλλά δεν μπορούν να μετακινηθούν σε " +"άλλο νήμα:" + +#: 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`: Χρησιμοποιεί πρωτόγονα επιπέδου λειτουργικού συστήματος " +"που πρέπει να κατανεμηθούν στο\n" +" νήμα που τα δημιούργησε." + +#: src/concurrency/send-sync/examples.md:34 +#, fuzzy +msgid "## `!Send + !Sync`" +msgstr "## `!Αποστολή + !Συγχρονισμός`" + +#: src/concurrency/send-sync/examples.md:36 +#, fuzzy +msgid "These types are not thread-safe and cannot be moved to other threads:" +msgstr "" +"Αυτοί οι τύποι δεν είναι ασφαλείς για νήμα και δεν μπορούν να μετακινηθούν " +"σε άλλα νήματα:" + +#: 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`: κάθε «Rc» έχει μια αναφορά σε ένα «RcBox», το οποίο " +"περιέχει ένα\n" +" μη ατομική μέτρηση αναφοράς.\n" +"* `*const T`, `*mut T`: Το Rust υποθέτει ότι οι ακατέργαστοι δείκτες μπορεί " +"να έχουν ειδικούς\n" +" ζητήματα ταυτόχρονης ύπαρξης." + +#: 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 "# Ασκήσεις" + +#: src/exercises/day-4/morning.md:3 +#, fuzzy +msgid "Let us practice our new concurrency skills with" +msgstr "Ας εξασκήσουμε τις νέες μας δεξιότητες συγχρονισμού με" + +#: 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 "" +"* Έλεγχος συνδέσμων πολλαπλών νημάτων: ένα μεγαλύτερο έργο στο οποίο θα " +"χρησιμοποιήσετε το Cargo\n" +" κατεβάστε τις εξαρτήσεις και, στη συνέχεια, ελέγξτε τους συνδέσμους " +"παράλληλα." + +#: src/exercises/day-4/dining-philosophers.md:1 +#, fuzzy +msgid "# Dining Philosophers" +msgstr "# Δείπνο Φιλόσοφοι" + +#: src/exercises/day-4/dining-philosophers.md:3 +#, fuzzy +msgid "The dining philosophers problem is a classic problem in concurrency:" +msgstr "" +"Το πρόβλημα των φιλοσόφων τραπεζαρίας είναι ένα κλασικό πρόβλημα ταυτόχρονα:" + +#: 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 "" +"> Πέντε φιλόσοφοι δειπνούν μαζί στο ίδιο τραπέζι. Κάθε φιλόσοφος έχει το " +"δικό του\n" +"> δική σου θέση στο τραπέζι. Ανάμεσα σε κάθε πιάτο υπάρχει ένα πιρούνι. Το " +"πιάτο που σερβίρεται είναι\n" +"> ένα είδος σπαγγέτι που τρώγεται με δύο πιρούνια. Κάθε φιλόσοφος μπορεί\n" +"> μόνο εναλλάξ σκεφτείτε και τρώτε. Επιπλέον, ένας φιλόσοφος μπορεί να φάει " +"μόνο τους\n" +"> μακαρόνια όταν έχουν και αριστερό και δεξί πιρούνι. Έτσι θα μόνο δύο " +"πιρούνια\n" +"> να είναι διαθέσιμοι όταν οι δύο κοντινότεροι γείτονές τους σκέφτονται και " +"δεν τρώνε. Μετά\n" +"> ένας μεμονωμένος φιλόσοφος τελειώνει το φαγητό, θα βάλει κάτω και τα δύο " +"πιρούνια." + +#: 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 `src/main.rs` file, fill out the " +"blanks,\n" +"and test that `cargo run` does not deadlock:" +msgstr "" +"Θα χρειαστείτε μια τοπική [Εγκατάσταση φορτίου](../../cargo/running-locally." +"md) για\n" +"αυτή η άσκηση. Αντιγράψτε τον παρακάτω κώδικα στο αρχείο `src/main.rs, " +"συμπληρώστε τα κενά,\n" +"και ελέγξτε ότι το «cargo run» δεν είναι αδιέξοδο:" + +#: src/exercises/day-4/dining-philosophers.md:17 +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/link-checker.md:1 +#, fuzzy +msgid "# Multi-threaded Link Checker" +msgstr "# Έλεγχος συνδέσμων πολλαπλών νημάτων" + +#: 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 "" +"Ας χρησιμοποιήσουμε τις νέες γνώσεις μας για να δημιουργήσουμε έναν έλεγχο " +"συνδέσμων πολλαπλών νημάτων. Θα έπρεπε\n" +"ξεκινήστε από μια ιστοσελίδα και ελέγξτε ότι οι σύνδεσμοι στη σελίδα είναι " +"έγκυροι. Θα έπρεπε\n" +"ελέγξτε αναδρομικά άλλες σελίδες στον ίδιο τομέα και συνεχίστε να το κάνετε " +"αυτό μέχρι να τελειώσει\n" +"οι σελίδες έχουν επικυρωθεί." + +#: 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 "" +"Για αυτό, θα χρειαστείτε ένα πρόγραμμα-πελάτη HTTP όπως το [`reqwest`][1]. " +"Δημιούργησε ένα νέο\n" +"Έργο φορτίου και το «ζήτησε» ως εξάρτηση με:" + +#: 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 "" +"> Εάν η «προσθήκη φορτίου» αποτύχει με «σφάλμα: δεν υπάρχει τέτοια " +"υποεντολή», τότε επεξεργαστείτε το\n" +"> Αρχείο «Cargo.toml» με το χέρι. Προσθέστε τις εξαρτήσεις που αναφέρονται " +"παρακάτω." + +#: 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 "" +"Θα χρειαστείτε επίσης έναν τρόπο να βρείτε συνδέσμους. Μπορούμε να " +"χρησιμοποιήσουμε το [`scraper`][2] για αυτό:" + +#: 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 "" +"Τέλος, θα χρειαστούμε κάποιο τρόπο χειρισμού των σφαλμάτων. Χρησιμοποιούμε " +"[`αυτό το σφάλμα`][3] για\n" +"ότι:" + +#: 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 "" +"Οι κλήσεις \"cargo add\" θα ενημερώσουν το αρχείο \"Cargo.toml\" ώστε να " +"έχει την εξής μορφή:" + +#: src/exercises/day-4/link-checker.md:35 +msgid "" +"```toml\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:42 +#, fuzzy +msgid "" +"You can now download the start page. Try with a small site such as\n" +"`https://www.google.org/`." +msgstr "" +"Τώρα μπορείτε να κάνετε λήψη της αρχικής σελίδας. Δοκιμάστε με ένα μικρό " +"site όπως π.χ\n" +"`https://www.google.org/`." + +#: src/exercises/day-4/link-checker.md:45 +#, fuzzy +msgid "Your `src/main.rs` file should look something like this:" +msgstr "Το αρχείο `src/main.rs` θα πρέπει να μοιάζει κάπως έτσι:" + +#: src/exercises/day-4/link-checker.md:47 +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:90 +#, fuzzy +msgid "Run the code in `src/main.rs` with" +msgstr "Εκτελέστε τον κώδικα στο `src/main.rs` με" + +#: src/exercises/day-4/link-checker.md:92 +msgid "" +"```shell\n" +"$ cargo run\n" +"```" +msgstr "" + +#: src/exercises/day-4/link-checker.md:96 +#, fuzzy +msgid "## Tasks" +msgstr "## Καθήκοντα" + +#: src/exercises/day-4/link-checker.md:98 +#, 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 "" +"* Χρησιμοποιήστε νήματα για να ελέγξετε τους συνδέσμους παράλληλα: στείλτε " +"τις διευθύνσεις URL που θα ελεγχθούν στο a\n" +" κανάλι και αφήστε μερικά νήματα να ελέγξουν τις διευθύνσεις URL " +"παράλληλα.\n" +"* Επεκτείνετε αυτό για να εξαγάγετε αναδρομικά συνδέσμους από όλες τις " +"σελίδες του\n" +" τομέας `www.google.org`. Βάλτε ένα ανώτατο όριο 100 σελίδων περίπου έτσι " +"ώστε να\n" +" μην καταλήξετε να αποκλειστείτε από τον ιστότοπο." + +#: src/android.md:1 src/bare-metal/android.md:1 +#, fuzzy +msgid "# Android" +msgstr "# Android" + +#: src/android.md:3 +#, fuzzy +msgid "" +"Rust is supported for native platform development on Android. This means " +"that\n" +"you can write new operating system services in Rust, as well as extending\n" +"existing services." +msgstr "" +"Το Rust υποστηρίζεται για ανάπτυξη εγγενούς πλατφόρμας στο Android. Αυτό " +"σημαίνει ότι\n" +"μπορείτε να γράψετε νέες υπηρεσίες λειτουργικού συστήματος στο Rust, καθώς " +"και να επεκτείνετε\n" +"υπάρχουσες υπηρεσίες." + +#: src/android.md:7 +#, fuzzy +msgid "" +"> We will attempt to call Rust from one of your own projects today. So try " +"to\n" +"> find a little corner of your code base where we can move some lines of " +"code to\n" +"> Rust. The fewer dependencies and \"exotic\" types the better. Something " +"that\n" +"> parses some raw bytes would be ideal." +msgstr "" +"> Θα προσπαθήσουμε να καλέσουμε τον Rust από ένα από τα δικά σας έργα " +"σήμερα. Προσπάθησε λοιπόν\n" +"> βρείτε μια μικρή γωνία της βάσης του κώδικα όπου μπορούμε να μετακινήσουμε " +"ορισμένες γραμμές κώδικα\n" +"> Σκουριά. Όσο λιγότερες εξαρτήσεις και «εξωτικοί» τύποι τόσο το καλύτερο. " +"Κάτι που\n" +"> η ανάλυση ορισμένων ακατέργαστων byte θα ήταν ιδανική." + +#: src/android/setup.md:1 +#, fuzzy +msgid "# Setup" +msgstr "# Ρύθμιση" + +#: src/android/setup.md:3 +#, fuzzy +msgid "" +"We will be using an Android Virtual Device to test our code. Make sure you " +"have\n" +"access to one or create a new one with:" +msgstr "" +"Θα χρησιμοποιήσουμε μια εικονική συσκευή Android για να δοκιμάσουμε τον " +"κώδικά μας. Βεβαιωθείτε ότι έχετε\n" +"πρόσβαση σε ένα ή δημιουργήστε ένα νέο με:" + +#: src/android/setup.md:6 +msgid "" +"```shell\n" +"$ source build/envsetup.sh\n" +"$ lunch aosp_cf_x86_64_phone-userdebug\n" +"$ acloud create\n" +"```" +msgstr "" + +#: src/android/setup.md:12 +#, fuzzy +msgid "" +"Please see the [Android Developer\n" +"Codelab](https://source.android.com/docs/setup/start) for details." +msgstr "" +"Ανατρέξτε στο [Android Developer\n" +"Codelab](https://source.android.com/docs/setup/start) για λεπτομέρειες." + +#: src/android/build-rules.md:1 +#, fuzzy +msgid "# Build Rules" +msgstr "# Δημιουργία κανόνων" + +#: src/android/build-rules.md:3 +#, fuzzy +msgid "The Android build system (Soong) supports Rust via a number of modules:" +msgstr "" +"Το σύστημα κατασκευής Android (Soong) υποστηρίζει το Rust μέσω μιας σειράς " +"λειτουργικών μονάδων:" + +#: src/android/build-rules.md:5 +#, fuzzy +msgid "" +"| Module Type | " +"Description " +"|\n" +"|-------------------|----------------------------------------------------------------------------------------------------|\n" +"| `rust_binary` | Produces a Rust " +"binary. " +"|\n" +"| `rust_library` | Produces a Rust library, and provides both `rlib` and " +"`dylib` variants. |\n" +"| `rust_ffi` | Produces a Rust C library usable by `cc` modules, and " +"provides both static and shared variants. |\n" +"| `rust_proc_macro` | Produces a `proc-macro` Rust library. These are " +"analogous to compiler plugins. |\n" +"| `rust_test` | Produces a Rust test binary that uses the standard " +"Rust test harness. |\n" +"| `rust_fuzz` | Produces a Rust fuzz binary leveraging " +"`libfuzzer`. |\n" +"| `rust_protobuf` | Generates source and produces a Rust library that " +"provides an interface for a particular protobuf. |\n" +"| `rust_bindgen` | Generates source and produces a Rust library " +"containing Rust bindings to C libraries. |" +msgstr "" +"| Τύπος ενότητας | Περιγραφή |\n" +"|------------------------------------------------- " +"-------------------------------------------------- ---------------------|\n" +"| `rust_binary` | Παράγει ένα Rust δυαδικό. |\n" +"| `rust_library` | Παράγει μια βιβλιοθήκη Rust και παρέχει παραλλαγές «rlib» " +"και «dylib». |\n" +"| `rust_ffi` | Παράγει μια βιβλιοθήκη Rust C που μπορεί να χρησιμοποιηθεί " +"από μονάδες «cc» και παρέχει τόσο στατικές όσο και κοινόχρηστες παραλλαγές. " +"|\n" +"| `rust_proc_macro` | Παράγει μια «proc-macro» βιβλιοθήκη Rust. Αυτά είναι " +"ανάλογα με τα πρόσθετα μεταγλωττιστή. |\n" +"| «δοκιμή_σκουριάς» | Παράγει ένα δυαδικό σύστημα δοκιμής Rust που " +"χρησιμοποιεί την τυπική ζώνη δοκιμής Rust. |\n" +"| `rust_fuzz` | Παράγει ένα Rust fuzz δυαδικό μόχλευσης «libfuzzer». |\n" +"| `rust_protobuf` | Δημιουργεί πηγή και παράγει μια βιβλιοθήκη Rust που " +"παρέχει μια διεπαφή για ένα συγκεκριμένο protobuf. |\n" +"| `rust_bindgen` | Δημιουργεί πηγή και παράγει μια βιβλιοθήκη Rust που " +"περιέχει δεσμεύσεις Rust σε βιβλιοθήκες C. |" + +#: src/android/build-rules.md:16 +#, fuzzy +msgid "We will look at `rust_binary` and `rust_library` next." +msgstr "Στη συνέχεια θα δούμε τα «rust_binary» και «rust_library»." + +#: src/android/build-rules/binary.md:1 +#, fuzzy +msgid "# Rust Binaries" +msgstr "# Rust Binaries" + +#: src/android/build-rules/binary.md:3 +#, fuzzy +msgid "" +"Let us start with a simple application. At the root of an AOSP checkout, " +"create\n" +"the following files:" +msgstr "" +"Ας ξεκινήσουμε με μια απλή εφαρμογή. Στη ρίζα ενός ταμείου AOSP, " +"δημιουργήστε\n" +"τα ακόλουθα αρχεία:" + +#: src/android/build-rules/binary.md:6 src/android/build-rules/library.md:13 +#, fuzzy +msgid "_hello_rust/Android.bp_:" +msgstr "_hello_rust/Android.bp_:" + +#: src/android/build-rules/binary.md:8 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust\",\n" +" crate_name: \"hello_rust\",\n" +" srcs: [\"src/main.rs\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md:16 src/android/build-rules/library.md:34 +#, fuzzy +msgid "_hello_rust/src/main.rs_:" +msgstr "_hello_rust/src/main.rs_:" + +#: src/android/build-rules/binary.md:18 +msgid "" +"```rust\n" +"//! Rust demo.\n" +"\n" +"/// Prints a greeting to standard output.\n" +"fn main() {\n" +" println!(\"Hello from Rust!\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md:27 +#, fuzzy +msgid "You can now build, push, and run the binary:" +msgstr "" +"Τώρα μπορείτε να δημιουργήσετε, να προωθήσετε και να εκτελέσετε το δυαδικό:" + +#: src/android/build-rules/binary.md:29 +msgid "" +"```shell\n" +"$ m hello_rust\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust\n" +"Hello from Rust!\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:1 +#, fuzzy +msgid "# Rust Libraries" +msgstr "# Βιβλιοθήκες Rust" + +#: src/android/build-rules/library.md:3 +#, fuzzy +msgid "You use `rust_library` to create a new Rust library for Android." +msgstr "" +"Χρησιμοποιείτε το \"rust_library\" για να δημιουργήσετε μια νέα βιβλιοθήκη " +"Rust για Android." + +#: src/android/build-rules/library.md:5 +#, fuzzy +msgid "Here we declare a dependency on two libraries:" +msgstr "Εδώ δηλώνουμε μια εξάρτηση από δύο βιβλιοθήκες:" + +#: src/android/build-rules/library.md:7 +#, fuzzy +msgid "" +"* `libgreeting`, which we define below,\n" +"* `libtextwrap`, which is a crate already vendored in\n" +" [`external/rust/crates/`][crates]." +msgstr "" +"* 'libgreeting', που ορίζουμε παρακάτω,\n" +"* «libtextwrap», το οποίο είναι ένα κιβώτιο που έχει ήδη πωληθεί\n" +" [`εξωτερικά/σκουριά/κιβώτια/`][κιβώτια]." + +#: src/android/build-rules/library.md:15 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_with_dep\",\n" +" crate_name: \"hello_rust_with_dep\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libgreetings\",\n" +" \"libtextwrap\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"\n" +"rust_library {\n" +" name: \"libgreetings\",\n" +" crate_name: \"greetings\",\n" +" srcs: [\"src/lib.rs\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:36 +msgid "" +"```rust,ignore\n" +"//! Rust demo.\n" +"\n" +"use greetings::greeting;\n" +"use textwrap::fill;\n" +"\n" +"/// Prints a greeting to standard output.\n" +"fn main() {\n" +" println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:48 +#, fuzzy +msgid "_hello_rust/src/lib.rs_:" +msgstr "_hello_rust/src/lib.rs_:" + +#: src/android/build-rules/library.md:50 +msgid "" +"```rust,ignore\n" +"//! Greeting library.\n" +"\n" +"/// Greet `name`.\n" +"pub fn greeting(name: &str) -> String {\n" +" format!(\"Hello {name}, it is very nice to meet you!\")\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:59 +#, fuzzy +msgid "You build, push, and run the binary like before:" +msgstr "Δημιουργείτε, πιέζετε και τρέχετε το δυαδικό αρχείο όπως πριν:" + +#: src/android/build-rules/library.md:61 +msgid "" +"```shell\n" +"$ m hello_rust_with_dep\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/" +"tmp\n" +"$ adb shell /data/local/tmp/hello_rust_with_dep\n" +"Hello Bob, it is very\n" +"nice to meet you!\n" +"```" +msgstr "" + +#: src/android/aidl.md:1 +#, fuzzy +msgid "# AIDL" +msgstr "# AIDL" + +#: src/android/aidl.md:3 +#, fuzzy +msgid "" +"The [Android Interface Definition Language\n" +"(AIDL)](https://developer.android.com/guide/components/aidl) is supported in " +"Rust:" +msgstr "" +"Η [Android Interface Definition Language\n" +"(AIDL)](https://developer.android.com/guide/components/aidl) υποστηρίζεται " +"στο Rust:" + +#: src/android/aidl.md:6 +#, fuzzy +msgid "" +"* Rust code can call existing AIDL servers,\n" +"* You can create new AIDL servers in Rust." +msgstr "" +"* Ο κώδικας σκουριάς μπορεί να καλέσει υπάρχοντες διακομιστές AIDL,\n" +"* Μπορείτε να δημιουργήσετε νέους διακομιστές AIDL στο Rust." + +#: src/android/aidl/interface.md:1 +#, fuzzy +msgid "# AIDL Interfaces" +msgstr "# Διεπαφές AIDL" + +#: src/android/aidl/interface.md:3 +#, fuzzy +msgid "You declare the API of your service using an AIDL interface:" +msgstr "Δηλώνετε το API της υπηρεσίας σας χρησιμοποιώντας μια διεπαφή AIDL:" + +#: src/android/aidl/interface.md:5 +#, fuzzy +msgid "" +"*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" +msgstr "" +"*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" + +#: src/android/aidl/interface.md:7 +msgid "" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years);\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/interface.md:17 +#, fuzzy +msgid "*birthday_service/aidl/Android.bp*:" +msgstr "*birthday_service/aidl/Android.bp*:" + +#: src/android/aidl/interface.md:19 +msgid "" +"```javascript\n" +"aidl_interface {\n" +" name: \"com.example.birthdayservice\",\n" +" srcs: [\"com/example/birthdayservice/*.aidl\"],\n" +" unstable: true,\n" +" backend: {\n" +" rust: { // Rust is not enabled by default\n" +" enabled: true,\n" +" },\n" +" },\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/interface.md:32 +#, fuzzy +msgid "" +"Add `vendor_available: true` if your AIDL file is used by a binary in the " +"vendor\n" +"partition." +msgstr "" +"Προσθέστε το \"vendor_available: true\" εάν το αρχείο AIDL σας " +"χρησιμοποιείται από ένα δυαδικό αρχείο στον προμηθευτή\n" +"χώρισμα." + +#: src/android/aidl/implementation.md:1 +#, fuzzy +msgid "# Service Implementation" +msgstr "# Υλοποίηση υπηρεσίας" + +#: src/android/aidl/implementation.md:3 +#, fuzzy +msgid "We can now implement the AIDL service:" +msgstr "Μπορούμε τώρα να εφαρμόσουμε την υπηρεσία AIDL:" + +#: src/android/aidl/implementation.md:5 +#, fuzzy +msgid "*birthday_service/src/lib.rs*:" +msgstr "*birthday_service/src/lib.rs*:" + +#: src/android/aidl/implementation.md:7 +msgid "" +"```rust,ignore\n" +"//! Implementation of the `IBirthdayService` AIDL interface.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::" +"IBirthdayService::IBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"/// The `IBirthdayService` implementation.\n" +"pub struct BirthdayService;\n" +"\n" +"impl binder::Interface for BirthdayService {}\n" +"\n" +"impl IBirthdayService for BirthdayService {\n" +" fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::" +"Result {\n" +" Ok(format!(\n" +" \"Happy Birthday {name}, congratulations with the {years} years!" +"\"\n" +" ))\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/implementation.md:26 src/android/aidl/server.md:28 +#: src/android/aidl/client.md:37 +#, fuzzy +msgid "*birthday_service/Android.bp*:" +msgstr "*birthday_service/Android.bp*:" + +#: src/android/aidl/implementation.md:28 +msgid "" +"```javascript\n" +"rust_library {\n" +" name: \"libbirthdayservice\",\n" +" srcs: [\"src/lib.rs\"],\n" +" crate_name: \"birthdayservice\",\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/server.md:1 +#, fuzzy +msgid "# AIDL Server" +msgstr "# Διακομιστής AIDL" + +#: src/android/aidl/server.md:3 +#, fuzzy +msgid "Finally, we can create a server which exposes the service:" +msgstr "" +"Τέλος, μπορούμε να δημιουργήσουμε έναν διακομιστή που εκθέτει την υπηρεσία:" + +#: src/android/aidl/server.md:5 +#, fuzzy +msgid "*birthday_service/src/server.rs*:" +msgstr "*birthday_service/src/server.rs*:" + +#: src/android/aidl/server.md:7 +msgid "" +"```rust,ignore\n" +"//! Birthday service.\n" +"use birthdayservice::BirthdayService;\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::" +"IBirthdayService::BnBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" +"/// Entry point for birthday service.\n" +"fn main() {\n" +" let birthday_service = BirthdayService;\n" +" let birthday_service_binder = BnBirthdayService::new_binder(\n" +" birthday_service,\n" +" binder::BinderFeatures::default(),\n" +" );\n" +" binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder." +"as_binder())\n" +" .expect(\"Failed to register service\");\n" +" binder::ProcessState::join_thread_pool()\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/server.md:30 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_server\",\n" +" crate_name: \"birthday_server\",\n" +" srcs: [\"src/server.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" \"libbirthdayservice\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:1 +#, fuzzy +msgid "# Deploy" +msgstr "# Ανάπτυξη" + +#: src/android/aidl/deploy.md:3 +#, fuzzy +msgid "We can now build, push, and start the service:" +msgstr "" +"Μπορούμε τώρα να δημιουργήσουμε, να προωθήσουμε και να ξεκινήσουμε την " +"υπηρεσία:" + +#: src/android/aidl/deploy.md:5 +msgid "" +"```shell\n" +"$ m birthday_server\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_server\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:11 +#, fuzzy +msgid "In another terminal, check that the service runs:" +msgstr "Σε άλλο τερματικό, ελέγξτε ότι η υπηρεσία εκτελείται:" + +#: src/android/aidl/deploy.md:13 +msgid "" +"```shell\n" +"$ adb shell service check birthdayservice\n" +"Service birthdayservice: found\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:18 +#, fuzzy +msgid "You can also call the service with `service call`:" +msgstr "Μπορείτε επίσης να καλέσετε την υπηρεσία με «κλήση υπηρεσίας»:" + +#: src/android/aidl/deploy.md:20 +msgid "" +"```shell\n" +"$ $ adb shell service call birthdayservice 1 s16 Bob i32 24\n" +"Result: Parcel(\n" +" 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" +" 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" +" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'\n" +" 0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'\n" +" 0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'\n" +" 0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'\n" +" 0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'\n" +" 0x00000070: 00210073 00000000 's.!..... ')\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:1 +#, fuzzy +msgid "# AIDL Client" +msgstr "# Πελάτης AIDL" + +#: src/android/aidl/client.md:3 +#, fuzzy +msgid "Finally, we can create a Rust client for our new service." +msgstr "" +"Τέλος, μπορούμε να δημιουργήσουμε έναν πελάτη Rust για τη νέα μας υπηρεσία." + +#: src/android/aidl/client.md:5 +#, fuzzy +msgid "*birthday_service/src/client.rs*:" +msgstr "*birthday_service/src/client.rs*:" + +#: src/android/aidl/client.md:7 +msgid "" +"```rust,ignore\n" +"//! Birthday service.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::" +"IBirthdayService::IBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" +"/// Connect to the BirthdayService.\n" +"pub fn connect() -> Result, binder::" +"StatusCode> {\n" +" binder::get_interface(SERVICE_IDENTIFIER)\n" +"}\n" +"\n" +"/// Call the birthday service.\n" +"fn main() -> Result<(), binder::Status> {\n" +" let name = std::env::args()\n" +" .nth(1)\n" +" .unwrap_or_else(|| String::from(\"Bob\"));\n" +" let years = std::env::args()\n" +" .nth(2)\n" +" .and_then(|arg| arg.parse::().ok())\n" +" .unwrap_or(42);\n" +"\n" +" binder::ProcessState::start_thread_pool();\n" +" let service = connect().expect(\"Failed to connect to " +"BirthdayService\");\n" +" let msg = service.wishHappyBirthday(&name, years)?;\n" +" println!(\"{msg}\");\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:39 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_client\",\n" +" crate_name: \"birthday_client\",\n" +" srcs: [\"src/client.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:52 +#, fuzzy +msgid "Notice that the client does not depend on `libbirthdayservice`." +msgstr "Σημειώστε ότι ο πελάτης δεν εξαρτάται από το \"libbirthdayservice\"." + +#: src/android/aidl/client.md:54 +#, fuzzy +msgid "Build, push, and run the client on your device:" +msgstr "Δημιουργήστε, προωθήστε και εκτελέστε τον πελάτη στη συσκευή σας:" + +#: src/android/aidl/client.md:56 +msgid "" +"```shell\n" +"$ m birthday_client\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_client Charlie 60\n" +"Happy Birthday Charlie, congratulations with the 60 years!\n" +"```" +msgstr "" + +#: src/android/aidl/changing.md:1 +#, fuzzy +msgid "# Changing API" +msgstr "# Αλλαγή API" + +#: src/android/aidl/changing.md:3 +#, fuzzy +msgid "" +"Let us extend the API with more functionality: we want to let clients " +"specify a\n" +"list of lines for the birthday card:" +msgstr "" +"Ας επεκτείνουμε το API με περισσότερη λειτουργικότητα: θέλουμε να " +"επιτρέψουμε στους πελάτες να καθορίσουν α\n" +"λίστα γραμμών για την κάρτα γενεθλίων:" + +#: src/android/aidl/changing.md:6 +msgid "" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years, in String[] text);\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:1 src/bare-metal/aps/logging.md:1 +#, fuzzy +msgid "# Logging" +msgstr "# Καταγραφή" + +#: src/android/logging.md:3 +#, fuzzy +msgid "" +"You should use the `log` crate to automatically log to `logcat` (on-device) " +"or\n" +"`stdout` (on-host):" +msgstr "" +"Θα πρέπει να χρησιμοποιήσετε το κιβώτιο «log» για αυτόματη σύνδεση στο " +"«logcat» (σε συσκευή) ή\n" +"`stdout` (στον οικοδεσπότη):" + +#: src/android/logging.md:6 +#, fuzzy +msgid "_hello_rust_logs/Android.bp_:" +msgstr "_hello_rust_logs/Android.bp_:" + +#: src/android/logging.md:8 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_logs\",\n" +" crate_name: \"hello_rust_logs\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"liblog_rust\",\n" +" \"liblogger\",\n" +" ],\n" +" prefer_rlib: true,\n" +" host_supported: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:22 +#, fuzzy +msgid "_hello_rust_logs/src/main.rs_:" +msgstr "_hello_rust_logs/src/main.rs_:" + +#: src/android/logging.md:24 +msgid "" +"```rust,ignore\n" +"//! Rust logging demo.\n" +"\n" +"use log::{debug, error, info};\n" +"\n" +"/// Logs a greeting.\n" +"fn main() {\n" +" logger::init(\n" +" logger::Config::default()\n" +" .with_tag_on_device(\"rust\")\n" +" .with_min_level(log::Level::Trace),\n" +" );\n" +" debug!(\"Starting program.\");\n" +" info!(\"Things are going fine.\");\n" +" error!(\"Something went wrong!\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:42 src/android/interoperability/with-c/bindgen.md:98 +#: src/android/interoperability/with-c/rust.md:73 +#, fuzzy +msgid "Build, push, and run the binary on your device:" +msgstr "Δημιουργήστε, σπρώξτε και εκτελέστε το δυαδικό στη συσκευή σας:" + +#: src/android/logging.md:44 +msgid "" +"```shell\n" +"$ m hello_rust_logs\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust_logs\n" +"```" +msgstr "" + +#: src/android/logging.md:50 +#, fuzzy +msgid "The logs show up in `adb logcat`:" +msgstr "Τα αρχεία καταγραφής εμφανίζονται στο `adb logcat`:" + +#: src/android/logging.md:52 +msgid "" +"```shell\n" +"$ adb logcat -s rust\n" +"09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.\n" +"09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going " +"fine.\n" +"09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went " +"wrong!\n" +"```" +msgstr "" + +#: src/android/interoperability.md:1 +#, fuzzy +msgid "# Interoperability" +msgstr "# Διαλειτουργικότητα" + +#: src/android/interoperability.md:3 +#, fuzzy +msgid "" +"Rust has excellent support for interoperability with other languages. This " +"means\n" +"that you can:" +msgstr "" +"Το Rust έχει εξαιρετική υποστήριξη για διαλειτουργικότητα με άλλες γλώσσες. " +"Αυτό σημαίνει\n" +"ότι μπορείτε να:" + +#: src/android/interoperability.md:6 +#, fuzzy +msgid "" +"* Call Rust functions from other languages.\n" +"* Call functions written in other languages from Rust." +msgstr "" +"* Καλέστε τις λειτουργίες Rust από άλλες γλώσσες.\n" +"* Κλήση συναρτήσεων γραμμένων σε άλλες γλώσσες από το Rust." + +#: src/android/interoperability.md:9 +#, fuzzy +msgid "" +"When you call functions in a foreign language we say that you're using a\n" +"_foreign function interface_, also known as FFI." +msgstr "" +"Όταν καλείτε συναρτήσεις σε μια ξένη γλώσσα, λέμε ότι χρησιμοποιείτε a\n" +"_ξένη διεπαφή λειτουργίας_, επίσης γνωστή ως FFI." + +#: src/android/interoperability/with-c.md:1 +#, fuzzy +msgid "# Interoperability with C" +msgstr "# Διαλειτουργικότητα με C" + +#: src/android/interoperability/with-c.md:3 +#, fuzzy +msgid "" +"Rust has full support for linking object files with a C calling convention.\n" +"Similarly, you can export Rust functions and call them from C." +msgstr "" +"Το Rust έχει πλήρη υποστήριξη για τη σύνδεση αρχείων αντικειμένων με μια " +"σύμβαση κλήσης C.\n" +"Ομοίως, μπορείτε να εξάγετε συναρτήσεις Rust και να τις καλέσετε από το C." + +#: src/android/interoperability/with-c.md:6 +#, fuzzy +msgid "You can do it by hand if you want:" +msgstr "Μπορείτε να το κάνετε με το χέρι αν θέλετε:" + +#: src/android/interoperability/with-c.md:8 +msgid "" +"```rust\n" +"extern \"C\" {\n" +" fn abs(x: i32) -> i32;\n" +"}\n" +"\n" +"fn main() {\n" +" let x = -42;\n" +" let abs_x = unsafe { abs(x) };\n" +" println!(\"{x}, {abs_x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c.md:20 +#, fuzzy +msgid "" +"We already saw this in the [Safe FFI Wrapper\n" +"exercise](../../exercises/day-3/safe-ffi-wrapper.md)." +msgstr "" +"Το είδαμε ήδη στο [Safe FFI Wrapper\n" +"άσκηση](../../exercises/day-3/safe-ffi-wrapper.md)." + +#: src/android/interoperability/with-c.md:23 +#, fuzzy +msgid "" +"> This assumes full knowledge of the target platform. Not recommended for\n" +"> production." +msgstr "" +"> Αυτό προϋποθέτει πλήρη γνώση της πλατφόρμας-στόχου. Δεν συνιστάται για\n" +"> παραγωγή." + +#: src/android/interoperability/with-c.md:26 +#, fuzzy +msgid "We will look at better options next." +msgstr "Θα εξετάσουμε καλύτερες επιλογές στη συνέχεια." + +#: src/android/interoperability/with-c/bindgen.md:1 +#, fuzzy +msgid "# Using Bindgen" +msgstr "# Χρήση Bindgen" + +#: src/android/interoperability/with-c/bindgen.md:3 +#, fuzzy +msgid "" +"The [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html) " +"tool\n" +"can auto-generate bindings from a C header file." +msgstr "" +"Το εργαλείο [bindgen](https://rust-lang.github.io/rust-bindgen/introduction." +"html)\n" +"μπορεί να δημιουργήσει αυτόματα δεσμεύσεις από ένα αρχείο κεφαλίδας C." + +#: src/android/interoperability/with-c/bindgen.md:6 +#, fuzzy +msgid "First create a small C library:" +msgstr "Πρώτα δημιουργήστε μια μικρή βιβλιοθήκη C:" + +#: src/android/interoperability/with-c/bindgen.md:8 +#, fuzzy +msgid "_interoperability/bindgen/libbirthday.h_:" +msgstr "_interoperability/bindgen/libbirthday.h_:" + +#: src/android/interoperability/with-c/bindgen.md:10 +msgid "" +"```c\n" +"typedef struct card {\n" +" const char* name;\n" +" int years;\n" +"} card;\n" +"\n" +"void print_card(const card* card);\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:19 +#, fuzzy +msgid "_interoperability/bindgen/libbirthday.c_:" +msgstr "_interoperability/bindgen/libbirthday.c_:" + +#: src/android/interoperability/with-c/bindgen.md:21 +msgid "" +"```c\n" +"#include \n" +"#include \"libbirthday.h\"\n" +"\n" +"void print_card(const card* card) {\n" +" printf(\"+--------------\\n\");\n" +" printf(\"| Happy Birthday %s!\\n\", card->name);\n" +" printf(\"| Congratulations with the %i years!\\n\", card->years);\n" +" printf(\"+--------------\\n\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:33 +#, fuzzy +msgid "Add this to your `Android.bp` file:" +msgstr "Προσθέστε αυτό στο αρχείο σας «Android.bp»:" + +#: src/android/interoperability/with-c/bindgen.md:35 +#: src/android/interoperability/with-c/bindgen.md:55 +#: src/android/interoperability/with-c/bindgen.md:69 +#: src/android/interoperability/with-c/bindgen.md:108 +#, fuzzy +msgid "_interoperability/bindgen/Android.bp_:" +msgstr "_interoperability/bindgen/Android.bp_:" + +#: src/android/interoperability/with-c/bindgen.md:37 +msgid "" +"```javascript\n" +"cc_library {\n" +" name: \"libbirthday\",\n" +" srcs: [\"libbirthday.c\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:44 +#, fuzzy +msgid "" +"Create a wrapper header file for the library (not strictly needed in this\n" +"example):" +msgstr "" +"Δημιουργήστε ένα αρχείο κεφαλίδας περιτυλίγματος για τη βιβλιοθήκη (δεν " +"απαιτείται αυστηρά σε αυτό\n" +"παράδειγμα):" + +#: src/android/interoperability/with-c/bindgen.md:47 +#, fuzzy +msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" +msgstr "_interoperability/bindgen/libbirthday_wrapper.h_:" + +#: src/android/interoperability/with-c/bindgen.md:49 +msgid "" +"```c\n" +"#include \"libbirthday.h\"\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:53 +#, fuzzy +msgid "You can now auto-generate the bindings:" +msgstr "Τώρα μπορείτε να δημιουργήσετε αυτόματα τις συνδέσεις:" + +#: src/android/interoperability/with-c/bindgen.md:57 +msgid "" +"```javascript\n" +"rust_bindgen {\n" +" name: \"libbirthday_bindgen\",\n" +" crate_name: \"birthday_bindgen\",\n" +" wrapper_src: \"libbirthday_wrapper.h\",\n" +" source_stem: \"bindings\",\n" +" static_libs: [\"libbirthday\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:67 +#, fuzzy +msgid "Finally, we can use the bindings in our Rust program:" +msgstr "Τέλος, μπορούμε να χρησιμοποιήσουμε τις συνδέσεις στο πρόγραμμα Rust:" + +#: src/android/interoperability/with-c/bindgen.md:71 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"print_birthday_card\",\n" +" srcs: [\"main.rs\"],\n" +" rustlibs: [\"libbirthday_bindgen\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:79 +#, fuzzy +msgid "_interoperability/bindgen/main.rs_:" +msgstr "_interoperability/bindgen/main.rs_:" + +#: src/android/interoperability/with-c/bindgen.md:81 +msgid "" +"```rust,compile_fail\n" +"//! Bindgen demo.\n" +"\n" +"use birthday_bindgen::{card, print_card};\n" +"\n" +"fn main() {\n" +" let name = std::ffi::CString::new(\"Peter\").unwrap();\n" +" let card = card {\n" +" name: name.as_ptr(),\n" +" years: 42,\n" +" };\n" +" unsafe {\n" +" print_card(&card as *const card);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:100 +msgid "" +"```shell\n" +"$ m print_birthday_card\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/" +"tmp\n" +"$ adb shell /data/local/tmp/print_birthday_card\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:106 +#, fuzzy +msgid "Finally, we can run auto-generated tests to ensure the bindings work:" +msgstr "" +"Τέλος, μπορούμε να εκτελέσουμε δοκιμές που δημιουργούνται αυτόματα για να " +"διασφαλίσουμε ότι οι δεσμεύσεις λειτουργούν:" + +#: src/android/interoperability/with-c/bindgen.md:110 +msgid "" +"```javascript\n" +"rust_test {\n" +" name: \"libbirthday_bindgen_test\",\n" +" srcs: [\":libbirthday_bindgen\"],\n" +" crate_name: \"libbirthday_bindgen_test\",\n" +" test_suites: [\"general-tests\"],\n" +" auto_gen_config: true,\n" +" clippy_lints: \"none\", // Generated file, skip linting\n" +" lints: \"none\",\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:122 +msgid "" +"```shell\n" +"$ atest libbirthday_bindgen_test\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:1 +#, fuzzy +msgid "# Calling Rust" +msgstr "# Calling Rust" + +#: src/android/interoperability/with-c/rust.md:3 +#, fuzzy +msgid "Exporting Rust functions and types to C is easy:" +msgstr "Η εξαγωγή λειτουργιών και τύπων Rust στο C είναι εύκολη:" + +#: src/android/interoperability/with-c/rust.md:5 +#, fuzzy +msgid "_interoperability/rust/libanalyze/analyze.rs_" +msgstr "_interoperability/rust/libanalyze/analyze.rs_" + +#: src/android/interoperability/with-c/rust.md:7 +msgid "" +"```rust,editable\n" +"//! Rust FFI demo.\n" +"#![deny(improper_ctypes_definitions)]\n" +"\n" +"use std::os::raw::c_int;\n" +"\n" +"/// Analyze the numbers.\n" +"#[no_mangle]\n" +"pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" +" if x < y {\n" +" println!(\"x ({x}) is smallest!\");\n" +" } else {\n" +" println!(\"y ({y}) is probably larger than x ({x})\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:24 +#, fuzzy +msgid "_interoperability/rust/libanalyze/analyze.h_" +msgstr "_interoperability/rust/libanalyze/analyze.h_" + +#: src/android/interoperability/with-c/rust.md:26 +msgid "" +"```c\n" +"#ifndef ANALYSE_H\n" +"#define ANALYSE_H\n" +"\n" +"extern \"C\" {\n" +"void analyze_numbers(int x, int y);\n" +"}\n" +"\n" +"#endif\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:37 +#, fuzzy +msgid "_interoperability/rust/libanalyze/Android.bp_" +msgstr "_interoperability/rust/libanalyze/Android.bp_" + +#: src/android/interoperability/with-c/rust.md:39 +msgid "" +"```javascript\n" +"rust_ffi {\n" +" name: \"libanalyze_ffi\",\n" +" crate_name: \"analyze_ffi\",\n" +" srcs: [\"analyze.rs\"],\n" +" include_dirs: [\".\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:48 +#, fuzzy +msgid "We can now call this from a C binary:" +msgstr "Μπορούμε τώρα να το ονομάσουμε αυτό από ένα δυαδικό C:" + +#: src/android/interoperability/with-c/rust.md:50 +#, fuzzy +msgid "_interoperability/rust/analyze/main.c_" +msgstr "_interoperability/rust/analyze/main.c_" + +#: src/android/interoperability/with-c/rust.md:52 +msgid "" +"```c\n" +"#include \"analyze.h\"\n" +"\n" +"int main() {\n" +" analyze_numbers(10, 20);\n" +" analyze_numbers(123, 123);\n" +" return 0;\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:62 +#, fuzzy +msgid "_interoperability/rust/analyze/Android.bp_" +msgstr "_interoperability/rust/analyze/Android.bp_" + +#: src/android/interoperability/with-c/rust.md:64 +msgid "" +"```javascript\n" +"cc_binary {\n" +" name: \"analyze_numbers\",\n" +" srcs: [\"main.c\"],\n" +" static_libs: [\"libanalyze_ffi\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:75 +msgid "" +"```shell\n" +"$ m analyze_numbers\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp\n" +"$ adb shell /data/local/tmp/analyze_numbers\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:83 +#, fuzzy +msgid "" +"`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol " +"will just be the name of\n" +"the function. You can also use `#[export_name = \"some_name\"]` to specify " +"whatever name you want." +msgstr "" +"Το \"#[no_mangle]\" απενεργοποιεί τη συνήθη παραποίηση ονόματος του Rust, " +"επομένως το σύμβολο που θα εξαχθεί θα είναι απλώς το όνομα του\n" +"η λειτουργία. Μπορείτε επίσης να χρησιμοποιήσετε το `#[export_name = " +"\"some_name\"]` για να καθορίσετε όποιο όνομα θέλετε." + +#: src/android/interoperability/cpp.md:1 +#, fuzzy +msgid "# With C++" +msgstr "# Με C++" + +#: src/android/interoperability/cpp.md:3 +#, fuzzy +msgid "" +"The [CXX crate][1] makes it possible to do safe interoperability between " +"Rust\n" +"and C++." +msgstr "" +"Το [CXX crate][1] καθιστά δυνατή την ασφαλή διαλειτουργικότητα μεταξύ του " +"Rust\n" +"και C++." + +#: src/android/interoperability/cpp.md:6 +#, fuzzy +msgid "The overall approach looks like this:" +msgstr "Η συνολική προσέγγιση μοιάζει με αυτό:" + +#: src/android/interoperability/cpp.md:8 +#, fuzzy +msgid "" +msgstr "" + +#: src/android/interoperability/cpp.md:10 +#, fuzzy +msgid "See the [CXX tutorial][2] for an full example of using this." +msgstr "Δείτε το [CXX tutorial][2] για ένα πλήρες παράδειγμα χρήσης αυτού." + +#: src/android/interoperability/java.md:1 +#, fuzzy +msgid "# Interoperability with Java" +msgstr "# Διαλειτουργικότητα με Java" + +#: src/android/interoperability/java.md:3 +#, fuzzy +msgid "" +"Java can load shared objects via [Java Native Interface\n" +"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). The [`jni`\n" +"crate](https://docs.rs/jni/) allows you to create a compatible library." +msgstr "" +"Η Java μπορεί να φορτώσει κοινόχρηστα αντικείμενα μέσω του [Java Native " +"Interface\n" +"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). Το [`jni`\n" +"crate](https://docs.rs/jni/) σας επιτρέπει να δημιουργήσετε μια συμβατή " +"βιβλιοθήκη." + +#: src/android/interoperability/java.md:7 +#, fuzzy +msgid "First, we create a Rust function to export to Java:" +msgstr "Αρχικά, δημιουργούμε μια συνάρτηση Rust για εξαγωγή σε Java:" + +#: src/android/interoperability/java.md:9 +#, fuzzy +msgid "_interoperability/java/src/lib.rs_:" +msgstr "_interoperability/java/src/lib.rs_:" + +#: src/android/interoperability/java.md:11 +msgid "" +"```rust,compile_fail\n" +"//! Rust <-> Java FFI demo.\n" +"\n" +"use jni::objects::{JClass, JString};\n" +"use jni::sys::jstring;\n" +"use jni::JNIEnv;\n" +"\n" +"/// HelloWorld::hello method implementation.\n" +"#[no_mangle]\n" +"pub extern \"system\" fn Java_HelloWorld_hello(\n" +" env: JNIEnv,\n" +" _class: JClass,\n" +" name: JString,\n" +") -> jstring {\n" +" let input: String = env.get_string(name).unwrap().into();\n" +" let greeting = format!(\"Hello, {input}!\");\n" +" let output = env.new_string(greeting).unwrap();\n" +" output.into_inner()\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:32 +#: src/android/interoperability/java.md:62 +#, fuzzy +msgid "_interoperability/java/Android.bp_:" +msgstr "_interoperability/java/Android.bp_:" + +#: src/android/interoperability/java.md:34 +msgid "" +"```javascript\n" +"rust_ffi_shared {\n" +" name: \"libhello_jni\",\n" +" crate_name: \"hello_jni\",\n" +" srcs: [\"src/lib.rs\"],\n" +" rustlibs: [\"libjni\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:43 +#, fuzzy +msgid "Finally, we can call this function from Java:" +msgstr "Τέλος, μπορούμε να καλέσουμε αυτή τη συνάρτηση από την Java:" + +#: src/android/interoperability/java.md:45 +#, fuzzy +msgid "_interoperability/java/HelloWorld.java_:" +msgstr "_interoperability/java/HelloWorld.java_:" + +#: src/android/interoperability/java.md:47 +msgid "" +"```java\n" +"class HelloWorld {\n" +" private static native String hello(String name);\n" +"\n" +" static {\n" +" System.loadLibrary(\"hello_jni\");\n" +" }\n" +"\n" +" public static void main(String[] args) {\n" +" String output = HelloWorld.hello(\"Alice\");\n" +" System.out.println(output);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:64 +msgid "" +"```javascript\n" +"java_binary {\n" +" name: \"helloworld_jni\",\n" +" srcs: [\"HelloWorld.java\"],\n" +" main_class: \"HelloWorld\",\n" +" required: [\"libhello_jni\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:73 +#, fuzzy +msgid "Finally, you can build, sync, and run the binary:" +msgstr "" +"Τέλος, μπορείτε να δημιουργήσετε, να συγχρονίσετε και να εκτελέσετε το " +"δυαδικό:" + +#: src/android/interoperability/java.md:75 +msgid "" +"```shell\n" +"$ m helloworld_jni\n" +"$ adb sync # requires adb root && adb remount\n" +"$ adb shell /system/bin/helloworld_jni\n" +"```" +msgstr "" + +#: src/exercises/day-4/android.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:" +msgstr "" +"Για την τελευταία άσκηση, θα δούμε ένα από τα έργα με τα οποία εργάζεστε. " +"Αφήστε μας\n" +"ομαδοποιήστε και κάντε αυτό μαζί. Μερικές προτάσεις:" + +#: src/exercises/day-4/android.md:6 +#, fuzzy +msgid "" +"* Call your AIDL service with a client written in Rust.\n" +"\n" +"* Move a function from your project to Rust and call it." +msgstr "* Μετακινήστε μια συνάρτηση από το έργο σας στο Rust και καλέστε την." + +#: src/exercises/day-4/android.md:12 +#, fuzzy +msgid "" +"No solution is provided here since this is open-ended: it relies on someone " +"in\n" +"the class having a piece of code which you can turn in to Rust on the fly." +msgstr "" +"Δεν παρέχεται λύση εδώ, δεδομένου ότι αυτό είναι ανοιχτό: βασίζεται σε " +"κάποιον μέσα\n" +"η τάξη έχει ένα κομμάτι κώδικα που μπορείτε να μεταφέρετε στο Rust on the " +"fly." + +#: src/thanks.md:1 +#, fuzzy +msgid "# Thanks!" +msgstr "# Ευχαριστώ!" + +#: src/thanks.md:3 +#, fuzzy +msgid "" +"_Thank you for taking Comprehensive Rust 🦀!_ We hope you enjoyed it and " +"that it\n" +"was useful." +msgstr "" +"_Σας ευχαριστούμε που πήρατε το Comprehensive Rust 🦀!_ Ελπίζουμε να σας " +"άρεσε και να\n" +"ήταν χρήσιμο." + +#: 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 "" +"Διασκεδάσαμε πολύ όταν συνδυάσαμε το μάθημα. Το μάθημα δεν είναι τέλειο,\n" +"οπότε αν εντοπίσατε λάθη ή έχετε ιδέες για βελτιώσεις, παρακαλούμε μπείτε\n" +"[επικοινωνήστε μαζί μας στο\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Θα " +"αγαπούσαμε\n" +"να ακούσω από σένα." + +#: src/other-resources.md:1 +#, fuzzy +msgid "# Other Rust Resources" +msgstr "# Άλλοι πόροι σκουριάς" + +#: src/other-resources.md:3 +#, fuzzy +msgid "" +"The Rust community has created a wealth of high-quality and free resources\n" +"online." +msgstr "" +"Η κοινότητα του Rust έχει δημιουργήσει έναν πλούτο υψηλής ποιότητας και " +"δωρεάν πόρων\n" +"Σε σύνδεση." + +#: src/other-resources.md:6 +#, fuzzy +msgid "## Official Documentation" +msgstr "## Επίσημη Τεκμηρίωση" + +#: src/other-resources.md:8 +#, fuzzy +msgid "The Rust project hosts many resources. These cover Rust in general:" +msgstr "Το έργο Rust φιλοξενεί πολλούς πόρους. Αυτά καλύπτουν το Rust γενικά:" + +#: 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 "" +"* [The Rust Programming Language](https://doc.rust-lang.org/book/): το\n" +" κανονικό δωρεάν βιβλίο για το Rust. Καλύπτει αναλυτικά τη γλώσσα και " +"περιλαμβάνει α\n" +" λίγα έργα για να κατασκευάσουν οι άνθρωποι.\n" +"* [Rust By Example](https://doc.rust-lang.org/rust-by-example/): καλύπτει τη " +"σκουριά\n" +" σύνταξη μέσω μιας σειράς παραδειγμάτων που παρουσιάζουν διαφορετικές " +"κατασκευές. Ωρες ωρες\n" +" περιλαμβάνει μικρές ασκήσεις όπου σας ζητείται να αναπτύξετε τον κώδικα " +"στο\n" +" παραδείγματα.\n" +"* [Rust Standard Library](https://doc.rust-lang.org/std/): πλήρης τεκμηρίωση " +"του\n" +" η τυπική βιβλιοθήκη για το Rust.\n" +"* [The Rust Reference](https://doc.rust-lang.org/reference/): ένα ημιτελές " +"βιβλίο\n" +" που περιγράφει το μοντέλο της γραμματικής και της μνήμης Rust." + +#: src/other-resources.md:22 +#, fuzzy +msgid "More specialized guides hosted on the official Rust site:" +msgstr "" +"Περισσότεροι εξειδικευμένοι οδηγοί που φιλοξενούνται στον επίσημο ιστότοπο " +"της Rust:" + +#: 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/): καλύπτει το μη " +"ασφαλές Rust,\n" +" συμπεριλαμβανομένης της εργασίας με ακατέργαστους δείκτες και της διεπαφής " +"με άλλες γλώσσες\n" +" (FFI).\n" +"* [Asynchronous Programming in Rust](https://rust-lang.github.io/async-" +"book/):\n" +" καλύπτει το νέο μοντέλο ασύγχρονου προγραμματισμού που εισήχθη μετά το\n" +" Το Rust Book γράφτηκε.\n" +"* [The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-" +"book/):\n" +" εισαγωγή στη χρήση του Rust σε ενσωματωμένες συσκευές χωρίς λειτουργικό " +"σύστημα." + +#: src/other-resources.md:33 +#, fuzzy +msgid "## Unofficial Learning Material" +msgstr "## Ανεπίσημο Εκπαιδευτικό Υλικό" + +#: src/other-resources.md:35 +#, fuzzy +msgid "A small selection of other guides and tutorial for Rust:" +msgstr "Μια μικρή επιλογή άλλων οδηγών και οδηγών για το 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/): καλύπτει " +"το Rust\n" +" από την οπτική γωνία των προγραμματιστών χαμηλού επιπέδου C.\n" +"* [Rust for Embedded C\n" +" Προγραμματιστές](https://docs.opentitan.org/doc/ug/rust_for_c/): καλύπτει " +"το Rust από\n" +" η προοπτική των προγραμματιστών που γράφουν υλικολογισμικό σε C.\n" +"* [Rust για επαγγελματίες](https://overexact.com/rust-for-professionals/):\n" +" καλύπτει τη σύνταξη του Rust χρησιμοποιώντας συγκρίσεις δίπλα-δίπλα με " +"άλλες γλώσσες\n" +" όπως C, C++, Java, JavaScript και Python.\n" +"* [Rust on Exercism](https://exercism.org/tracks/rust): 100+ ασκήσεις για " +"βοήθεια\n" +" μαθαίνεις Rust.\n" +"* [Σιδήρου Διδασκαλία\n" +" Υλικό](https://ferrous-systems.github.io/teaching-material/index.html): α\n" +" σειρά μικρών παρουσιάσεων που καλύπτουν τόσο βασικό όσο και προχωρημένο " +"μέρος του\n" +" Γλώσσα σκουριάς. Άλλα θέματα όπως το WebAssembly και το async/wait είναι " +"επίσης\n" +" σκεπαστός.\n" +"* [Beginner's Series to\n" +" Rust](https://docs.microsoft.com/en-us/shows/beginners-series-to-rust/) " +"και\n" +" [Κάντε τα πρώτα σας βήματα με\n" +" Rust](https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/): " +"δύο\n" +" Οδηγοί Rust που απευθύνονται σε νέους προγραμματιστές. Το πρώτο είναι ένα " +"σύνολο 35 βίντεο και το\n" +" Το δεύτερο είναι ένα σύνολο 11 ενοτήτων που καλύπτει τη σύνταξη του Rust " +"και τις βασικές δομές." + +#: 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 "" +"Δείτε το [Little Book of Rust Books](https://lborb.github.io/book/) για\n" +"ακόμα περισσότερα βιβλία Rust." + +#: src/credits.md:1 +#, fuzzy +msgid "# Credits" +msgstr "# Πιστώσεις" + +#: 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 "" +"Το υλικό εδώ βασίζεται στις πολλές σπουδαίες πηγές τεκμηρίωσης του Rust.\n" +"Δείτε τη σελίδα στο [other resources](other-resources.md) για μια πλήρη " +"λίστα χρήσιμων\n" +"πόροι." + +#: 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 "" +"Το υλικό του Comprehensive Rust έχει άδεια χρήσης σύμφωνα με τους όρους του " +"Apache 2.0\n" +"άδεια, ανατρέξτε στην ενότητα [`ΑΔΕΙΑ`](../LICENSE) για λεπτομέρειες." + +#: src/credits.md:10 +#, fuzzy +msgid "## Rust by Example" +msgstr "## Σκουριά από Παράδειγμα" + +#: 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 "" +"Ορισμένα παραδείγματα και ασκήσεις έχουν αντιγραφεί και προσαρμοστεί από το " +"[Rust by\n" +"Παράδειγμα](https://doc.rust-lang.org/rust-by-example/). Παρακαλώ δείτε το\n" +"Κατάλογος `third_party/rust-by-example/` για λεπτομέρειες, " +"συμπεριλαμβανομένης της άδειας χρήσης\n" +"όροι." + +#: src/credits.md:17 +#, fuzzy +msgid "## Rust on Exercism" +msgstr "## Σκουριά στην άσκηση" + +#: 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 "" +"Ορισμένες ασκήσεις έχουν αντιγραφεί και προσαρμοστεί από το [Rust on\n" +"Άσκηση](https://exercism.org/tracks/rust). Παρακαλώ δείτε το\n" +"Κατάλογος `third_party/rust-on-exercism/` για λεπτομέρειες, " +"συμπεριλαμβανομένης της άδειας\n" +"όροι." + +#: 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 "" +"Η ενότητα [Διαλειτουργικότητα με C++](android/interoperability/cpp.md) " +"χρησιμοποιεί ένα\n" +"εικόνα από [CXX](https://cxx.rs/). Δείτε τον κατάλογο `third_party/cxx/`\n" +"για λεπτομέρειες, συμπεριλαμβανομένων των όρων άδειας." + +#: src/welcome-bare-metal.md:1 +#, fuzzy +msgid "# Welcome to Bare Metal Rust" +msgstr "# Καλώς ήρθατε στην Comprehensive Rust 🦀" + +#: src/welcome-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" +"basics of Rust (perhaps from completing the Comprehensive Rust course), and " +"ideally also have some\n" +"experience with bare-metal programming in some other language such as C." +msgstr "" + +#: src/welcome-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 +msgid "" +"- What is `no_std` Rust?\n" +"- Writing firmware for microcontrollers.\n" +"- Writing bootloader / kernel code for application processors.\n" +"- Some useful crates for bare-metal Rust development." +msgstr "" + +#: src/welcome-bare-metal.md:15 +msgid "" +"For the microcontroller part of the course we will use the [BBC micro:bit]" +"(https://microbit.org/) v2\n" +"as an example. It's a [development board](https://tech.microbit.org/" +"hardware/) based on the Nordic\n" +"nRF51822 microcontroller with some LEDs and buttons, an I2C-connected " +"accelerometer and compass, and\n" +"an on-board SWD debugger." +msgstr "" + +#: src/welcome-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 +msgid "" +"```bash\n" +"sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom " +"qemu-system-arm\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" +msgstr "" + +#: src/welcome-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 +msgid "" +"```bash\n" +"echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", " +"GROUP=\"plugdev\"' |\\\n" +" sudo tee /etc/udev/rules.d/50-microbit.rules\n" +"sudo udevadm control --reload-rules\n" +"```" +msgstr "" + +#: src/welcome-bare-metal.md:38 +msgid "On MacOS:" +msgstr "" + +#: src/welcome-bare-metal.md:40 +msgid "" +"```bash\n" +"xcode-select --install\n" +"brew install gdb picocom qemu\n" +"brew install --cask gcc-aarch64-embedded\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" +msgstr "" + +#: src/bare-metal/no_std.md:1 +msgid "# `no_std`" +msgstr "" + +#: src/bare-metal/no_std.md:3 +msgid "" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"
" +msgstr "" + +#: src/bare-metal/no_std.md:7 +msgid "`core`" +msgstr "" + +#: src/bare-metal/no_std.md:9 src/bare-metal/no_std.md:14 +msgid "" +"" +msgstr "" + +#: src/bare-metal/no_std.md:12 +msgid "`alloc`" +msgstr "" + +#: src/bare-metal/no_std.md:17 +msgid "`std`" +msgstr "" + +#: src/bare-metal/no_std.md:19 +msgid "" +"
" +msgstr "" + +#: src/bare-metal/no_std.md:24 +msgid "" +"* Slices, `&str`, `CStr`\n" +"* `NonZeroU8`...\n" +"* `Option`, `Result`\n" +"* `Display`, `Debug`, `write!`...\n" +"* `Iterator`\n" +"* `panic!`, `assert_eq!`...\n" +"* `NonNull` and all the usual pointer-related functions\n" +"* `Future` and `async`/`await`\n" +"* `fence`, `AtomicBool`, `AtomicPtr`, `AtomicU32`...\n" +"* `Duration`" +msgstr "" + +#: src/bare-metal/no_std.md:35 src/bare-metal/no_std.md:42 +msgid "" +"" +msgstr "" + +#: src/bare-metal/no_std.md:38 +msgid "" +"* `Box`, `Cow`, `Arc`, `Rc`\n" +"* `Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque`\n" +"* `String`, `CString`, `format!`" +msgstr "" + +#: src/bare-metal/no_std.md:45 +msgid "" +"* `Error`\n" +"* `HashMap`\n" +"* `Mutex`, `Condvar`, `Barrier`, `Once`, `RwLock`, `mpsc`\n" +"* `File` and the rest of `fs`\n" +"* `println!`, `Read`, `Write`, `Stdin`, `Stdout` and the rest of `io`\n" +"* `Path`, `OsString`\n" +"* `net`\n" +"* `Command`, `Child`, `ExitCode`\n" +"* `spawn`, `sleep` and the rest of `thread`\n" +"* `SystemTime`, `Instant`" +msgstr "" + +#: src/bare-metal/no_std.md:56 +msgid "" +"
\n" +"\n" +"
" +msgstr "" + +#: src/bare-metal/no_std.md:62 +msgid "" +"* `HashMap` depends on RNG.\n" +"* `std` re-exports the contents of both `core` and `alloc`." +msgstr "" + +#: src/bare-metal/minimal.md:1 +msgid "# A minimal `no_std` program" +msgstr "" + +#: src/bare-metal/minimal.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::panic::PanicInfo;\n" +"\n" +"#[panic_handler]\n" +"fn panic(_panic: &PanicInfo) -> ! {\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/minimal.md:17 +msgid "" +"* This will compile to an empty binary.\n" +"* `std` provides a panic handler; without it we must provide our own.\n" +"* It can also be provided by another crate, such as `panic-halt`.\n" +"* Depending on the target, you may need to compile with `panic = \"abort\"` " +"to avoid an error about\n" +" `eh_personality`.\n" +"* Note that there is no `main` or any other entry point; it's up to you to " +"define your own entry\n" +" point. This will typically involve a linker script and some assembly code " +"to set things up ready\n" +" for Rust code to run." +msgstr "" + +#: src/bare-metal/alloc.md:1 +msgid "# `alloc`" +msgstr "" + +#: src/bare-metal/alloc.md:3 +msgid "" +"To use `alloc` you must implement a\n" +"[global (heap) allocator](https://doc.rust-lang.org/stable/std/alloc/trait." +"GlobalAlloc.html)." +msgstr "" + +#: src/bare-metal/alloc.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate alloc;\n" +"extern crate panic_halt as _;\n" +"\n" +"use alloc::{string::ToString, vec::Vec};\n" +"use buddy_system_allocator::LockedHeap;\n" +"\n" +"#[global_allocator]\n" +"static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();\n" +"\n" +"static mut HEAP: [u8; 65536] = [0; 65536];\n" +"\n" +"pub fn entry() {\n" +" // Safe because `HEAP` is only used here and `entry` is only called " +"once.\n" +" unsafe {\n" +" // Give the allocator some memory to allocate.\n" +" HEAP_ALLOCATOR\n" +" .lock()\n" +" .init(HEAP.as_mut_ptr() as usize, HEAP.len());\n" +" }\n" +"\n" +" // Now we can do things that require heap allocation.\n" +" let mut v = Vec::new();\n" +" v.push(\"A string\".to_string());\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/alloc.md:38 +msgid "" +"* `buddy_system_allocator` is a third-party crate implementing a basic buddy " +"system allocator. Other\n" +" crates are available, or you can write your own or hook into your existing " +"allocator.\n" +"* The const parameter of `LockedHeap` is the max order of the allocator; i." +"e. in this case it can\n" +" allocate regions of up to 2**32 bytes.\n" +"* If any crate in your dependency tree depends on `alloc` then you must have " +"exactly one global\n" +" allocator defined in your binary. Usually this is done in the top-level " +"binary crate.\n" +"* `extern crate panic_halt as _` is necessary to ensure that the " +"`panic_halt` crate is linked in so\n" +" we get its panic handler." +msgstr "" + +#: src/bare-metal/microcontrollers.md:1 +msgid "# Microcontrollers" +msgstr "" + +#: src/bare-metal/microcontrollers.md:3 +msgid "" +"The `cortex_m_rt` crate provides (among other things) a reset handler for " +"Cortex M microcontrollers." +msgstr "" + +#: src/bare-metal/microcontrollers.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use cortex_m_rt::entry;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers.md:21 +msgid "" +"Next we'll look at how to access peripherals, with increasing levels of " +"abstraction." +msgstr "" + +#: src/bare-metal/microcontrollers.md:25 +msgid "" +"* The `cortex_m_rt::entry` macro requires that the function have type `fn() -" +"> !`, because returning\n" +" to the reset handler doesn't make sense.\n" +"* Run the example with `cargo embed --bin minimal`" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:1 +msgid "# Raw MMIO" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:3 +msgid "" +"Most microcontrollers access peripherals via memory-mapped IO. Let's try " +"turning on an LED on our\n" +"micro:bit:" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use core::mem::size_of;\n" +"use cortex_m_rt::entry;\n" +"\n" +"/// GPIO port 0 peripheral address\n" +"const GPIO_P0: usize = 0x5000_0000;\n" +"\n" +"// GPIO peripheral offsets\n" +"const PIN_CNF: usize = 0x700;\n" +"const OUTSET: usize = 0x508;\n" +"const OUTCLR: usize = 0x50c;\n" +"\n" +"// PIN_CNF fields\n" +"const DIR_OUTPUT: u32 = 0x1;\n" +"const INPUT_DISCONNECT: u32 = 0x1 << 1;\n" +"const PULL_DISABLED: u32 = 0x0 << 2;\n" +"const DRIVE_S0S1: u32 = 0x0 << 8;\n" +"const SENSE_DISABLED: u32 = 0x0 << 16;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let pin_cnf_21 = (GPIO_P0 + PIN_CNF + 21 * size_of::()) as *mut " +"u32;\n" +" let pin_cnf_28 = (GPIO_P0 + PIN_CNF + 28 * size_of::()) as *mut " +"u32;\n" +" // Safe because the pointers are to valid peripheral control registers, " +"and\n" +" // no aliases exist.\n" +" unsafe {\n" +" pin_cnf_21.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | " +"SENSE_DISABLED,\n" +" );\n" +" pin_cnf_28.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | " +"SENSE_DISABLED,\n" +" );\n" +" }\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" let gpio0_outset = (GPIO_P0 + OUTSET) as *mut u32;\n" +" let gpio0_outclr = (GPIO_P0 + OUTCLR) as *mut u32;\n" +" // Safe because the pointers are to valid peripheral control registers, " +"and\n" +" // no aliases exist.\n" +" unsafe {\n" +" gpio0_outclr.write_volatile(1 << 28);\n" +" gpio0_outset.write_volatile(1 << 21);\n" +" }\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:64 +msgid "" +"* GPIO 0 pin 21 is connected to the first column of the LED matrix, and pin " +"28 to the first row." +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:66 +#: src/bare-metal/microcontrollers/pacs.md:59 +#: src/bare-metal/microcontrollers/hals.md:43 +#: src/bare-metal/microcontrollers/board-support.md:34 +msgid "Run the example with:" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:68 +msgid "" +"```sh\n" +"cargo embed --bin mmio\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:1 +msgid "# Peripheral Access Crates" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:3 +msgid "" +"[`svd2rust`](https://crates.io/crates/svd2rust) generates mostly-safe Rust " +"wrappers for\n" +"memory-mapped peripherals from [CMSIS-SVD](https://www.keil.com/pack/doc/" +"CMSIS/SVD/html/index.html)\n" +"files." +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_pac::Peripherals;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p.P0;\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" gpio0.pin_cnf[21].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +" gpio0.pin_cnf[28].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" gpio0.outclr.write(|w| w.pin28().clear());\n" +" gpio0.outset.write(|w| w.pin21().set());\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:49 +msgid "" +"* SVD (System View Description) files are XML files typically provided by " +"silicon vendors which\n" +" describe the memory map of the device.\n" +" * They are organised by peripheral, register, field and value, with names, " +"descriptions, addresses\n" +" and so on.\n" +" * SVD files are often buggy and incomplete, so there are various projects " +"which patch the\n" +" mistakes, add missing details, and publish the generated crates.\n" +"* `cortex-m-rt` provides the vector table, among other things.\n" +"* If you `cargo install cargo-binutils` then you can run\n" +" `cargo objdump --bin pac -- -d --no-show-raw-insn` to see the resulting " +"binary." +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:61 +msgid "" +"```sh\n" +"cargo embed --bin pac\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:1 +msgid "# HAL crates" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:3 +msgid "" +"[HAL crates](https://github.com/rust-embedded/awesome-embedded-rust#hal-" +"implementation-crates) for\n" +"many microcontrollers provide wrappers around various peripherals. These " +"generally implement traits\n" +"from [`embedded-hal`](https://crates.io/crates/embedded-hal)." +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_hal::gpio::{p0, Level};\n" +"use nrf52833_hal::pac::Peripherals;\n" +"use nrf52833_hal::prelude::*;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +"\n" +" // Create HAL wrapper for GPIO port 0.\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let mut col1 = gpio0.p0_28.into_push_pull_output(Level::High);\n" +" let mut row1 = gpio0.p0_21.into_push_pull_output(Level::Low);\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" col1.set_low().unwrap();\n" +" row1.set_high().unwrap();\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:39 +msgid "" +" * `set_low` and `set_high` are methods on the `embedded_hal` `OutputPin` " +"trait.\n" +" * HAL crates exist for many Cortex-M and RISC-V devices, including various " +"STM32, GD32, nRF, NXP,\n" +" MSP430, AVR and PIC microcontrollers." +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:45 +msgid "" +"```sh\n" +"cargo embed --bin hal\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:1 +#, fuzzy +msgid "# Board support crates" +msgstr "# Συντομεύσεις πληκτρολογίου" + +#: src/bare-metal/microcontrollers/board-support.md:3 +msgid "" +"Board support crates provide a further level of wrapping for a specific " +"board for convenience." +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use microbit::hal::prelude::*;\n" +"use microbit::Board;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let mut board = Board::take().unwrap();\n" +"\n" +" board.display_pins.col1.set_low().unwrap();\n" +" board.display_pins.row1.set_high().unwrap();\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:28 +msgid "" +" * In this case the board support crate is just providing more useful names, " +"and a bit of\n" +" initialisation.\n" +" * The crate may also include drivers for some on-board devices outside of " +"the microcontroller\n" +" itself.\n" +" * `microbit-v2` includes a simple driver for the LED matrix." +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:36 +msgid "" +"```sh\n" +"cargo embed --bin board_support\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:1 +msgid "# The type state pattern" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" let pin: P0_01 = gpio0.p0_01;\n" +"\n" +" // let gpio0_01_again = gpio0.p0_01; // Error, moved.\n" +" let pin_input: P0_01> = pin.into_floating_input();\n" +" if pin_input.is_high().unwrap() {\n" +" // ...\n" +" }\n" +" let mut pin_output: P0_01> =\n" +" pin_input.into_open_drain_output(OpenDrainConfig::" +"Disconnect0Standard1, Level::Low);\n" +" pin_output.set_high().unwrap();\n" +" // pin_input.is_high(); // Error, moved.\n" +"\n" +" let _pin2: P0_02> = gpio0\n" +" .p0_02\n" +" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, " +"Level::Low);\n" +" let _pin3: P0_03> = gpio0.p0_03." +"into_push_pull_output(Level::Low);\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:32 +msgid "" +" * Pins don't implement `Copy` or `Clone`, so only one instance of each can " +"exist. Once a pin is\n" +" moved out of the port struct nobody else can take it.\n" +" * Changing the configuration of a pin consumes the old pin instance, so you " +"can’t keep use the old\n" +" instance afterwards.\n" +" * The type of a value indicates the state that it is in: e.g. in this case, " +"the configuration state\n" +" of a GPIO pin. This encodes the state machine into the type system, and " +"ensures that you don't\n" +" try to use a pin in a certain way without properly configuring it first. " +"Illegal state\n" +" transitions are caught at compile time.\n" +" * You can call `is_high` on an input pin and `set_high` on an output pin, " +"but not vice-versa.\n" +" * Many HAL crates follow this pattern." +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:1 +msgid "# `embedded-hal`" +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:3 +msgid "" +"The [`embedded-hal`](https://crates.io/crates/embedded-hal) crate provides a " +"number of traits\n" +"covering common microcontroller peripherals." +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:6 +msgid "" +" * GPIO\n" +" * ADC\n" +" * I2C, SPI, UART, CAN\n" +" * RNG\n" +" * Timers\n" +" * Watchdogs" +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:13 +msgid "" +"Other crates then implement\n" +"[drivers](https://github.com/rust-embedded/awesome-embedded-rust#driver-" +"crates) in terms of these\n" +"traits, e.g. an accelerometer driver might need an I2C or SPI bus " +"implementation." +msgstr "" + +#: src/bare-metal/microcontrollers/embedded-hal.md:19 +msgid "" +" * There are implementations for many microcontrollers, as well as other " +"platforms such as Linux on\n" +"Raspberry Pi.\n" +" * There is work in progress on an `async` version of `embedded-hal`, but it " +"isn't stable yet." +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:1 +msgid "# probe-rs, `cargo-embed`" +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:3 +msgid "" +"[probe-rs](https://probe.rs/) is a handy toolset for embedded debugging, " +"like OpenOCD but better\n" +"integrated." +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:6 +msgid "" +"* SWD and JTAG via CMSIS-DAP, ST-" +"Link and J-Link probes\n" +"* GDB stub and Microsoft DAP " +"server\n" +"* Cargo integration" +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:10 +msgid "" +"`cargo-embed` is a cargo subcommand to build and flash binaries, log\n" +"RTT output and connect GDB. It's " +"configured by an\n" +"`Embed.toml` file in your project directory." +msgstr "" + +#: src/bare-metal/microcontrollers/probe-rs.md:16 +msgid "" +"* [CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) is " +"an Arm standard\n" +" protocol over USB for an in-circuit debugger to access the CoreSight Debug " +"Access Port of various\n" +" Arm Cortex processors. It's what the on-board debugger on the BBC micro:" +"bit uses.\n" +"* ST-Link is a range of in-circuit debuggers from ST Microelectronics, J-" +"Link is a range from\n" +" SEGGER.\n" +"* The Debug Access Port is usually either a 5-pin JTAG interface or 2-pin " +"Serial Wire Debug.\n" +"* probe-rs is a library which you can integrate into your own tools if you " +"want to.\n" +"* The [Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-" +"adapter-protocol/) lets\n" +" VSCode and other IDEs debug code running on any supported " +"microcontroller.\n" +"* cargo-embed is a binary built using the probe-rs library.\n" +"* RTT (Real Time Transfers) is a mechanism to transfer data between the " +"debug host and the target\n" +" through a number of ringbuffers." +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:1 +#, fuzzy +msgid "# Debugging" +msgstr "# Καταγραφή" + +#: src/bare-metal/microcontrollers/debugging.md:3 +msgid "Embed.toml:" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:5 +msgid "" +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:13 +msgid "In one terminal under `src/bare-metal/microcontrollers/examples/`:" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:15 +msgid "" +"```sh\n" +"cargo embed --bin board_support debug\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:19 +#, fuzzy +msgid "In another terminal in the same directory:" +msgstr "Σε άλλο τερματικό, ελέγξτε ότι η υπηρεσία εκτελείται:" + +#: src/bare-metal/microcontrollers/debugging.md:21 +msgid "" +"```sh\n" +"gdb-multiarch target/thumbv7em-none-eabihf/debug/board_support --eval-" +"command=\"target remote :1337\"\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:27 +msgid "In GDB, try running:" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:29 +msgid "" +"```gdb\n" +"b src/bin/board_support.rs:29\n" +"b src/bin/board_support.rs:30\n" +"b src/bin/board_support.rs:32\n" +"c\n" +"c\n" +"c\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/other-projects.md:1 +#: src/bare-metal/aps/other-projects.md:1 +msgid "# Other projects" +msgstr "" + +#: src/bare-metal/microcontrollers/other-projects.md:3 +msgid "" +" * [RTIC](https://rtic.rs/)\n" +" * \"Real-Time Interrupt-driven Concurrency\"\n" +" * Shared resource management, message passing, task scheduling, timer " +"queue\n" +" * [Embassy](https://embassy.dev/)\n" +" * `async` executors with priorities, timers, networking, USB\n" +" * [TockOS](https://www.tockos.org/documentation/getting-started)\n" +" * Security-focused RTOS with preemptive scheduling and Memory Protection " +"Unit support\n" +" * [Hubris](https://hubris.oxide.computer/)\n" +" * Microkernel RTOS from Oxide Computer Company with memory protection, " +"unprivileged drivers, IPC\n" +" * [Bindings for FreeRTOS](https://github.com/lobaro/FreeRTOS-rust)\n" +" * Some platforms have `std` implementations, e.g.\n" +" [esp-idf](https://esp-rs.github.io/book/overview/using-the-standard-" +"library.html)." +msgstr "" + +#: src/bare-metal/microcontrollers/other-projects.md:18 +msgid "" +" * RTIC can be considered either an RTOS or a concurrency framework.\n" +" * It doesn't include any HALs.\n" +" * It uses the Cortex-M NVIC (Nested Virtual Interrupt Controller) for " +"scheduling rather than a\n" +" proper kernel.\n" +" * Cortex-M only.\n" +" * Google uses TockOS on the Haven microcontroller for Titan security keys.\n" +" * FreeRTOS is mostly written in C, but there are Rust bindings for writing " +"applications." +msgstr "" + +#: src/exercises/bare-metal/morning.md:3 +msgid "" +"We will read the direction from an I2C compass, and log the readings to a " +"serial port." +msgstr "" + +#: src/exercises/bare-metal/compass.md:1 +#, fuzzy +msgid "# Compass" +msgstr "# Σύγκριση" + +#: src/exercises/bare-metal/compass.md:3 +msgid "" +"We will read the direction from an I2C compass, and log the readings to a " +"serial port. If you have\n" +"time, try displaying it on the LEDs somehow too, or use the buttons somehow." +msgstr "" + +#: src/exercises/bare-metal/compass.md:6 +msgid "Hints:" +msgstr "" + +#: src/exercises/bare-metal/compass.md:8 +msgid "" +"- Check the documentation for the [`lsm303agr`](https://docs.rs/lsm303agr/" +"latest/lsm303agr/) and\n" +" [`microbit-v2`](https://docs.rs/microbit-v2/latest/microbit/) crates, as " +"well as the\n" +" [micro:bit hardware](https://tech.microbit.org/hardware/).\n" +"- The LSM303AGR Inertial Measurement Unit is connected to the internal I2C " +"bus.\n" +"- TWI is another name for I2C, so the I2C master peripheral is called TWIM.\n" +"- The LSM303AGR driver needs something implementing the `embedded_hal::" +"blocking::i2c::WriteRead`\n" +" trait. The\n" +" [`microbit::hal::Twim`](https://docs.rs/microbit-v2/latest/microbit/hal/" +"struct.Twim.html) struct\n" +" implements this.\n" +"- You have a [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/" +"struct.Board.html)\n" +" struct with fields for the various pins and peripherals.\n" +"- You can also look at the\n" +" [nRF52833 datasheet](https://infocenter.nordicsemi.com/pdf/" +"nRF52833_PS_v1.5.pdf) if you want, but\n" +" it shouldn't be necessary for this exercise." +msgstr "" + +#: src/exercises/bare-metal/compass.md:23 src/exercises/bare-metal/rtc.md:7 +#, fuzzy +msgid "`src/main.rs`:" +msgstr "_hello_rust/src/main.rs_:" + +#: src/exercises/bare-metal/compass.md:25 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"use microbit::{hal::uarte::{Baudrate, Parity, Uarte}, Board};\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // TODO\n" +"\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // TODO\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:59 src/exercises/bare-metal/rtc.md:344 +msgid "`Cargo.toml` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/compass.md:61 +msgid "" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"compass\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"cortex-m-rt = \"0.7.3\"\n" +"embedded-hal = \"0.2.6\"\n" +"lsm303agr = \"0.2.2\"\n" +"microbit-v2 = \"0.13.0\"\n" +"panic-halt = \"0.2.0\"\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:78 +msgid "`Embed.toml` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/compass.md:80 +msgid "" +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"\n" +"[debug.reset]\n" +"halt_afterwards = true\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:91 src/exercises/bare-metal/rtc.md:922 +msgid "`.cargo/config.toml` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/compass.md:93 +msgid "" +"```toml\n" +"[build]\n" +"target = \"thumbv7em-none-eabihf\" # Cortex-M4F\n" +"\n" +"[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))']\n" +"rustflags = [\"-C\", \"link-arg=-Tlink.x\"]\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:101 +msgid "See the serial output on Linux with:" +msgstr "" + +#: src/exercises/bare-metal/compass.md:103 +msgid "" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/ttyACM0\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:107 +msgid "" +"Or on Mac OS something like (the device name may be slightly different):" +msgstr "" + +#: src/exercises/bare-metal/compass.md:109 +msgid "" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:113 +msgid "Use Ctrl+A Ctrl+Q to quit picocom." +msgstr "" + +#: src/bare-metal/aps.md:1 +msgid "# Application processors" +msgstr "" + +#: src/bare-metal/aps.md:3 +msgid "" +"So far we've talked about microcontrollers, such as the Arm Cortex-M series. " +"Now let's try writing\n" +"something for Cortex-A. For simplicity we'll just work with QEMU's aarch64\n" +"['virt'](https://qemu-project.gitlab.io/qemu/system/arm/virt.html) board." +msgstr "" + +#: src/bare-metal/aps.md:9 +msgid "" +"* Broadly speaking, microcontrollers don't have an MMU or multiple levels of " +"privilege (exception\n" +" levels on Arm CPUs, rings on x86), while application processors do.\n" +"* QEMU supports emulating various different machines or board models for " +"each architecture. The\n" +" 'virt' board doesn't correspond to any particular real hardware, but is " +"designed purely for\n" +" virtual machines." +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:1 +msgid "# Inline assembly" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:3 +msgid "" +"Sometimes we need to use assembly to do things that aren't possible with " +"Rust code. For example,\n" +"to make an HVC to tell the firmware " +"to power off the system:" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::arch::asm;\n" +"use core::panic::PanicInfo;\n" +"\n" +"mod exceptions;\n" +"\n" +"const PSCI_SYSTEM_OFF: u32 = 0x84000008;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) {\n" +" // Safe because this only uses the declared registers and doesn't do\n" +" // anything with memory.\n" +" unsafe {\n" +" asm!(\"hvc #0\",\n" +" inout(\"w0\") PSCI_SYSTEM_OFF => _,\n" +" inout(\"w1\") 0 => _,\n" +" inout(\"w2\") 0 => _,\n" +" inout(\"w3\") 0 => _,\n" +" inout(\"w4\") 0 => _,\n" +" inout(\"w5\") 0 => _,\n" +" inout(\"w6\") 0 => _,\n" +" inout(\"w7\") 0 => _,\n" +" options(nomem, nostack)\n" +" );\n" +" }\n" +"\n" +" loop {}\n" +"}\n" +"```" +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 functions.)" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:43 +msgid "" +"* PSCI is the Arm Power State Coordination Interface, a standard set of " +"functions to manage system\n" +" and CPU power states, among other things. It is implemented by EL3 " +"firmware and hypervisors on\n" +" many systems.\n" +"* The `0 => _` syntax means initialise the register to 0 before running the " +"inline assembly code,\n" +" and ignore its contents afterwards. We need to use `inout` rather than " +"`in` because the call could\n" +" potentially clobber the contents of the registers.\n" +"* Run the example in QEMU with `make qemu_psci` under `src/bare-metal/aps/" +"examples`." +msgstr "" + +#: src/bare-metal/aps/mmio.md:1 +msgid "# Volatile memory access for MMIO" +msgstr "" + +#: src/bare-metal/aps/mmio.md:3 +msgid "" +" * Use `pointer::read_volatile` and `pointer::write_volatile`.\n" +" * Never hold a reference.\n" +" * `addr_of!` lets you get fields of structs without creating an " +"intermediate reference." +msgstr "" + +#: src/bare-metal/aps/mmio.md:9 +msgid "" +" * Volatile access: read or write operations may have side-effects, so " +"prevent the compiler or\n" +" hardware from reordering, duplicating or eliding them.\n" +" * Usually if you write and then read, e.g. via a mutable reference, the " +"compiler may assume that\n" +" the value read is the same as the value just written, and not bother " +"actually reading memory.\n" +" * Some existing crates for volatile access to hardware do hold references, " +"but this is unsound.\n" +" Whenever a reference exist, the compiler may choose to dereference it.\n" +" * Use the `addr_of!` macro to get struct field pointers from a pointer to " +"the struct." +msgstr "" + +#: src/bare-metal/aps/uart.md:1 +msgid "# Let's write a UART driver" +msgstr "" + +#: src/bare-metal/aps/uart.md:3 +msgid "" +"The QEMU 'virt' machine has a [PL011][1] UART, so let's write a driver for " +"that." +msgstr "" + +#: src/bare-metal/aps/uart.md:5 +msgid "" +"```rust,editable\n" +"const FLAG_REGISTER_OFFSET: usize = 0x18;\n" +"const FR_BUSY: u8 = 1 << 3;\n" +"const FR_TXFF: u8 = 1 << 5;\n" +"\n" +"/// Minimal driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" base_address: *mut u8,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at " +"the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of " +"a\n" +" /// PL011 device, which must be mapped into the address space of the " +"process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u8) -> Self {\n" +" Self { base_address }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register() & FR_TXFF != 0 {}\n" +"\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" self.base_address.write_volatile(byte);\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register() & FR_BUSY != 0 {}\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> u8 {\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { self.base_address.add(FLAG_REGISTER_OFFSET)." +"read_volatile() }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/uart/traits.md:1 +#, fuzzy +msgid "# More traits" +msgstr "# Χαρακτηριστικά" + +#: src/bare-metal/aps/uart/traits.md:3 +msgid "" +"We derived the `Debug` trait. It would be useful to implement a few more " +"traits too." +msgstr "" + +#: src/bare-metal/aps/uart/traits.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use core::fmt::{self, Write};\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/uart/traits.md:24 +msgid "" +"* Implementing `Write` lets us use the `write!` and `writeln!` macros with " +"our `Uart` type.\n" +"* Run the example in QEMU with `make qemu_minimal` under `src/bare-metal/aps/" +"examples`." +msgstr "" + +#: src/bare-metal/aps/better-uart.md:1 +msgid "# A better UART driver" +msgstr "" + +#: src/bare-metal/aps/better-uart.md:3 +msgid "" +"The PL011 actually has [a bunch more registers][1], and adding offsets to " +"construct pointers to access\n" +"them is error-prone and hard to read. Plus, some of them are bit fields " +"which would be nice to\n" +"access in a structured way." +msgstr "" + +#: src/bare-metal/aps/better-uart.md:7 +msgid "" +"| Offset | Register name | Width |\n" +"| ------ | ------------- | ----- |\n" +"| 0x00 | DR | 12 |\n" +"| 0x04 | RSR | 4 |\n" +"| 0x18 | FR | 9 |\n" +"| 0x20 | ILPR | 8 |\n" +"| 0x24 | IBRD | 16 |\n" +"| 0x28 | FBRD | 6 |\n" +"| 0x2c | LCR_H | 8 |\n" +"| 0x30 | CR | 16 |\n" +"| 0x34 | IFLS | 6 |\n" +"| 0x38 | IMSC | 11 |\n" +"| 0x3c | RIS | 11 |\n" +"| 0x40 | MIS | 11 |\n" +"| 0x44 | ICR | 11 |\n" +"| 0x48 | DMACR | 3 |" +msgstr "" + +#: src/bare-metal/aps/better-uart.md:26 +msgid "- There are also some ID registers which have been omitted for brevity." +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:1 +msgid "# Bitflags" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:3 +msgid "" +"The [`bitflags`](https://crates.io/crates/bitflags) crate is useful for " +"working with bitflags." +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:37 +msgid "" +"* The `bitflags!` macro creates a newtype something like `Flags(u16)`, along " +"with a bunch of method\n" +" implementations to get and set flags." +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:1 +msgid "# Multiple registers" +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:3 +msgid "" +"We can use a struct to represent the memory layout of the UART's registers." +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:41 +msgid "" +"* [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-" +"representation) tells\n" +" the compiler to lay the struct fields out in order, following the same " +"rules as C. This is\n" +" necessary for our struct to have a predictable layout, as default Rust " +"representation allows the\n" +" compiler to (among other things) reorder fields however it sees fit." +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:1 +msgid "# Driver" +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:3 +msgid "Now let's use the new `Registers` struct in our driver." +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at " +"the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of " +"a\n" +" /// PL011 device, which must be mapped into the address space of the " +"process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been " +"received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr)." +"read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:64 +msgid "" +"* Note the use of `addr_of!` / `addr_of_mut!` to get pointers to individual " +"fields without creating\n" +" an intermediate reference, which would be unsound." +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:1 +#: src/bare-metal/aps/logging/using.md:1 +#, fuzzy +msgid "# Using it" +msgstr "# Χρήση Bindgen" + +#: src/bare-metal/aps/better-uart/using.md:3 +msgid "" +"Let's write a small program using our driver to write to the serial console, " +"and echo incoming\n" +"bytes." +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::{fmt::Write, panic::PanicInfo};\n" +"use log::error;\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"pub const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +"\n" +" writeln!(uart, \"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3)." +"unwrap();\n" +"\n" +" loop {\n" +" if let Some(b) = uart.read_byte() {\n" +" uart.write_byte(b);\n" +" match b {\n" +" b'\\r' => {\n" +" uart.write_byte(b'\\n');\n" +" }\n" +" b'q' => break,\n" +" _ => {}\n" +" }\n" +" }\n" +" }\n" +"\n" +" writeln!(uart, \"Bye!\").unwrap();\n" +" system_off().unwrap();\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:49 +msgid "" +"* Run the example in QEMU with `make qemu` under `src/bare-metal/aps/" +"examples`." +msgstr "" + +#: src/bare-metal/aps/logging.md:3 +msgid "" +"It would be nice to be able to use the logging macros from the [`log`][1] " +"crate. We can do this by\n" +"implementing the `Log` trait." +msgstr "" + +#: src/bare-metal/aps/logging.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" +" }\n" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), " +"SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/logging.md:50 +msgid "" +"* The unwrap in `log` is safe because we initialise `LOGGER` before calling " +"`set_logger`." +msgstr "" + +#: src/bare-metal/aps/logging/using.md:3 +msgid "We need to initialise the logger before we use it." +msgstr "" + +#: src/bare-metal/aps/logging/using.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, LevelFilter};\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"pub const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +"\n" +" assert_eq!(x1, 42);\n" +"\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{}\", info);\n" +" system_off().unwrap();\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/logging/using.md:45 +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`." +msgstr "" + +#: src/bare-metal/aps/other-projects.md:3 +msgid "" +" * [oreboot](https://github.com/oreboot/oreboot)\n" +" * \"coreboot without the C\"\n" +" * Supports x86, aarch64 and RISC-V.\n" +" * Relies on LinuxBoot rather than having many drivers itself.\n" +" * [Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-" +"raspberrypi-OS-tutorials)\n" +" * Initialisation, UART driver, simple bootloader, JTAG, exception levels, " +"exception handling, page tables\n" +" * Not all very well written, so beware.\n" +" * [`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)\n" +" * Static analysis to determine maximum stack usage." +msgstr "" + +#: src/bare-metal/useful-crates.md:1 +msgid "# Useful crates" +msgstr "" + +#: src/bare-metal/useful-crates.md:3 +msgid "" +"We'll go over a few crates which solve some common problems in bare-metal " +"programming." +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:1 +msgid "# `zerocopy`" +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:3 +msgid "" +"The [`zerocopy`][1] crate (from Fuchsia) provides traits and macros for " +"safely converting between\n" +"byte sequences and other types." +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use zerocopy::AsBytes;\n" +"\n" +"#[repr(u32)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"enum RequestType {\n" +" #[default]\n" +" In = 0,\n" +" Out = 1,\n" +" Flush = 4,\n" +"}\n" +"\n" +"#[repr(C)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"struct VirtioBlockRequest {\n" +" request_type: RequestType,\n" +" reserved: u32,\n" +" sector: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let request = VirtioBlockRequest {\n" +" request_type: RequestType::Flush,\n" +" sector: 42,\n" +" ..Default::default()\n" +" };\n" +"\n" +" assert_eq!(\n" +" request.as_bytes(),\n" +" &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0]\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:40 +msgid "" +"This is not suitable for MMIO (as it doesn't use volatile reads and writes), " +"but can be useful for\n" +"working with structures shared with hardware e.g. by DMA, or sent over some " +"external interface." +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:45 +msgid "" +"* `FromBytes` can be implemented for types for which any byte pattern is " +"valid, and so can safely be\n" +" converted from an untrusted sequence of bytes.\n" +"* Attempting to derive `FromBytes` for these types would fail, because " +"`RequestType` doesn't use all\n" +" possible u32 values as discriminants, so not all byte patterns are valid.\n" +"* `zerocopy::byteorder` has types for byte-order aware numeric primitives." +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:1 +msgid "# `aarch64-paging`" +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:3 +msgid "" +"The [`aarch64-paging`][1] crate lets you create page tables according to the " +"AArch64 Virtual Memory\n" +"System Architecture." +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use aarch64_paging::{\n" +" idmap::IdMap,\n" +" paging::{Attributes, MemoryRegion},\n" +"};\n" +"\n" +"const ASID: usize = 1;\n" +"const ROOT_LEVEL: usize = 1;\n" +"\n" +"// Create a new page table with identity mapping.\n" +"let mut idmap = IdMap::new(ASID, ROOT_LEVEL);\n" +"// Map a 2 MiB region of memory as read-only.\n" +"idmap.map_range(\n" +" &MemoryRegion::new(0x80200000, 0x80400000),\n" +" Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,\n" +").unwrap();\n" +"// Set `TTBR0_EL1` to activate the page table.\n" +"idmap.activate();\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:28 +msgid "" +"* For now it only supports EL1, but support for other exception levels " +"should be straightforward to\n" +" add.\n" +"* This is used in Android for the [Protected VM Firmware][2]." +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:1 +msgid "# `buddy_system_allocator`" +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:3 +msgid "" +"[`buddy_system_allocator`][1] is a third-party crate implementing a basic " +"buddy system allocator.\n" +"It can be used both for [`LockedHeap`][2] implementing [`GlobalAlloc`][3] so " +"you can use the\n" +"standard `alloc` crate (as we saw [before][4]), or for allocating other " +"address space. For example,\n" +"we might want to allocate MMIO space for PCI BARs:" +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use buddy_system_allocator::FrameAllocator;\n" +"use core::alloc::Layout;\n" +"\n" +"fn main() {\n" +" let mut allocator = FrameAllocator::<32>::new();\n" +" allocator.add_frame(0x200_0000, 0x400_0000);\n" +"\n" +" let layout = Layout::from_size_align(0x100, 0x100).unwrap();\n" +" let bar = allocator\n" +" .alloc_aligned(layout)\n" +" .expect(\"Failed to allocate 0x100 byte MMIO region\");\n" +" println!(\"Allocated 0x100 byte MMIO region at {:#x}\", bar);\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:26 +msgid "* PCI BARs always have alignment equal to their size." +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:1 +msgid "# `tinyvec`" +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:3 +msgid "" +"Sometimes you want something which can be resized like a `Vec`, but without " +"heap allocation.\n" +"[`tinyvec`][1] provides this: a vector backed by an array or slice, which " +"could be statically\n" +"allocated or on the stack, which keeps track of how many elements are used " +"and panics if you try to\n" +"use more than are allocated." +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use tinyvec::{array_vec, ArrayVec};\n" +"\n" +"fn main() {\n" +" let mut numbers: ArrayVec<[u32; 5]> = array_vec!(42, 66);\n" +" println!(\"{numbers:?}\");\n" +" numbers.push(7);\n" +" println!(\"{numbers:?}\");\n" +" numbers.remove(1);\n" +" println!(\"{numbers:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:23 +msgid "" +"* `tinyvec` requires that the element type implement `Default` for " +"initialisation." +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:1 +#, fuzzy +msgid "# `spin`" +msgstr "## «στατικό»." + +#: src/bare-metal/useful-crates/spin.md:3 +msgid "" +"`std::sync::Mutex` and the other synchronisation primitives from `std::sync` " +"are not available in\n" +"`core` or `alloc`. How can we manage synchronisation or interior mutability, " +"such as for sharing\n" +"state between different CPUs?" +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:7 +msgid "" +"The [`spin`][1] crate provides spinlock-based equivalents of many of these " +"primitives." +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:9 +msgid "" +"```rust,editable,compile_fail\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static counter: SpinMutex = SpinMutex::new(0);\n" +"\n" +"fn main() {\n" +" println!(\"count: {}\", counter.lock());\n" +" *counter.lock() += 2;\n" +" println!(\"count: {}\", counter.lock());\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:23 +msgid "" +"* Be careful to avoid deadlock if you take locks in interrupt handlers.\n" +"* `spin` also has a ticket lock mutex implementation; equivalents of " +"`RwLock`, `Barrier` and `Once`\n" +" from `std::sync`; and `Lazy` for lazy initialisation.\n" +"* The [`once_cell`][2] crate also has some useful types for late " +"initialisation with a slightly\n" +" different approach to `spin::once::Once`." +msgstr "" + +#: 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 build\n" +"your Rust code, then a `cc_binary` with a linker script to produce the " +"binary itself, and then a\n" +"`raw_binary` to convert the ELF to a raw binary ready to be run." +msgstr "" + +#: src/bare-metal/android.md:7 +msgid "" +"```soong\n" +"rust_ffi_static {\n" +" name: \"libvmbase_example\",\n" +" defaults: [\"vmbase_ffi_defaults\"],\n" +" crate_name: \"vmbase_example\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libvmbase\",\n" +" ],\n" +"}\n" +"\n" +"cc_binary {\n" +" name: \"vmbase_example\",\n" +" defaults: [\"vmbase_elf_defaults\"],\n" +" srcs: [\n" +" \"idmap.S\",\n" +" ],\n" +" static_libs: [\n" +" \"libvmbase_example\",\n" +" ],\n" +" linker_scripts: [\n" +" \"image.ld\",\n" +" \":vmbase_sections\",\n" +" ],\n" +"}\n" +"\n" +"raw_binary {\n" +" name: \"vmbase_example_bin\",\n" +" stem: \"vmbase_example.bin\",\n" +" src: \":vmbase_example\",\n" +" enabled: false,\n" +" target: {\n" +" android_arm64: {\n" +" enabled: true,\n" +" },\n" +" },\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/android/vmbase.md:1 +msgid "# vmbase" +msgstr "" + +#: src/bare-metal/android/vmbase.md:3 +msgid "" +"For VMs running under crosvm on aarch64, the [vmbase][1] library provides a " +"linker script and useful\n" +"defaults for the build rules, along with an entry point, UART console " +"logging and more." +msgstr "" + +#: src/bare-metal/android/vmbase.md:6 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use vmbase::{main, println};\n" +"\n" +"main!(main);\n" +"\n" +"pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {\n" +" println!(\"Hello world\");\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/android/vmbase.md:21 +msgid "" +"* The `main!` macro marks your main function, to be called from the `vmbase` " +"entry point.\n" +"* The `vmbase` entry point handles console initialisation, and issues a " +"PSCI_SYSTEM_OFF to shutdown\n" +" the VM if your main function returns." +msgstr "" + +#: src/exercises/bare-metal/afternoon.md:3 +msgid "We will write a driver for the PL031 real-time clock device." +msgstr "" + +#: src/exercises/bare-metal/rtc.md:1 +msgid "# RTC driver" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:3 +msgid "" +"The QEMU aarch64 virt machine has a [PL031][1] real-time clock at 0x9010000. " +"For this exercise, you\n" +"should write a driver for it and use it to print the current time to the " +"serial console. You can use\n" +"the [`chrono`][2] crate for date/time formatting." +msgstr "" + +#: src/exercises/bare-metal/rtc.md:8 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, LevelFilter};\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"pub const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +"\n" +" // TODO: Initialise RTC and print value.\n" +"\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{}\", info);\n" +" system_off().unwrap();\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:46 +msgid "`src/exceptions.rs` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:47 +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" +"use log::error;\n" +"use psci::system_off;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_exception_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:114 +msgid "`src/logger.rs` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:115 +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: main\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" +" }\n" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), " +"SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:172 +msgid "`src/pl011.rs` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:173 +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" +"use core::{\n" +" fmt::{self, Write},\n" +" ptr::{addr_of, addr_of_mut},\n" +"};\n" +"\n" +"// ANCHOR: Flags\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"// ANCHOR_END: Flags\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART Receive Status Register / Error Clear Register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct ReceiveStatus: u16 {\n" +" /// Framing error.\n" +" const FE = 1 << 0;\n" +" /// Parity error.\n" +" const PE = 1 << 1;\n" +" /// Break error.\n" +" const BE = 1 << 2;\n" +" /// Overrun error.\n" +" const OE = 1 << 3;\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Registers\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"// ANCHOR_END: Registers\n" +"\n" +"// ANCHOR: Uart\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at " +"the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of " +"a\n" +" /// PL011 device, which must be mapped into the address space of the " +"process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been " +"received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr)." +"read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" +"}\n" +"// ANCHOR_END: Uart\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:345 +msgid "" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"rtc\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"bitflags = \"2.0.0\"\n" +"chrono = { version = \"0.4.24\", default-features = false }\n" +"log = \"0.4.17\"\n" +"psci = \"0.1.1\"\n" +"spin = \"0.9.4\"\n" +"\n" +"[build-dependencies]\n" +"cc = \"1.0.73\"\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:365 +msgid "`build.rs` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:366 +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" +"use cc::Build;\n" +"use std::env;\n" +"\n" +"fn main() {\n" +" #[cfg(target_os = \"linux\")]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-linux-gnu\");\n" +" #[cfg(not(target_os = \"linux\"))]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-none-elf\");\n" +"\n" +" Build::new()\n" +" .file(\"entry.S\")\n" +" .file(\"exceptions.S\")\n" +" .file(\"idmap.S\")\n" +" .compile(\"empty\")\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:398 +msgid "`entry.S` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:399 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".macro adr_l, reg:req, sym:req\n" +"\tadrp \\reg, \\sym\n" +"\tadd \\reg, \\reg, :lo12:\\sym\n" +".endm\n" +"\n" +".macro mov_i, reg:req, imm:req\n" +"\tmovz \\reg, :abs_g3:\\imm\n" +"\tmovk \\reg, :abs_g2_nc:\\imm\n" +"\tmovk \\reg, :abs_g1_nc:\\imm\n" +"\tmovk \\reg, :abs_g0_nc:\\imm\n" +".endm\n" +"\n" +".set .L_MAIR_DEV_nGnRE,\t0x04\n" +".set .L_MAIR_MEM_WBWA,\t0xff\n" +".set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8)\n" +"\n" +"/* 4 KiB granule size for TTBR0_EL1. */\n" +".set .L_TCR_TG0_4KB, 0x0 << 14\n" +"/* 4 KiB granule size for TTBR1_EL1. */\n" +".set .L_TCR_TG1_4KB, 0x2 << 30\n" +"/* Disable translation table walk for TTBR1_EL1, generating a translation " +"fault instead. */\n" +".set .L_TCR_EPD1, 0x1 << 23\n" +"/* Translation table walks for TTBR0_EL1 are inner sharable. */\n" +".set .L_TCR_SH_INNER, 0x3 << 12\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are outer write-back read-allocate " +"write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_OWB, 0x1 << 10\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are inner write-back read-allocate " +"write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_IWB, 0x1 << 8\n" +"/* Size offset for TTBR0_EL1 is 2**39 bytes (512 GiB). */\n" +".set .L_TCR_T0SZ_512, 64 - 39\n" +".set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_TG1_4KB | .L_TCR_EPD1 | ." +"L_TCR_RGN_OWB\n" +".set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | ." +"L_TCR_T0SZ_512\n" +"\n" +"/* Stage 1 instruction access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_I, 0x1 << 12\n" +"/* SP alignment fault if SP is not aligned to a 16 byte boundary. */\n" +".set .L_SCTLR_ELx_SA, 0x1 << 3\n" +"/* Stage 1 data access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_C, 0x1 << 2\n" +"/* EL0 and EL1 stage 1 MMU enabled. */\n" +".set .L_SCTLR_ELx_M, 0x1 << 0\n" +"/* Privileged Access Never is unchanged on taking an exception to EL1. */\n" +".set .L_SCTLR_EL1_SPAN, 0x1 << 23\n" +"/* SETEND instruction disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_SED, 0x1 << 8\n" +"/* Various IT instructions are disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_ITD, 0x1 << 7\n" +".set .L_SCTLR_EL1_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << " +"28) | (0x1 << 29)\n" +".set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | ." +"L_SCTLR_EL1_ITD | .L_SCTLR_EL1_SED\n" +".set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL1_SPAN | ." +"L_SCTLR_EL1_RES1\n" +"\n" +"/**\n" +" * This is a generic entry point for an image. It carries out the operations " +"required to prepare the\n" +" * loaded image to be run. Specifically, it zeroes the bss section using " +"registers x25 and above,\n" +" * prepares the stack, enables floating point, and sets up the exception " +"vector. It preserves x0-x3\n" +" * for the Rust entry point, as these may contain boot parameters.\n" +" */\n" +".section .init.entry, \"ax\"\n" +".global entry\n" +"entry:\n" +"\t/* Load and apply the memory management configuration, ready to enable MMU " +"and caches. */\n" +"\tadrp x30, idmap\n" +"\tmsr ttbr0_el1, x30\n" +"\n" +"\tmov_i x30, .Lmairval\n" +"\tmsr mair_el1, x30\n" +"\n" +"\tmov_i x30, .Ltcrval\n" +"\t/* Copy the supported PA range into TCR_EL1.IPS. */\n" +"\tmrs x29, id_aa64mmfr0_el1\n" +"\tbfi x30, x29, #32, #4\n" +"\n" +"\tmsr tcr_el1, x30\n" +"\n" +"\tmov_i x30, .Lsctlrval\n" +"\n" +"\t/*\n" +"\t * Ensure everything before this point has completed, then invalidate any " +"potentially stale\n" +"\t * local TLB entries before they start being used.\n" +"\t */\n" +"\tisb\n" +"\ttlbi vmalle1\n" +"\tic iallu\n" +"\tdsb nsh\n" +"\tisb\n" +"\n" +"\t/*\n" +"\t * Configure sctlr_el1 to enable MMU and cache and don't proceed until " +"this has completed.\n" +"\t */\n" +"\tmsr sctlr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Disable trapping floating point access in EL1. */\n" +"\tmrs x30, cpacr_el1\n" +"\torr x30, x30, #(0x3 << 20)\n" +"\tmsr cpacr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Zero out the bss section. */\n" +"\tadr_l x29, bss_begin\n" +"\tadr_l x30, bss_end\n" +"0:\tcmp x29, x30\n" +"\tb.hs 1f\n" +"\tstp xzr, xzr, [x29], #16\n" +"\tb 0b\n" +"\n" +"1:\t/* Prepare the stack. */\n" +"\tadr_l x30, boot_stack_end\n" +"\tmov sp, x30\n" +"\n" +"\t/* Set up exception vector. */\n" +"\tadr x30, vector_table_el1\n" +"\tmsr vbar_el1, x30\n" +"\n" +"\t/* Call into Rust code. */\n" +"\tbl main\n" +"\n" +"\t/* Loop forever waiting for interrupts. */\n" +"2:\twfi\n" +"\tb 2b\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:544 +msgid "`exceptions.S` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:545 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +"/**\n" +" * Saves the volatile registers onto the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers with 18 " +"instructions\n" +" * left.\n" +" *\n" +" * On return, x0 and x1 are initialised to elr_el2 and spsr_el2 " +"respectively,\n" +" * which can be used as the first and second arguments of a subsequent " +"call.\n" +" */\n" +".macro save_volatile_to_stack\n" +"\t/* Reserve stack space and save registers x0-x18, x29 & x30. */\n" +"\tstp x0, x1, [sp, #-(8 * 24)]!\n" +"\tstp x2, x3, [sp, #8 * 2]\n" +"\tstp x4, x5, [sp, #8 * 4]\n" +"\tstp x6, x7, [sp, #8 * 6]\n" +"\tstp x8, x9, [sp, #8 * 8]\n" +"\tstp x10, x11, [sp, #8 * 10]\n" +"\tstp x12, x13, [sp, #8 * 12]\n" +"\tstp x14, x15, [sp, #8 * 14]\n" +"\tstp x16, x17, [sp, #8 * 16]\n" +"\tstr x18, [sp, #8 * 18]\n" +"\tstp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/*\n" +"\t * Save elr_el1 & spsr_el1. This such that we can take nested exception\n" +"\t * and still be able to unwind.\n" +"\t */\n" +"\tmrs x0, elr_el1\n" +"\tmrs x1, spsr_el1\n" +"\tstp x0, x1, [sp, #8 * 22]\n" +".endm\n" +"\n" +"/**\n" +" * Restores the volatile registers from the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers while still leaving " +"18\n" +" * instructions left; if paired with save_volatile_to_stack, there are 4\n" +" * instructions to spare.\n" +" */\n" +".macro restore_volatile_from_stack\n" +"\t/* Restore registers x2-x18, x29 & x30. */\n" +"\tldp x2, x3, [sp, #8 * 2]\n" +"\tldp x4, x5, [sp, #8 * 4]\n" +"\tldp x6, x7, [sp, #8 * 6]\n" +"\tldp x8, x9, [sp, #8 * 8]\n" +"\tldp x10, x11, [sp, #8 * 10]\n" +"\tldp x12, x13, [sp, #8 * 12]\n" +"\tldp x14, x15, [sp, #8 * 14]\n" +"\tldp x16, x17, [sp, #8 * 16]\n" +"\tldr x18, [sp, #8 * 18]\n" +"\tldp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/* Restore registers elr_el1 & spsr_el1, using x0 & x1 as scratch. */\n" +"\tldp x0, x1, [sp, #8 * 22]\n" +"\tmsr elr_el1, x0\n" +"\tmsr spsr_el1, x1\n" +"\n" +"\t/* Restore x0 & x1, and release stack space. */\n" +"\tldp x0, x1, [sp], #8 * 24\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while " +"using\n" +" * SP0. It behaves similarly to the SPx case by first switching to SPx, " +"doing\n" +" * the work, then switching back to SP0 before returning.\n" +" *\n" +" * Switching to SPx and calling the Rust handler takes 16 instructions. To\n" +" * restore and return we need an additional 16 instructions, so we can " +"implement\n" +" * the whole handler within the allotted 32 instructions.\n" +" */\n" +".macro current_exception_sp0 handler:req\n" +"\tmsr spsel, #1\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\tmsr spsel, #0\n" +"\teret\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while " +"using\n" +" * SPx. It saves volatile registers, calls the Rust handler, restores " +"volatile\n" +" * registers, then returns.\n" +" *\n" +" * This also works for exceptions taken from EL0, if we don't care about\n" +" * non-volatile registers.\n" +" *\n" +" * Saving state and jumping to the Rust handler takes 15 instructions, and\n" +" * restoring and returning also takes 15 instructions, so we can fit the " +"whole\n" +" * handler in 30 instructions, under the limit of 32.\n" +" */\n" +".macro current_exception_spx handler:req\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\teret\n" +".endm\n" +"\n" +".section .text.vector_table_el1, \"ax\"\n" +".global vector_table_el1\n" +".balign 0x800\n" +"vector_table_el1:\n" +"sync_cur_sp0:\n" +"\tcurrent_exception_sp0 sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_sp0:\n" +"\tcurrent_exception_sp0 irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_sp0:\n" +"\tcurrent_exception_sp0 fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_sp0:\n" +"\tcurrent_exception_sp0 serr_current\n" +"\n" +".balign 0x80\n" +"sync_cur_spx:\n" +"\tcurrent_exception_spx sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_spx:\n" +"\tcurrent_exception_spx irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_spx:\n" +"\tcurrent_exception_spx fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_spx:\n" +"\tcurrent_exception_spx serr_current\n" +"\n" +".balign 0x80\n" +"sync_lower_64:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_64:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_64:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_64:\n" +"\tcurrent_exception_spx serr_lower\n" +"\n" +".balign 0x80\n" +"sync_lower_32:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_32:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_32:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_32:\n" +"\tcurrent_exception_spx serr_lower\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:726 +msgid "`idmap.S` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:727 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".set .L_TT_TYPE_BLOCK, 0x1\n" +".set .L_TT_TYPE_PAGE, 0x3\n" +".set .L_TT_TYPE_TABLE, 0x3\n" +"\n" +"/* Access flag. */\n" +".set .L_TT_AF, 0x1 << 10\n" +"/* Not global. */\n" +".set .L_TT_NG, 0x1 << 11\n" +".set .L_TT_XN, 0x3 << 53\n" +"\n" +".set .L_TT_MT_DEV, 0x0 << 2\t\t\t// MAIR #0 (DEV_nGnRE)\n" +".set .L_TT_MT_MEM, (0x1 << 2) | (0x3 << 8)\t// MAIR #1 (MEM_WBWA), inner " +"shareable\n" +"\n" +".set .L_BLOCK_DEV, .L_TT_TYPE_BLOCK | .L_TT_MT_DEV | .L_TT_AF | .L_TT_XN\n" +".set .L_BLOCK_MEM, .L_TT_TYPE_BLOCK | .L_TT_MT_MEM | .L_TT_AF | .L_TT_NG\n" +"\n" +".section \".rodata.idmap\", \"a\", %progbits\n" +".global idmap\n" +".align 12\n" +"idmap:\n" +"\t/* level 1 */\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x0\t\t // 1 GiB of device mappings\n" +"\t.quad\t\t.L_BLOCK_MEM | 0x40000000\t// 1 GiB of DRAM\n" +"\t.fill\t\t254, 8, 0x0\t\t\t// 254 GiB of unmapped VA space\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x4000000000 // 1 GiB of device mappings\n" +"\t.fill\t\t255, 8, 0x0\t\t\t// 255 GiB of remaining VA space\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:772 +msgid "`image.ld` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:773 +msgid "" +"```ld\n" +"/*\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" +" * https://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" +"\n" +"/*\n" +" * Code will start running at this symbol which is placed at the start of " +"the\n" +" * image.\n" +" */\n" +"ENTRY(entry)\n" +"\n" +"MEMORY\n" +"{\n" +"\timage : ORIGIN = 0x40080000, LENGTH = 2M\n" +"}\n" +"\n" +"SECTIONS\n" +"{\n" +"\t/*\n" +"\t * Collect together the code.\n" +"\t */\n" +"\t.init : ALIGN(4096) {\n" +"\t\ttext_begin = .;\n" +"\t\t*(.init.entry)\n" +"\t\t*(.init.*)\n" +"\t} >image\n" +"\t.text : {\n" +"\t\t*(.text.*)\n" +"\t} >image\n" +"\ttext_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together read-only data.\n" +"\t */\n" +"\t.rodata : ALIGN(4096) {\n" +"\t\trodata_begin = .;\n" +"\t\t*(.rodata.*)\n" +"\t} >image\n" +"\t.got : {\n" +"\t\t*(.got)\n" +"\t} >image\n" +"\trodata_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together the read-write data including .bss at the end which\n" +"\t * will be zero'd by the entry code.\n" +"\t */\n" +"\t.data : ALIGN(4096) {\n" +"\t\tdata_begin = .;\n" +"\t\t*(.data.*)\n" +"\t\t/*\n" +"\t\t * The entry point code assumes that .data is a multiple of 32\n" +"\t\t * bytes long.\n" +"\t\t */\n" +"\t\t. = ALIGN(32);\n" +"\t\tdata_end = .;\n" +"\t} >image\n" +"\n" +"\t/* Everything beyond this point will not be included in the binary. */\n" +"\tbin_end = .;\n" +"\n" +"\t/* The entry point code assumes that .bss is 16-byte aligned. */\n" +"\t.bss : ALIGN(16) {\n" +"\t\tbss_begin = .;\n" +"\t\t*(.bss.*)\n" +"\t\t*(COMMON)\n" +"\t\t. = ALIGN(16);\n" +"\t\tbss_end = .;\n" +"\t} >image\n" +"\n" +"\t.stack (NOLOAD) : ALIGN(4096) {\n" +"\t\tboot_stack_begin = .;\n" +"\t\t. += 40 * 4096;\n" +"\t\t. = ALIGN(4096);\n" +"\t\tboot_stack_end = .;\n" +"\t} >image\n" +"\n" +"\t. = ALIGN(4K);\n" +"\tPROVIDE(dma_region = .);\n" +"\n" +"\t/*\n" +"\t * Remove unused sections from the image.\n" +"\t */\n" +"\t/DISCARD/ : {\n" +"\t\t/* The image loads itself so doesn't need these sections. */\n" +"\t\t*(.gnu.hash)\n" +"\t\t*(.hash)\n" +"\t\t*(.interp)\n" +"\t\t*(.eh_frame_hdr)\n" +"\t\t*(.eh_frame)\n" +"\t\t*(.note.gnu.build-id)\n" +"\t}\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:880 +msgid "`Makefile` (you shouldn't need to change this):" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:881 +msgid "" +"```makefile\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" +"UNAME := $(shell uname -s)\n" +"ifeq ($(UNAME),Linux)\n" +"\tTARGET = aarch64-linux-gnu\n" +"else\n" +"\tTARGET = aarch64-none-elf\n" +"endif\n" +"OBJCOPY = $(TARGET)-objcopy\n" +"\n" +".PHONY: build qemu_minimal qemu qemu_logger\n" +"\n" +"all: rtc.bin\n" +"\n" +"build:\n" +"\tcargo build\n" +"\n" +"rtc.bin: build\n" +"\t$(OBJCOPY) -O binary target/aarch64-unknown-none/debug/rtc $@\n" +"\n" +"qemu: rtc.bin\n" +"\tqemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none " +"-kernel $< -s\n" +"\n" +"clean:\n" +"\tcargo clean\n" +"\trm -f *.bin\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:923 +msgid "" +"```toml\n" +"[build]\n" +"target = \"aarch64-unknown-none\"\n" +"rustflags = [\"-C\", \"link-arg=-Timage.ld\"]\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:929 +msgid "Run the code in QEMU with `make qemu`." +msgstr "" + +#: src/exercises/solutions.md:1 +#, fuzzy +msgid "# Solutions" +msgstr "# Λύσεις" + +#: src/exercises/solutions.md:3 +#, fuzzy +msgid "You will find solutions to the exercises on the following pages." +msgstr "Θα βρείτε λύσεις στις ασκήσεις στις επόμενες σελίδες." + +#: src/exercises/solutions.md:5 +#, fuzzy +msgid "" +"Feel free to ask questions about the solutions [on\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Let us " +"know\n" +"if you have a different or better solution than what is presented here." +msgstr "" +"Μη διστάσετε να κάνετε ερωτήσεις σχετικά με τις λύσεις [on\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Ενημέρωσέ " +"μας\n" +"εάν έχετε διαφορετική ή καλύτερη λύση από αυτή που παρουσιάζεται εδώ." + +#: src/exercises/solutions.md:10 +#, fuzzy +msgid "" +"> **Note:** Please ignore the `// ANCHOR: label` and `// ANCHOR_END: label`\n" +"> comments you see in the solutions. They are there to make it possible to\n" +"> re-use parts of the solutions as the exercises." +msgstr "" +"> **Σημείωση:** Αγνοήστε τα \"// ANCHOR: label\" και \"// ANCHOR_END: " +"label\"\n" +"> σχόλια που βλέπετε στις λύσεις. Είναι εκεί για να το κάνουν δυνατό\n" +"> επαναχρησιμοποιήστε μέρη των λύσεων ως ασκήσεις." + +#: src/exercises/day-1/solutions-morning.md:1 +#, fuzzy +msgid "# Day 1 Morning Exercises" +msgstr "# Πρωινές ασκήσεις 1ης ημέρας" + +#: src/exercises/day-1/solutions-morning.md:3 +#, fuzzy +msgid "## Arrays and `for` Loops" +msgstr "## Πίνακες και βρόχοι «for»." + +#: src/exercises/day-1/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](for-loops.md))" +msgstr "([επιστροφή στην άσκηση](for-loops.md))" + +#: src/exercises/day-1/solutions-morning.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: transpose\n" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" // ANCHOR_END: transpose\n" +" let mut result = [[0; 3]; 3];\n" +" for i in 0..3 {\n" +" for j in 0..3 {\n" +" result[j][i] = matrix[i][j];\n" +" }\n" +" }\n" +" return result;\n" +"}\n" +"\n" +"// ANCHOR: pretty_print\n" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" // ANCHOR_END: pretty_print\n" +" for row in matrix {\n" +" println!(\"{row:?}\");\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: tests\n" +"#[test]\n" +"fn test_transpose() {\n" +" let matrix = [\n" +" [101, 102, 103], //\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +" let transposed = transpose(matrix);\n" +" assert_eq!(\n" +" transposed,\n" +" [\n" +" [101, 201, 301], //\n" +" [102, 202, 302],\n" +" [103, 203, 303],\n" +" ]\n" +" );\n" +"}\n" +"// ANCHOR_END: tests\n" +"\n" +"// ANCHOR: main\n" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:78 +#, fuzzy +msgid "### Bonus question" +msgstr "## Ερώτηση μπόνους" + +#: src/exercises/day-1/solutions-morning.md:80 +#, fuzzy +msgid "" +"It requires more advanced concepts. It might seem that we could use a slice-" +"of-slices (`&[&[i32]]`) as the input type to transpose and thus make our " +"function handle any size of matrix. However, this quickly breaks down: the " +"return type cannot be `&[&[i32]]` since it needs to own the data you return." +msgstr "" +"Ειλικρινά δεν λειτουργεί τόσο καλά. Μπορεί να φαίνεται ότι θα μπορούσαμε να " +"χρησιμοποιήσουμε ένα slice-of-slices (`&[&[i32]]`) ως τύπο εισόδου για να " +"μεταφέρουμε και έτσι να κάνουμε τη συνάρτησή μας να χειρίζεται οποιοδήποτε " +"μέγεθος πίνακα. Ωστόσο, αυτό αναλύεται γρήγορα: ο τύπος επιστροφής δεν " +"μπορεί να είναι \"&[&[i32]]\", καθώς πρέπει να είναι κάτοχος των δεδομένων " +"που επιστρέφετε." + +#: src/exercises/day-1/solutions-morning.md:82 +#, fuzzy +msgid "" +"You can attempt to use something like `Vec>`, but this doesn't work " +"out-of-the-box either: it's hard to convert from `Vec>` to " +"`&[&[i32]]` so now you cannot easily use `pretty_print` either." +msgstr "" +"Μπορείτε να επιχειρήσετε να χρησιμοποιήσετε κάτι σαν `Vec>`, αλλά " +"ούτε αυτό λειτουργεί πολύ καλά: είναι δύσκολο να μετατρέψετε από " +"`Vec>` σε `&[&[i32]] Έτσι τώρα δεν μπορείτε να χρησιμοποιήσετε " +"εύκολα ούτε το \"pretty_print\"." + +#: src/exercises/day-1/solutions-morning.md:84 +msgid "" +"Once we get to traits and generics, we'll be able to use the [`std::convert::" +"AsRef`][1] trait to abstract over anything that can be referenced as a slice." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:86 +msgid "" +"```rust\n" +"use std::convert::AsRef;\n" +"use std::fmt::Debug;\n" +"\n" +"fn pretty_print(matrix: Matrix)\n" +"where\n" +" T: Debug,\n" +" // A line references a slice of items\n" +" Line: AsRef<[T]>,\n" +" // A matrix references a slice of lines\n" +" Matrix: AsRef<[Line]>\n" +"{\n" +" for row in matrix.as_ref() {\n" +" println!(\"{:?}\", row.as_ref());\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" // &[&[i32]]\n" +" pretty_print(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" +" // [[&str; 2]; 2]\n" +" pretty_print([[\"a\", \"b\"], [\"c\", \"d\"]]);\n" +" // Vec>\n" +" pretty_print(vec![vec![1, 2], vec![3, 4]]);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:113 +#, fuzzy +msgid "" +"In addition, the type itself would not enforce that the child slices are of " +"the same length, so such variable could contain an invalid matrix." +msgstr "" +"Επιπλέον, ο ίδιος ο τύπος δεν θα επιβάλλει ότι οι θυγατρικές φέτες έχουν το " +"ίδιο μήκος, επομένως μια τέτοια μεταβλητή θα μπορούσε να περιέχει έναν μη " +"έγκυρο πίνακα." + +#: src/exercises/day-1/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 1 Afternoon Exercises" +msgstr "# 1η ημέρα Απογευματινές Ασκήσεις" + +#: src/exercises/day-1/solutions-afternoon.md:3 +#, fuzzy +msgid "## Designing a Library" +msgstr "## Σχεδιασμός Βιβλιοθήκης" + +#: src/exercises/day-1/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](book-library.md))" +msgstr "([επιστροφή στην άσκηση](book-library.md))" + +#: src/exercises/day-1/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: setup\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// 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" +"impl Library {\n" +" fn new() -> Library {\n" +" // ANCHOR_END: Library_new\n" +" Library { books: Vec::new() }\n" +" }\n" +"\n" +" // ANCHOR: Library_len\n" +" //fn len(self) -> usize {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_len\n" +" fn len(&self) -> usize {\n" +" self.books.len()\n" +" }\n" +"\n" +" // ANCHOR: Library_is_empty\n" +" //fn is_empty(self) -> bool {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_is_empty\n" +" fn is_empty(&self) -> bool {\n" +" self.books.is_empty()\n" +" }\n" +"\n" +" // ANCHOR: Library_add_book\n" +" //fn add_book(self, book: Book) {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_add_book\n" +" fn add_book(&mut self, book: Book) {\n" +" self.books.push(book)\n" +" }\n" +"\n" +" // ANCHOR: Library_print_books\n" +" //fn print_books(self) {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_print_books\n" +" fn print_books(&self) {\n" +" for book in &self.books {\n" +" println!(\"{}\", book);\n" +" }\n" +" }\n" +"\n" +" // ANCHOR: Library_oldest_book\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // unimplemented!()\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" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();\n" +"\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" +" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " +"1865));\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" +" //}\n" +" //\n" +" //println!(\"Our library has {} books\", library.len());\n" +" for book in library.books {\n" +" println!(\"{book}\");\n" +" }\n" +"}\n" +"// ANCHOR_END: main\n" +"\n" +"#[test]\n" +"fn test_library_len() {\n" +" let mut library = Library::new();\n" +" assert_eq!(library.len(), 0);\n" +" assert!(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" +" assert_eq!(library.len(), 2);\n" +" assert!(!library.is_empty());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_is_empty() {\n" +" let mut library = Library::new();\n" +" assert!(library.is_empty());\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert!(!library.is_empty());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_print_books() {\n" +" let mut library = Library::new();\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " +"1865));\n" +" // We could try and capture stdout, but let us just call the\n" +" // method to start with.\n" +" library.print_books();\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_oldest_book() {\n" +" let mut library = Library::new();\n" +" assert!(library.oldest_book().is_none());\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Lord of the Rings\")\n" +" );\n" +"\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " +"1865));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Alice's Adventures in Wonderland\")\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:1 +#, fuzzy +msgid "# Day 2 Morning Exercises" +msgstr "# 2η ημέρα Πρωινές ασκήσεις" + +#: src/exercises/day-2/solutions-morning.md:3 +#, fuzzy +msgid "## Points and Polygons" +msgstr "## Σημεία και πολύγωνα" + +#: src/exercises/day-2/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](points-polygons.md))" +msgstr "([επιστροφή στην άσκηση](points-polygons.md))" + +#: src/exercises/day-2/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" +"#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" +"// ANCHOR: Point\n" +"pub struct Point {\n" +" // ANCHOR_END: Point\n" +" x: i32,\n" +" y: i32,\n" +"}\n" +"\n" +"// ANCHOR: Point-impl\n" +"impl Point {\n" +" // ANCHOR_END: Point-impl\n" +" pub fn new(x: i32, y: i32) -> Point {\n" +" Point { x, y }\n" +" }\n" +"\n" +" pub fn magnitude(self) -> f64 {\n" +" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +" }\n" +"\n" +" pub fn dist(self, other: Point) -> f64 {\n" +" (self - other).magnitude()\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x + other.x,\n" +" y: self.y + other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Sub for Point {\n" +" type Output = Self;\n" +"\n" +" fn sub(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x - other.x,\n" +" y: self.y - other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Polygon\n" +"pub struct Polygon {\n" +" // ANCHOR_END: Polygon\n" +" points: Vec,\n" +"}\n" +"\n" +"// ANCHOR: Polygon-impl\n" +"impl Polygon {\n" +" // ANCHOR_END: Polygon-impl\n" +" pub fn new() -> Polygon {\n" +" Polygon { points: Vec::new() }\n" +" }\n" +"\n" +" pub fn add_point(&mut self, point: Point) {\n" +" self.points.push(point);\n" +" }\n" +"\n" +" pub fn left_most_point(&self) -> Option {\n" +" self.points.iter().min_by_key(|p| p.x).copied()\n" +" }\n" +"\n" +" pub fn iter(&self) -> impl Iterator {\n" +" self.points.iter()\n" +" }\n" +"\n" +" pub fn length(&self) -> f64 {\n" +" if self.points.is_empty() {\n" +" return 0.0;\n" +" }\n" +"\n" +" let mut result = 0.0;\n" +" let mut last_point = self.points[0];\n" +" for point in &self.points[1..] {\n" +" result += last_point.dist(*point);\n" +" last_point = *point;\n" +" }\n" +" result += last_point.dist(self.points[0]);\n" +" result\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Circle\n" +"pub struct Circle {\n" +" // ANCHOR_END: Circle\n" +" center: Point,\n" +" radius: i32,\n" +"}\n" +"\n" +"// ANCHOR: Circle-impl\n" +"impl Circle {\n" +" // ANCHOR_END: Circle-impl\n" +" pub fn new(center: Point, radius: i32) -> Circle {\n" +" Circle { center, radius }\n" +" }\n" +"\n" +" pub fn circumference(&self) -> f64 {\n" +" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +" }\n" +"\n" +" pub fn dist(&self, other: &Self) -> f64 {\n" +" self.center.dist(other.center)\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Shape\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"// ANCHOR_END: Shape\n" +"\n" +"impl From for Shape {\n" +" fn from(poly: Polygon) -> Self {\n" +" Shape::Polygon(poly)\n" +" }\n" +"}\n" +"\n" +"impl From for Shape {\n" +" fn from(circle: Circle) -> Self {\n" +" Shape::Circle(circle)\n" +" }\n" +"}\n" +"\n" +"impl Shape {\n" +" pub fn perimeter(&self) -> f64 {\n" +" match self {\n" +" Shape::Polygon(poly) => poly.length(),\n" +" Shape::Circle(circle) => circle.circumference(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 2 Afternoon Exercises" +msgstr "# 2η μέρα Απογευματινές Ασκήσεις" + +#: src/exercises/day-2/solutions-afternoon.md:3 +#, fuzzy +msgid "## Luhn Algorithm" +msgstr "## Αλγόριθμος Luhn" + +#: src/exercises/day-2/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](luhn.md))" +msgstr "([επιστροφή στην άσκηση](luhn.md))" + +#: src/exercises/day-2/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: luhn\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" // ANCHOR_END: luhn\n" +" let mut digits_seen = 0;\n" +" let mut sum = 0;\n" +" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ')." +"enumerate() {\n" +" match ch.to_digit(10) {\n" +" Some(d) => {\n" +" sum += if i % 2 == 1 {\n" +" let dd = d * 2;\n" +" dd / 10 + dd % 10\n" +" } else {\n" +" d\n" +" };\n" +" digits_seen += 1;\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +"\n" +" if digits_seen < 2 {\n" +" return false;\n" +" }\n" +"\n" +" sum % 10 == 0\n" +"}\n" +"\n" +"fn main() {\n" +" let cc_number = \"1234 5678 1234 5670\";\n" +" println!(\n" +" \"Is {} a valid credit card number? {}\",\n" +" cc_number,\n" +" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" +" );\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:98 +#, fuzzy +msgid "## Strings and Iterators" +msgstr "## Συμβολοσειρές και επαναλήπτες" + +#: src/exercises/day-2/solutions-afternoon.md:100 +#, fuzzy +msgid "([back to exercise](strings-iterators.md))" +msgstr "([επιστροφή στην άσκηση](strings-iterators.md))" + +#: src/exercises/day-2/solutions-afternoon.md:102 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: prefix_matches\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" // ANCHOR_END: prefix_matches\n" +" let prefixes = prefix.split('/');\n" +" let request_paths = request_path\n" +" .split('/')\n" +" .map(|p| Some(p))\n" +" .chain(std::iter::once(None));\n" +"\n" +" for (prefix, request_path) in prefixes.zip(request_paths) {\n" +" match request_path {\n" +" Some(request_path) => {\n" +" if (prefix != \"*\") && (prefix != request_path) {\n" +" return false;\n" +" }\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +" true\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/" +"abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/" +"books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/" +"publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/" +"publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:1 +#, fuzzy +msgid "# Day 3 Morning Exercise" +msgstr "# 3η ημέρα Πρωινή άσκηση" + +#: src/exercises/day-3/solutions-morning.md:3 +#, fuzzy +msgid "## A Simple GUI Library" +msgstr "## Μια απλή βιβλιοθήκη GUI" + +#: src/exercises/day-3/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](simple-gui.md))" +msgstr "([επιστροφή στην άσκηση](simple-gui.md))" + +#: src/exercises/day-3/solutions-morning.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: setup\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"}\n" +"\n" +"// ANCHOR_END: setup\n" +"\n" +"// ANCHOR: Window-width\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" // ANCHOR_END: Window-width\n" +" std::cmp::max(\n" +" self.title.chars().count(),\n" +" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +" )\n" +" }\n" +"\n" +" // ANCHOR: Window-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Window-draw_into\n" +" let mut inner = String::new();\n" +" for widget in &self.widgets {\n" +" widget.draw_into(&mut inner);\n" +" }\n" +"\n" +" let window_width = self.width();\n" +"\n" +" // TODO: after learning about error handling, you can change\n" +" // draw_into to return Result<(), std::fmt::Error>. Then use\n" +" // the ?-operator here instead of .unwrap().\n" +" writeln!(buffer, \"+-{:- usize {\n" +" // ANCHOR_END: Button-width\n" +" self.label.width() + 8 // add a bit of padding\n" +" }\n" +"\n" +" // ANCHOR: Button-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Button-draw_into\n" +" let width = self.width();\n" +" let mut label = String::new();\n" +" self.label.draw_into(&mut label);\n" +"\n" +" writeln!(buffer, \"+{:- usize {\n" +" // ANCHOR_END: Label-width\n" +" self.label\n" +" .lines()\n" +" .map(|line| line.chars().count())\n" +" .max()\n" +" .unwrap_or(0)\n" +" }\n" +"\n" +" // ANCHOR: Label-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Label-draw_into\n" +" writeln!(buffer, \"{}\", &self.label).unwrap();\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo." +"\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" +"}\n" +"// ANCHOR_END: main\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 3 Afternoon Exercises" +msgstr "# 3η ημέρα Απογευματινές Ασκήσεις" + +#: src/exercises/day-3/solutions-afternoon.md:3 +#, fuzzy +msgid "## Safe FFI Wrapper" +msgstr "## Ασφαλές περιτύλιγμα FFI" + +#: src/exercises/day-3/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](safe-ffi-wrapper.md))" +msgstr "([επιστροφή στην άσκηση](safe-ffi-wrapper.md))" + +#: src/exercises/day-3/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: ffi\n" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::" +"PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-" +"gnu.\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}\n" +"// ANCHOR_END: ffi\n" +"\n" +"// ANCHOR: DirectoryIterator\n" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" // ANCHOR_END: DirectoryIterator\n" +" let path = CString::new(path).map_err(|err| format!(\"Invalid path: " +"{err}\"))?;\n" +" // SAFETY: path.as_ptr() cannot be NULL.\n" +" let dir = unsafe { ffi::opendir(path.as_ptr()) };\n" +" if dir.is_null() {\n" +" Err(format!(\"Could not open {:?}\", path))\n" +" } else {\n" +" Ok(DirectoryIterator { path, dir })\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Iterator\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" // ANCHOR_END: Iterator\n" +" // SAFETY: self.dir is never NULL.\n" +" let dirent = unsafe { ffi::readdir(self.dir) };\n" +" if dirent.is_null() {\n" +" // We have reached the end of the directory.\n" +" return None;\n" +" }\n" +" // SAFETY: dirent is not NULL and dirent.d_name is NUL\n" +" // terminated.\n" +" let d_name = unsafe { CStr::from_ptr((*dirent).d_name.as_ptr()) };\n" +" let os_str = OsStr::from_bytes(d_name.to_bytes());\n" +" Some(os_str.to_owned())\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Drop\n" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" // ANCHOR_END: Drop\n" +" if !self.dir.is_null() {\n" +" // SAFETY: self.dir is not NULL.\n" +" if unsafe { ffi::closedir(self.dir) } != 0 {\n" +" panic!(\"Could not close {:?}\", self.path);\n" +" }\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"// ANCHOR_END: main\n" +"```" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:1 +#, fuzzy +msgid "# Day 4 Morning Exercise" +msgstr "# 4η ημέρα Πρωινή άσκηση" + +#: src/exercises/day-4/solutions-morning.md:3 +#, fuzzy +msgid "## Dining Philosophers" +msgstr "## Dining Philosophers" + +#: src/exercises/day-4/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](dining-philosophers.md))" +msgstr "([επιστροφή στην άσκηση](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" +"\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/bare-metal/solutions-morning.md:1 +#, fuzzy +msgid "# Bare Metal Rust Morning Exercise" +msgstr "# 3η ημέρα Πρωινή άσκηση" + +#: src/exercises/bare-metal/solutions-morning.md:3 +#, fuzzy +msgid "## Compass" +msgstr "# Σύγκριση" + +#: src/exercises/bare-metal/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](compass.md))" +msgstr "([επιστροφή στην άσκηση](for-loops.md))" + +#: src/exercises/bare-metal/solutions-morning.md:7 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"// ANCHOR_END: top\n" +"use core::cmp::{max, min};\n" +"use lsm303agr::{AccelOutputDataRate, Lsm303agr, MagOutputDataRate};\n" +"use microbit::{\n" +" display::blocking::Display,\n" +" hal::{\n" +" prelude::*,\n" +" twim::Twim,\n" +" uarte::{Baudrate, Parity, Uarte},\n" +" Timer,\n" +" },\n" +" pac::twim0::frequency::FREQUENCY_A,\n" +" Board,\n" +"};\n" +"\n" +"const COMPASS_SCALE: i32 = 30000;\n" +"const ACCELEROMETER_SCALE: i32 = 700;\n" +"\n" +"// ANCHOR: main\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // ANCHOR_END: main\n" +" writeln!(serial, \"Setting up IMU...\").unwrap();\n" +" let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::" +"K100);\n" +" let mut imu = Lsm303agr::new_with_i2c(i2c);\n" +" imu.init().unwrap();\n" +" imu.set_mag_odr(MagOutputDataRate::Hz50).unwrap();\n" +" imu.set_accel_odr(AccelOutputDataRate::Hz50).unwrap();\n" +" let mut imu = imu.into_mag_continuous().ok().unwrap();\n" +"\n" +" // Set up display and timer.\n" +" let mut timer = Timer::new(board.TIMER0);\n" +" let mut display = Display::new(board.display_pins);\n" +"\n" +" let mut mode = Mode::Compass;\n" +" let mut button_pressed = false;\n" +"\n" +" // ANCHOR: loop\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // ANCHOR_END: loop\n" +" while !(imu.mag_status().unwrap().xyz_new_data\n" +" && imu.accel_status().unwrap().xyz_new_data)\n" +" {}\n" +" let compass_reading = imu.mag_data().unwrap();\n" +" let accelerometer_reading = imu.accel_data().unwrap();\n" +" writeln!(\n" +" serial,\n" +" \"{},{},{}\\t{},{},{}\",\n" +" compass_reading.x,\n" +" compass_reading.y,\n" +" compass_reading.z,\n" +" accelerometer_reading.x,\n" +" accelerometer_reading.y,\n" +" accelerometer_reading.z,\n" +" )\n" +" .unwrap();\n" +"\n" +" let mut image = [[0; 5]; 5];\n" +" let (x, y) = match mode {\n" +" Mode::Compass => (\n" +" scale(-compass_reading.x, -COMPASS_SCALE, COMPASS_SCALE, 0, " +"4) as usize,\n" +" scale(compass_reading.y, -COMPASS_SCALE, COMPASS_SCALE, 0, " +"4) as usize,\n" +" ),\n" +" Mode::Accelerometer => (\n" +" scale(\n" +" accelerometer_reading.x,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" scale(\n" +" -accelerometer_reading.y,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" ),\n" +" };\n" +" image[y][x] = 255;\n" +" display.show(&mut timer, image, 100);\n" +"\n" +" // If button A is pressed, switch to the next mode and briefly blink " +"all LEDs on.\n" +" if board.buttons.button_a.is_low().unwrap() {\n" +" if !button_pressed {\n" +" mode = mode.next();\n" +" display.show(&mut timer, [[255; 5]; 5], 200);\n" +" }\n" +" button_pressed = true;\n" +" } else {\n" +" button_pressed = false;\n" +" }\n" +" }\n" +"}\n" +"\n" +"#[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +"enum Mode {\n" +" Compass,\n" +" Accelerometer,\n" +"}\n" +"\n" +"impl Mode {\n" +" fn next(self) -> Self {\n" +" match self {\n" +" Self::Compass => Self::Accelerometer,\n" +" Self::Accelerometer => Self::Compass,\n" +" }\n" +" }\n" +"}\n" +"\n" +"fn scale(value: i32, min_in: i32, max_in: i32, min_out: i32, max_out: i32) -" +"> i32 {\n" +" let range_in = max_in - min_in;\n" +" let range_out = max_out - min_out;\n" +" cap(\n" +" min_out + range_out * (value - min_in) / range_in,\n" +" min_out,\n" +" max_out,\n" +" )\n" +"}\n" +"\n" +"fn cap(value: i32, min_value: i32, max_value: i32) -> i32 {\n" +" max(min_value, min(value, max_value))\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:1 +msgid "# Bare Metal Rust Afternoon" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:3 +msgid "## RTC driver" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](rtc.md))" +msgstr "([επιστροφή στην άσκηση](luhn.md))" + +#: src/exercises/bare-metal/solutions-afternoon.md:7 +msgid "`main.rs`:" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:9 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"// ANCHOR_END: top\n" +"mod pl031;\n" +"\n" +"use crate::pl031::Rtc;\n" +"use chrono::{TimeZone, Utc};\n" +"// ANCHOR: imports\n" +"use crate::pl011::Uart;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, LevelFilter};\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"pub const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"// ANCHOR_END: imports\n" +"\n" +"/// Base address of the PL031 RTC.\n" +"pub const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;\n" +"\n" +"// ANCHOR: main\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +" // ANCHOR_END: main\n" +"\n" +" // Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 " +"device,\n" +" // and nothing else accesses that address range.\n" +" let rtc = unsafe { Rtc::new(PL031_BASE_ADDRESS) };\n" +" let time = Utc.timestamp_opt(rtc.read().into(), 0).unwrap();\n" +" info!(\"RTC: {}\", time);\n" +"\n" +" // ANCHOR: main_end\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{}\", info);\n" +" system_off().unwrap();\n" +" loop {}\n" +"}\n" +"// ANCHOR_END: main_end\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:79 +msgid "`pl031.rs`:" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:81 +msgid "" +"```rust\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"use core::ptr::addr_of;\n" +"\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" /// Data register\n" +" dr: u32,\n" +" /// Match register\n" +" mr: u32,\n" +" /// Load register\n" +" lr: u32,\n" +" /// Control register\n" +" cr: u8,\n" +" _reserved0: [u8; 3],\n" +" /// Interrupt Mask Set or Clear register\n" +" imsc: u8,\n" +" _reserved1: [u8; 3],\n" +" /// Raw Interrupt Status\n" +" ris: u8,\n" +" _reserved2: [u8; 3],\n" +" /// Masked Interrupt Status\n" +" mis: u8,\n" +" _reserved3: [u8; 3],\n" +" /// Interrupt Clear Register\n" +" icr: u8,\n" +" _reserved4: [u8; 3],\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"pub struct Rtc {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Rtc {\n" +" /// Constructs a new instance of the RTC driver for a PL031 device at " +"the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of " +"a\n" +" /// PL031 device, which must be mapped into the address space of the " +"process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Reads the current RTC value.\n" +" pub fn read(&self) -> u32 {\n" +" unsafe { addr_of!((*self.registers).dr).read_volatile() }\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Rtc {}\n" +"```" +msgstr "" + +#~ msgid "" +#~ "1. Make yourself familiar with the course material. We've included " +#~ "speaker notes\n" +#~ " on some of the pages to help highlight the key points (please help us " +#~ "by\n" +#~ " contributing more speaker notes!). You should make sure to open the " +#~ "speaker\n" +#~ " notes in a popup (click the link with a little arrow next to " +#~ "\"Speaker\n" +#~ " Notes\"). This way you have a clean screen to present to the class." +#~ msgstr "" +#~ "1. Εξοικειωθείτε με το υλικό του μαθήματος. Έχουμε συμπεριλάβει " +#~ "σημειώσεις ομιλητή\n" +#~ " σε ορισμένες από τις σελίδες για να τονίσουμε τα βασικά σημεία " +#~ "(παρακαλούμε βοηθήστε μας να\n" +#~ " συνεισφέροντας περισσότερες σημειώσεις ομιλητή!). Θα πρέπει να " +#~ "φροντίσετε να ανοίξετε τις σημειώσεις\n" +#~ " σε ένα αναδυόμενο παράθυρο (κάντε κλικ στο σύνδεσμο με ένα μικρό βέλος " +#~ "δίπλα στο \"Speaker\n" +#~ " Notes\"). Με αυτόν τον τρόπο θα έχετε μια καθαρή οθόνη για να " +#~ "παρουσιάσετε στην τάξη." + +#~ msgid "" +#~ "2. 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" +#~ " they find it helpful to have a gap in the course since it helps them " +#~ "process\n" +#~ " all the information we give them." +#~ msgstr "" +#~ "2. Αποφασίστε τις ημερομηνίες. Επειδή το μάθημα είναι μεγάλο, σας " +#~ "συνιστούμε να το απλώσετε\n" +#~ " τις τέσσερις ημέρες σε δύο εβδομάδες. Οι συμμετέχοντες στο μάθημα το " +#~ "θεωρούν γενικά\n" +#~ " χρήσιμο να έχουν ένα κενό στο μεταξύ των παραδόσεων, καθώς τους βοηθά " +#~ "να επεξεργαστούν\n" +#~ " όλες τις πληροφορίες που τους δίνουμε." + +#~ msgid "" +#~ "3. 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" +#~ " asking questions --- it's also small enough that one instructor will " +#~ "have\n" +#~ " time to answer the questions." +#~ msgstr "" +#~ "3. Βρείτε ένα δωμάτιο αρκετά μεγάλο για τους φυσικούς σας συμμετέχοντες. " +#~ "Συνιστούμε τάξεις μεγέθους 15-20 άτομα. Είναι αρκετά μικρό ώστε οι " +#~ "συμμετέχοντες να νιώθουν άνετα\n" +#~ " κάνοντας ερωτήσεις --- αλλά και ο εκπαιδευτής\n" +#~ " να έχει χρόνο να απαντήσει στις ερωτήσεις." + +#~ msgid "" +#~ "4. On the day of your course, show up to the room a little early to set " +#~ "things\n" +#~ " up. We recommend presenting directly using `mdbook serve` running on " +#~ "your\n" +#~ " laptop (see the [installation instructions][5]). This ensures optimal " +#~ "performance with no lag as you change pages.\n" +#~ " Using your laptop will also allow you to fix typos as you or the " +#~ "course\n" +#~ " participants spot them." +#~ msgstr "" +#~ "4. Την ημέρα του μαθήματος, πηγαίνετε στην αίθουσα λίγο νωρίς για να " +#~ "προετοιμαστείτε.\n" +#~ " Συνιστούμε την απευθείας παρουσίαση χρησιμοποιώντας την υπηρεσία " +#~ "\"mdbook serve\" που θα τρέξετε στον δικό σας\n" +#~ " λάπτοπ(βλέπε τις [οδηγίες εγκατάστασης][5]. Αυτό εξασφαλίζει βέλτιστη " +#~ "απόδοση χωρίς καθυστέρηση μεταξύ των σελίδων.\n" +#~ " Η χρήση του φορητού υπολογιστή σας θα σας επιτρέψει επίσης να " +#~ "διορθώσετε τυπογραφικά λάθη όταν εσείς ή οι συμμετέχοντες\n" +#~ " τα εντοπίζετε." + +#~ msgid "" +#~ "5. Let people solve the exercises by themselves or in small groups. 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." +#~ msgstr "" +#~ "5. Αφήστε τους συμμετέχοντες να λύσουν τις ασκήσεις μόνοι τους ή σε " +#~ "μικρές ομάδες. Να ρωτάτε περιοδικά τους μαθητές αν έχουν κολλήσει ή αν " +#~ "υπάρχει κάτι με το οποίο μπορείτε να βοηθήσετε. Οταν\n" +#~ " βλέπετε ότι πολλοί άνθρωποι έχουν το ίδιο πρόβλημα, αναφέρετέ το στην " +#~ "τάξη\n" +#~ " βρείτε μια λύση, π.χ., δείχνοντας στους ανθρώπους πώς να ψάξουν για " +#~ "σχετικές\n" +#~ " πληροφορίες στην standard βιβλιοθήκη." + +#~ msgid "" +#~ "> **Exercise for Day 4:** Do you interface with some C/C++ code in your " +#~ "project\n" +#~ "> which we could attempt to move to Rust? The fewer dependencies the " +#~ "better.\n" +#~ "> Parsing code would be ideal." +#~ msgstr "" +#~ "> **Άσκηση για την 4η Ημέρα:** Διασυνδέεστε με κώδικα C/C++ στο πρότζεκτ " +#~ "σας\n" +#~ "> που θα μπορούσαμε να προσπαθήσουμε να μεταφέρουμε στο Rust; Όσο " +#~ "λιγότερες εξαρτήσεις τόσο το καλύτερο.\n" +#~ "> Η ανάλυση του κώδικα θα ήταν ιδανικό παράδειγμα." + +#, fuzzy +#~ msgid "" +#~ "[1]: https://rust-analyzer.github.io/\n" +#~ "[2]: https://code.visualstudio.com/\n" +#~ "[3]: https://rustup.rs/\n" +#~ "[4]: https://www.jetbrains.com/clion/\n" +#~ "[5]: https://www.jetbrains.com/rust/\n" +#~ "[6]: https://github.com/rust-lang/rustfmt" +#~ msgstr "" +#~ "[1]: https://rust-analyzer.github.io/\n" +#~ "[2]: https://code.visualstudio.com/\n" +#~ "[3]: https://rustup.rs/\n" +#~ "[4]: https://www.jetbrains.com/clion/\n" +#~ "[5]: https://www.jetbrains.com/rust/" + +#, fuzzy +#~ msgid "" +#~ "* `rustc`: the Rust compiler which turns `.rs` files into binaries and " +#~ "other\n" +#~ " intermediate formats." +#~ msgstr "" +#~ "* `rustc`: ο μεταγλωττιστής Rust που μετατρέπει τα αρχεία `.rs` σε " +#~ "δυαδικά και άλλα\n" +#~ " ενδιάμεσες μορφές[^rustc]." + +#, fuzzy +#~ msgid "" +#~ "* `cargo`: the Rust dependency manager and build tool. Cargo knows how " +#~ "to\n" +#~ " download dependencies hosted on and it will pass " +#~ "them to\n" +#~ " `rustc` when building your project. Cargo also comes with a built-in " +#~ "test\n" +#~ " runner which is used to execute unit tests." +#~ msgstr "" +#~ "* «cargo»: ο διαχειριστής εξάρτησης Rust και το εργαλείο κατασκευής. Το " +#~ "φορτίο ξέρει πώς να\n" +#~ " κατεβάστε τις εξαρτήσεις που φιλοξενούνται στο και " +#~ "θα τις μεταβιβάσει\n" +#~ " «rustc» κατά την κατασκευή του έργου σας. Το Cargo συνοδεύεται επίσης " +#~ "από ενσωματωμένη δοκιμή\n" +#~ " runner που χρησιμοποιείται για την εκτέλεση δοκιμών μονάδας[^cargo]." + +#, fuzzy +#~ msgid "" +#~ "* Rust has a rapid release schedule with a new release coming out\n" +#~ " every six weeks. New releases maintain backwards compatibility with\n" +#~ " old releases --- plus they enable new functionality." +#~ msgstr "" +#~ "* Το Rust έχει ένα γρήγορο πρόγραμμα κυκλοφορίας με μια νέα κυκλοφορία να " +#~ "κυκλοφορεί\n" +#~ " κάθε έξι εβδομάδες. Οι νέες εκδόσεις διατηρούν συμβατότητα προς τα πίσω " +#~ "με\n" +#~ " παλιές εκδόσεις --- συν ότι επιτρέπουν νέες λειτουργίες." + +#, fuzzy +#~ msgid "" +#~ "* There are three release channels: \"stable\", \"beta\", and \"nightly\"." +#~ msgstr "" +#~ "* Υπάρχουν τρία κανάλια κυκλοφορίας: \"σταθερό\", \"beta\" και " +#~ "\"νυχτερινό\"." + +#, fuzzy +#~ msgid "" +#~ "* New features are being tested on \"nightly\", \"beta\" is what becomes\n" +#~ " \"stable\" every six weeks." +#~ msgstr "" +#~ "* Νέες δυνατότητες δοκιμάζονται σε \"νυχτερινό\", \"beta\" είναι αυτό που " +#~ "γίνεται\n" +#~ " «σταθερό» κάθε έξι εβδομάδες." + +#, fuzzy +#~ msgid "" +#~ "* Rust also has [editions]: the current edition is Rust 2021. Previous\n" +#~ " editions were Rust 2015 and Rust 2018." +#~ msgstr "" +#~ "* Το Rust έχει επίσης [εκδόσεις]: η τρέχουσα έκδοση είναι Rust 2021. " +#~ "Προηγούμενο\n" +#~ " οι εκδόσεις ήταν Rust 2015 και Rust 2018." + +#, fuzzy +#~ msgid "" +#~ " * The editions are allowed to make backwards incompatible changes to\n" +#~ " the language." +#~ msgstr "" +#~ " * Οι εκδόσεις επιτρέπεται να κάνουν προς τα πίσω μη συμβατές αλλαγές\n" +#~ " η γλώσσα." + +#, fuzzy +#~ msgid "" +#~ " * To prevent breaking code, editions are opt-in: you select the\n" +#~ " edition for your crate via the `Cargo.toml` file." +#~ msgstr "" +#~ " * Για να αποφευχθεί η παραβίαση του κώδικα, οι εκδόσεις επιλέγονται: " +#~ "επιλέγετε το\n" +#~ " έκδοση για το κλουβί σας μέσω του αρχείου «Cargo.toml»." + +#, fuzzy +#~ msgid "" +#~ " * To avoid splitting the ecosystem, Rust compilers can mix code\n" +#~ " written for different editions." +#~ msgstr "" +#~ " * Για να αποφευχθεί η διάσπαση του οικοσυστήματος, οι μεταγλωττιστές " +#~ "Rust μπορούν να συνδυάσουν κώδικα\n" +#~ " γραμμένο για διαφορετικές εκδόσεις." + +#, fuzzy +#~ msgid "" +#~ " * Mention that it is quite rare to ever use the compiler directly not " +#~ "through `cargo` (most users never do)." +#~ msgstr "" +#~ " * Αναφέρετε ότι είναι πολύ σπάνιο να χρησιμοποιήσετε ποτέ τον " +#~ "μεταγλωττιστή απευθείας όχι μέσω «cargo» (οι περισσότεροι χρήστες δεν το " +#~ "κάνουν ποτέ)." + +#, fuzzy +#~ msgid "" +#~ " * It might be worth alluding that Cargo itself is an extremely powerful " +#~ "and comprehensive tool. It is capable of many advanced features " +#~ "including but not limited to: \n" +#~ " * Project/package structure\n" +#~ " * [workspaces]\n" +#~ " * Dev Dependencies and Runtime Dependency management/caching\n" +#~ " * [build scripting]\n" +#~ " * [global installation]\n" +#~ " * It is also extensible with sub command plugins as well (such as " +#~ "[cargo clippy]).\n" +#~ " * Read more from the [official Cargo Book]" +#~ msgstr "" +#~ " * Ίσως αξίζει να αναφέρουμε ότι το ίδιο το Cargo είναι ένα εξαιρετικά " +#~ "ισχυρό και ολοκληρωμένο εργαλείο. Είναι ικανό για πολλά προηγμένα " +#~ "χαρακτηριστικά, όπως ενδεικτικά:\n" +#~ " * Δομή έργου/πακέτου\n" +#~ " * [χώροι εργασίας]\n" +#~ " * Εξαρτήσεις προγραμματιστή και διαχείριση/αποθήκευση εξαρτήσεων " +#~ "χρόνου εκτέλεσης\n" +#~ " * [κατασκευή σεναρίων]\n" +#~ " * [καθολική εγκατάσταση]\n" +#~ " * Είναι επίσης επεκτάσιμο με πρόσθετα δευτερευουσών εντολών (όπως " +#~ "[cargo clippy]).\n" +#~ " * Διαβάστε περισσότερα από το [επίσημο βιβλίο φορτίου]" + +#, fuzzy +#~ msgid "[editions]: https://doc.rust-lang.org/edition-guide/" +#~ msgstr "[εκδόσεις]: https://doc.rust-lang.org/edition-guide/" + +#, fuzzy +#~ msgid "" +#~ "[workspaces]: https://doc.rust-lang.org/cargo/reference/workspaces.html" +#~ msgstr "" +#~ "[χώροι εργασίας]: https://doc.rust-lang.org/cargo/reference/workspaces." +#~ "html" + +#, fuzzy +#~ msgid "" +#~ "[build scripting]: https://doc.rust-lang.org/cargo/reference/build-" +#~ "scripts.html" +#~ msgstr "" +#~ "[build scripting]: https://doc.rust-lang.org/cargo/reference/build-" +#~ "scripts.html" + +#, fuzzy +#~ msgid "" +#~ "[global installation]: https://doc.rust-lang.org/cargo/commands/cargo-" +#~ "install.html" +#~ msgstr "" +#~ "[παγκόσμια εγκατάσταση]: https://doc.rust-lang.org/cargo/commands/cargo-" +#~ "install.html" + +#, fuzzy +#~ msgid "[cargo clippy]: https://github.com/rust-lang/rust-clippy" +#~ msgstr "[cargo clippy]: https://github.com/rust-lang/rust-clippy" + +#, fuzzy +#~ msgid "[official Cargo Book]: https://doc.rust-lang.org/cargo/" +#~ msgstr "[επίσημο βιβλίο φορτίου]: https://doc.rust-lang.org/cargo/" + +#, 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." +#~ msgstr "" +#~ "* Οι ενσωματωμένες παιδικές χαρές δεν μπορούν να εκτελέσουν δοκιμές " +#~ "μονάδων. Αντιγραφή-επικόλληση το\n" +#~ " κωδικοποιήστε και ανοίξτε το στην πραγματική παιδική χαρά για να " +#~ "επιδείξετε δοκιμές μονάδων." + +#, fuzzy +#~ msgid "" +#~ "1. Click the \"Copy to clipboard\" button on the example you want to copy." +#~ msgstr "" +#~ "1. Κάντε κλικ στο κουμπί \"Αντιγραφή στο πρόχειρο\" στο παράδειγμα που " +#~ "θέλετε να αντιγράψετε." + +#, fuzzy +#~ msgid "" +#~ "2. Use `cargo new exercise` to create a new `exercise/` directory for " +#~ "your code:" +#~ msgstr "" +#~ "2. Χρησιμοποιήστε το «cargo new exercise» για να δημιουργήσετε έναν νέο " +#~ "κατάλογο «exercise/» για τον κώδικά σας:" + +#, fuzzy +#~ msgid "" +#~ "3. Navigate into `exercise/` and use `cargo run` to build and run your " +#~ "binary:" +#~ msgstr "" +#~ "3. Πλοηγηθείτε στο «άσκηση/» και χρησιμοποιήστε το «cargo run» για να " +#~ "δημιουργήσετε και να εκτελέσετε το δυαδικό σας αρχείο:" + +#, fuzzy +#~ msgid "" +#~ "4. Replace the boiler-plate code in `src/main.rs` with your own code. " +#~ "For\n" +#~ " example, using the example on the previous page, make `src/main.rs` " +#~ "look like" +#~ msgstr "" +#~ "4. Αντικαταστήστε τον κωδικό λέβητα στο «src/main.rs» με τον δικό σας " +#~ "κωδικό. Για\n" +#~ " Για παράδειγμα, χρησιμοποιώντας το παράδειγμα της προηγούμενης " +#~ "σελίδας, κάντε το \"src/main.rs\" να μοιάζει" + +#, fuzzy +#~ msgid "5. Use `cargo run` to build and run your updated binary:" +#~ msgstr "" +#~ "5. Χρησιμοποιήστε το \"cargo run\" για να δημιουργήσετε και να εκτελέσετε " +#~ "το ενημερωμένο δυαδικό σας αρχείο:" + +#, fuzzy +#~ msgid "" +#~ "6. Use `cargo check` to quickly check your project for errors, use `cargo " +#~ "build`\n" +#~ " to compile it without running it. You will find the output in `target/" +#~ "debug/`\n" +#~ " for a normal debug build. Use `cargo build --release` to produce an " +#~ "optimized\n" +#~ " release build in `target/release/`." +#~ msgstr "" +#~ "6. Χρησιμοποιήστε «έλεγχος φορτίου» για να ελέγξετε γρήγορα το έργο σας " +#~ "για σφάλματα, χρησιμοποιήστε «κατασκευή φορτίου».\n" +#~ " για να το μεταγλωττίσετε χωρίς να το εκτελέσετε. Θα βρείτε την έξοδο " +#~ "στο «target/debug/».\n" +#~ " για μια κανονική κατασκευή εντοπισμού σφαλμάτων. Χρησιμοποιήστε το " +#~ "\"cargo build --release\" για να δημιουργήσετε ένα βελτιστοποιημένο\n" +#~ " έκδοση build σε `target/release/`." + +#, fuzzy +#~ msgid "" +#~ "7. You can add dependencies for your project by editing `Cargo.toml`. " +#~ "When you\n" +#~ " run `cargo` commands, it will automatically download and compile " +#~ "missing\n" +#~ " dependencies for you." +#~ msgstr "" +#~ "7. Μπορείτε να προσθέσετε εξαρτήσεις για το έργο σας επεξεργάζοντας το " +#~ "«Cargo.toml». Οταν εσύ\n" +#~ " εκτελέστε τις εντολές «cargo», θα γίνει αυτόματα λήψη και μεταγλώττιση " +#~ "λείπει\n" +#~ " εξαρτήσεις για εσάς." + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" +#~ msgstr "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" + +#, fuzzy +#~ msgid "" +#~ "* Basic Rust syntax: variables, scalar and compound types, enums, " +#~ "structs,\n" +#~ " references, functions, and methods." +#~ msgstr "" +#~ "* Βασική σύνταξη Rust: μεταβλητές, βαθμωτοί και σύνθετοι τύποι, enums, " +#~ "δομές,\n" +#~ " αναφορές, συναρτήσεις και μεθόδους." + +#, fuzzy +#~ msgid "" +#~ "* Memory management: stack vs heap, manual memory management, scope-based " +#~ "memory\n" +#~ " management, and garbage collection." +#~ msgstr "" +#~ "* Διαχείριση μνήμης: στοίβα έναντι σωρού, χειροκίνητη διαχείριση μνήμης, " +#~ "μνήμη βάσει εμβέλειας\n" +#~ " διαχείριση και αποκομιδή σκουπιδιών." + +#, fuzzy +#~ msgid "" +#~ "* Ownership: move semantics, copying and cloning, borrowing, and " +#~ "lifetimes." +#~ msgstr "" +#~ "* Ιδιοκτησία: μετακίνηση σημασιολογίας, αντιγραφή και κλωνοποίηση, " +#~ "δανεισμός και διάρκειες ζωής." + +#, fuzzy +#~ msgid "[1]: https://blog.rust-lang.org/2015/05/15/Rust-1.0.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" + +#, fuzzy +#~ msgid "" +#~ "* Rust is very much like other languages in the C/C++/Java tradition. It " +#~ "is\n" +#~ " imperative (not functional) and it doesn't try to reinvent things " +#~ "unless\n" +#~ " absolutely necessary." +#~ msgstr "" +#~ "* Η σκουριά μοιάζει πολύ με άλλες γλώσσες στην παράδοση C/C++/Java. " +#~ "είναι\n" +#~ " επιτακτική (όχι λειτουργική) και δεν προσπαθεί να επανεφεύρει πράγματα " +#~ "εκτός και αν\n" +#~ " Απόλυτα αναγκαίο." + +#, fuzzy +#~ msgid "* Rust is modern with full support for things like Unicode." +#~ msgstr "" +#~ "* Το Rust είναι μοντέρνο με πλήρη υποστήριξη για πράγματα όπως το Unicode." + +#, fuzzy +#~ msgid "" +#~ "* Rust uses macros for situations where you want to have a variable " +#~ "number of\n" +#~ " arguments (no function [overloading](basic-syntax/functions-interlude." +#~ "md))." +#~ msgstr "" +#~ "* Το Rust χρησιμοποιεί μακροεντολές για καταστάσεις όπου θέλετε να έχετε " +#~ "έναν μεταβλητό αριθμό\n" +#~ " ορίσματα (καμία συνάρτηση [υπερφόρτωση](βασική-σύνταξη/συναρτήσεις-" +#~ "ενδιάμεσο.md))." + +#, fuzzy +#~ msgid "" +#~ "* Explain that all variables are statically typed. Try removing `i32` to " +#~ "trigger\n" +#~ " type inference. Try with `i8` instead and trigger a runtime integer " +#~ "overflow." +#~ msgstr "" +#~ "* Εξηγήστε ότι όλες οι μεταβλητές πληκτρολογούνται στατικά. Δοκιμάστε να " +#~ "αφαιρέσετε το \"i32\" για ενεργοποίηση\n" +#~ " συμπέρασμα τύπου. Δοκιμάστε με το `i8` και ενεργοποιήστε μια " +#~ "υπερχείλιση ακέραιου χρόνου εκτέλεσης." + +#, fuzzy +#~ msgid "* Change `let mut x` to `let x`, discuss the compiler error." +#~ msgstr "" +#~ "* Αλλάξτε το «let mut x» σε «let x», συζητήστε το σφάλμα του " +#~ "μεταγλωττιστή." + +#, fuzzy +#~ msgid "" +#~ "* Show how `print!` gives a compilation error if the arguments don't " +#~ "match the\n" +#~ " format string." +#~ msgstr "" +#~ "* Δείξτε πώς το \"print!\" δίνει ένα σφάλμα μεταγλώττισης εάν τα ορίσματα " +#~ "δεν ταιριάζουν με το\n" +#~ " συμβολοσειρά μορφής." + +#, fuzzy +#~ msgid "" +#~ "* Show how you need to use `{}` as a placeholder if you want to print an\n" +#~ " expression which is more complex than just a single variable." +#~ msgstr "" +#~ "* Δείξτε πώς πρέπει να χρησιμοποιήσετε το \"{}\" ως σύμβολο κράτησης " +#~ "θέσης εάν θέλετε να εκτυπώσετε ένα\n" +#~ " έκφραση που είναι πιο σύνθετη από μια απλή μεταβλητή." + +#, fuzzy +#~ msgid "" +#~ "* Show the students the standard library, show them how to search for " +#~ "`std::fmt`\n" +#~ " 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 "" +#~ "* Δείξτε στους μαθητές την τυπική βιβλιοθήκη, δείξτε τους πώς να " +#~ "αναζητούν το «std::fmt».\n" +#~ " που έχει τους κανόνες της μορφοποίησης της μίνι-γλώσσας. Είναι " +#~ "σημαντικό ότι το\n" +#~ " οι μαθητές εξοικειώνονται με την αναζήτηση στην τυπική βιβλιοθήκη." + +#, 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" +#~ " have the memory unsafety issues. In addition, you get a modern language " +#~ "with\n" +#~ " constructs like pattern matching and built-in dependency management." +#~ msgstr "" +#~ "* Εμπειρία με C ή C++: Το Rust εξαλείφει μια ολόκληρη κατηγορία _runtime " +#~ "errors_\n" +#~ " μέσω του ελεγκτή δανείου. Έχετε απόδοση όπως στη C και τη C++, αλλά δεν " +#~ "έχετε\n" +#~ " έχετε προβλήματα με την ασφάλεια της μνήμης. Επιπλέον, αποκτάτε μια " +#~ "σύγχρονη γλώσσα με\n" +#~ " κατασκευές όπως η αντιστοίχιση προτύπων και η ενσωματωμένη διαχείριση " +#~ "εξαρτήσεων." + +#, fuzzy +#~ msgid "" +#~ "[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method." +#~ "leak\n" +#~ "[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" +#~ "[reference cycle]: https://doc.rust-lang.org/book/ch15-06-reference-" +#~ "cycles.html" +#~ msgstr "" +#~ "[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method." +#~ "leak\n" +#~ "[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" +#~ "[κύκλος αναφοράς]: https://doc.rust-lang.org/book/ch15-06-reference-" +#~ "cycles.html" + +#, fuzzy +#~ msgid "" +#~ "* Bounds checking cannot be disabled with a compiler flag. It can also\n" +#~ " not be disabled directly with the `unsafe` keyword. However,\n" +#~ " `unsafe` allows you to call functions such as `slice::get_unchecked`\n" +#~ " which does not do bounds checking." +#~ msgstr "" +#~ "* Ο έλεγχος ορίων δεν μπορεί να απενεργοποιηθεί με μια σημαία " +#~ "μεταγλωττιστή. Μπορεί επίσης\n" +#~ " να μην απενεργοποιηθεί απευθείας με τη λέξη-κλειδί \"μη ασφαλής\". " +#~ "Ωστόσο,\n" +#~ " Το \"unsafe\" σάς επιτρέπει να καλείτε συναρτήσεις όπως \"slice::" +#~ "get_unchecked\".\n" +#~ " που δεν κάνει έλεγχο ορίων." + +#, fuzzy +#~ msgid "" +#~ "* Zero-cost abstractions, similar to C++, means that you don't have to " +#~ "'pay'\n" +#~ " for higher-level programming constructs with memory or CPU. For " +#~ "example,\n" +#~ " writing a loop using `for` should result in roughly the same low level\n" +#~ " instructions as using the `.iter().fold()` construct." +#~ msgstr "" +#~ "* Αφαιρέσεις μηδενικού κόστους, παρόμοιες με τη C++, σημαίνει ότι δεν " +#~ "χρειάζεται να «πληρώσετε»\n" +#~ " για κατασκευές προγραμματισμού υψηλότερου επιπέδου με μνήμη ή CPU. Για " +#~ "παράδειγμα,\n" +#~ " Η σύνταξη ενός βρόχου χρησιμοποιώντας «για» θα πρέπει να έχει περίπου " +#~ "το ίδιο χαμηλό επίπεδο\n" +#~ " οδηγίες όπως χρησιμοποιώντας την κατασκευή `.iter().fold()`." + +#, fuzzy +#~ msgid "" +#~ "* It may be worth mentioning that Rust enums are 'Algebraic Data Types', " +#~ "also\n" +#~ " known as 'sum types', which allow the type system to express things " +#~ "like\n" +#~ " `Option` and `Result`." +#~ msgstr "" +#~ "* Αξίζει να αναφέρουμε ότι τα Rust enums είναι επίσης «Αλγεβρικοί τύποι " +#~ "δεδομένων».\n" +#~ " γνωστοί ως «τύποι αθροίσματος», οι οποίοι επιτρέπουν στο σύστημα τύπων " +#~ "να εκφράσει πράγματα όπως\n" +#~ " \"Επιλογή\" και \"Αποτέλεσμα\"." + +#, fuzzy +#~ msgid "" +#~ "* Remind people to read the errors --- many developers have gotten used " +#~ "to\n" +#~ " ignore lengthy compiler output. The Rust compiler is significantly " +#~ "more\n" +#~ " talkative than other compilers. It will often provide you with " +#~ "_actionable_\n" +#~ " feedback, ready to copy-paste into your code." +#~ msgstr "" +#~ "* Υπενθυμίστε στους ανθρώπους να διαβάσουν τα σφάλματα --- πολλοί " +#~ "προγραμματιστές έχουν συνηθίσει\n" +#~ " αγνοήστε την έξοδο του μεταγλωττιστή μεγάλης διάρκειας. Ο " +#~ "μεταγλωττιστής Rust είναι πολύ περισσότερος\n" +#~ " ομιλητικός από άλλους μεταγλωττιστές. Συχνά θα σας παρέχει " +#~ "_actionable_\n" +#~ " σχόλια, έτοιμο για αντιγραφή-επικόλληση στον κώδικά σας." + +#, fuzzy +#~ msgid "" +#~ "* The Rust standard library is small compared to languages like Java, " +#~ "Python,\n" +#~ " and Go. Rust does not come with several things you might consider " +#~ "standard and\n" +#~ " essential:" +#~ msgstr "" +#~ "* Η τυπική βιβλιοθήκη Rust είναι μικρή σε σύγκριση με γλώσσες όπως Java, " +#~ "Python,\n" +#~ " και φύγε. Η σκουριά δεν συνοδεύεται από πολλά πράγματα που μπορεί να " +#~ "θεωρήσετε τυπικά και\n" +#~ " ουσιώδης:" + +#, fuzzy +#~ msgid "" +#~ " * a random number generator, but see [rand].\n" +#~ " * support for SSL or TLS, but see [rusttls].\n" +#~ " * support for JSON, but see [serde_json]." +#~ msgstr "" +#~ " * μια γεννήτρια τυχαίων αριθμών, αλλά δείτε [rand].\n" +#~ " * υποστήριξη για SSL ή TLS, αλλά ανατρέξτε στο [rusttls].\n" +#~ " * υποστήριξη για JSON, αλλά ανατρέξτε στο [serde_json]." + +#, fuzzy +#~ msgid "" +#~ " The reasoning behind this is that functionality in the standard library " +#~ "cannot\n" +#~ " go away, so it has to be very stable. For the examples above, the Rust\n" +#~ " community is still working on finding the best solution --- and perhaps " +#~ "there\n" +#~ " isn't a single \"best solution\" for some of these things." +#~ msgstr "" +#~ " Το σκεπτικό πίσω από αυτό είναι ότι η λειτουργικότητα στην τυπική " +#~ "βιβλιοθήκη δεν μπορεί\n" +#~ " φύγετε, οπότε πρέπει να είναι πολύ σταθερό. Για τα παραπάνω " +#~ "παραδείγματα, η Σκουριά\n" +#~ " Η κοινότητα εξακολουθεί να εργάζεται για την εύρεση της καλύτερης λύσης " +#~ "--- και ίσως εκεί\n" +#~ " δεν είναι μια ενιαία \"καλύτερη λύση\" για μερικά από αυτά τα πράγματα." + +#, fuzzy +#~ msgid "" +#~ " Rust comes with a built-in package manager in the form of Cargo and " +#~ "this makes\n" +#~ " it trivial to download and compile third-party crates. A consequence of " +#~ "this\n" +#~ " is that the standard library can be smaller." +#~ msgstr "" +#~ " Το Rust έρχεται με ενσωματωμένο διαχειριστή πακέτων σε μορφή Cargo και " +#~ "αυτό κάνει\n" +#~ " Είναι ασήμαντο να κατεβάζετε και να μεταγλωττίζετε κιβώτια τρίτων. " +#~ "Συνέπεια αυτού\n" +#~ " είναι ότι η τυπική βιβλιοθήκη μπορεί να είναι μικρότερη." + +#, fuzzy +#~ msgid "" +#~ " Discovering good third-party crates can be a problem. Sites like\n" +#~ " help with this by letting you compare health metrics " +#~ "for\n" +#~ " crates to find a good and trusted one.\n" +#~ " \n" +#~ "* [rust-analyzer] is a well supported LSP implementation used in major\n" +#~ " IDEs and text editors." +#~ msgstr "" +#~ " Η ανακάλυψη καλών κιβωτίων τρίτων μπορεί να είναι πρόβλημα. Ιστότοποι " +#~ "όπως\n" +#~ " βοηθήστε σε αυτό, επιτρέποντάς σας να συγκρίνετε " +#~ "μετρήσεις υγείας για\n" +#~ " κιβώτια για να βρείτε ένα καλό και αξιόπιστο.\n" +#~ " \n" +#~ "* Το [rust-analyzer] είναι μια καλά υποστηριζόμενη υλοποίηση LSP που " +#~ "χρησιμοποιείται σε μεγάλες\n" +#~ " IDE και επεξεργαστές κειμένου." + +#, fuzzy +#~ msgid "" +#~ "[rand]: https://docs.rs/rand/\n" +#~ "[rusttls]: https://docs.rs/rustls/\n" +#~ "[serde_json]: https://docs.rs/serde_json/\n" +#~ "[rust-analyzer]: https://rust-analyzer.github.io/" +#~ msgstr "" +#~ "[rand]: https://docs.rs/rand/\n" +#~ "[rusttls]: https://docs.rs/rustls/\n" +#~ "[serde_json]: https://docs.rs/serde_json/\n" +#~ "[rust-analyzer]: https://rust-analyzer.github.io/" + +#, fuzzy +#~ msgid "* We can use literals to assign values to arrays." +#~ msgstr "" +#~ "* Μπορούμε να χρησιμοποιήσουμε literals για να εκχωρήσουμε τιμές σε " +#~ "πίνακες." + +#, fuzzy +#~ msgid "" +#~ "* In the main function, the print statement asks for the debug " +#~ "implementation with the `?` format\n" +#~ " parameter: `{}` gives the default output, `{:?}` gives the debug " +#~ "output. We\n" +#~ " could also have used `{a}` and `{a:?}` without specifying the value " +#~ "after the\n" +#~ " format string." +#~ msgstr "" +#~ "* Στην κύρια συνάρτηση, η δήλωση εκτύπωσης ζητά την υλοποίηση εντοπισμού " +#~ "σφαλμάτων με τη μορφή «?».\n" +#~ " παράμετρος: Το `{}` δίνει την προεπιλεγμένη έξοδο, το `{:?}` δίνει την " +#~ "έξοδο εντοπισμού σφαλμάτων. Εμείς\n" +#~ " θα μπορούσε επίσης να χρησιμοποιήσει τα \"{a}\" και \"{a:?}\" χωρίς να " +#~ "καθορίσει την τιμή μετά το\n" +#~ " συμβολοσειρά μορφής." + +#, fuzzy +#~ msgid "" +#~ "* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which " +#~ "can be easier to read." +#~ msgstr "" +#~ "* Προσθέτοντας `#`, π.χ. `{a:#?}`, προκαλείται μια μορφή \"όμορφης " +#~ "εκτύπωσης\", η οποία μπορεί να είναι πιο ευανάγνωστη." + +#, fuzzy +#~ msgid "* Like arrays, tuples have a fixed length." +#~ msgstr "* Όπως και οι πίνακες, οι πλειάδες έχουν σταθερό μήκος." + +#, fuzzy +#~ msgid "" +#~ "* Tuples group together values of different types into a compound type." +#~ msgstr "" +#~ "* Οι πλειάδες ομαδοποιούν τιμές διαφορετικών τύπων σε έναν σύνθετο τύπο." + +#, fuzzy +#~ msgid "" +#~ "* Fields of a tuple can be accessed by the period and the index of the " +#~ "value, e.g. `t.0`, `t.1`." +#~ msgstr "" +#~ "* Τα πεδία μιας πλειάδας είναι προσβάσιμα από την περίοδο και τον δείκτη " +#~ "της τιμής, π.χ. «t.0», «t.1»." + +#, fuzzy +#~ msgid "" +#~ "* We create a slice by borrowing `a` and specifying the starting and " +#~ "ending indexes in brackets." +#~ msgstr "" +#~ "* Δημιουργούμε ένα slice δανειζόμενοι το `a` και προσδιορίζοντας τους " +#~ "δείκτες έναρξης και λήξης σε αγκύλες." + +#, fuzzy +#~ msgid "" +#~ "* If the slice starts at index 0, Rust’s range syntax allows us to drop " +#~ "the starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are " +#~ "identical.\n" +#~ " \n" +#~ "* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` " +#~ "are identical." +#~ msgstr "" +#~ "* Εάν το slice ξεκινά από το δείκτη 0, η σύνταξη εύρους του Rust μας " +#~ "επιτρέπει να απορρίψουμε τον αρχικό δείκτη, πράγμα που σημαίνει ότι το " +#~ "«&a[0..a.len()]» και το «&a[..a.len()]» είναι πανομοιότυπα .\n" +#~ " \n" +#~ "* Το ίδιο ισχύει και για τον τελευταίο δείκτη, επομένως τα «&a[2..a." +#~ "len()]» και «&a[2..]» είναι πανομοιότυπα." + +#, fuzzy +#~ msgid "" +#~ "* To easily create a slice of the full array, we can therefore use " +#~ "`&a[..]`." +#~ msgstr "" +#~ "* Για να δημιουργήσουμε εύκολα ένα κομμάτι του πλήρους πίνακα, μπορούμε " +#~ "επομένως να χρησιμοποιήσουμε το «&a[..]»." + +#, fuzzy +#~ msgid "" +#~ "* `&str` introduces a string slice, which is an immutable reference to " +#~ "UTF-8 encoded string data \n" +#~ " stored in a block of memory. String literals (`”Hello”`), are stored in " +#~ "the program’s binary." +#~ msgstr "" +#~ "* Το \"&str\" εισάγει ένα slice συμβολοσειράς, το οποίο είναι μια " +#~ "αμετάβλητη αναφορά σε κωδικοποιημένα δεδομένα συμβολοσειράς UTF-8\n" +#~ " αποθηκευμένο σε ένα μπλοκ μνήμης. Οι κυριολεκτικές συμβολοσειρές " +#~ "(\"Hello\"\"), αποθηκεύονται στο δυαδικό αρχείο του προγράμματος." + +#, fuzzy +#~ msgid " (Type annotations added for clarity, but they can be elided.)" +#~ msgstr "" +#~ " (Πληκτρολογήστε σχολιασμούς για λόγους σαφήνειας, αλλά μπορούν να " +#~ "διαγραφούν.)" + +#, fuzzy +#~ msgid "" +#~ "impl Rectangle {\n" +#~ " fn area(&self) -> u32 {\n" +#~ " self.width * self.height\n" +#~ " }" +#~ msgstr "" +#~ "impmpl Rectangle {\n" +#~ " fn area(&self) -> u32 {\n" +#~ " αυτο.πλάτος * εαυτός.ύψος\n" +#~ " }" + +#, fuzzy +#~ msgid "* Arrays and `for` loops." +#~ msgstr "* Πίνακες και βρόχοι «για»." + +#, fuzzy +#~ msgid "* Alternatively, use the Rust Playground." +#~ msgstr "* Εναλλακτικά, χρησιμοποιήστε την παιδική χαρά Rust." + +#, fuzzy +#~ msgid "[solutions]: solutions-morning.md" +#~ msgstr "[λύσεις]: λύσεις-πρωί.μδ" + +#, fuzzy +#~ msgid "[Using Cargo]: ../../cargo.md" +#~ msgstr "[Χρήση φορτίου]: ../../cargo.md" + +#, fuzzy +#~ msgid "1. Execute the above program and look at the compiler error." +#~ msgstr "" +#~ "1. Εκτελέστε το παραπάνω πρόγραμμα και δείτε το σφάλμα μεταγλωττιστή." + +#, fuzzy +#~ msgid "2. Update the code above to use `into()` to do the conversion." +#~ msgstr "" +#~ "2. Ενημερώστε τον παραπάνω κώδικα για να χρησιμοποιήσετε το «into()» για " +#~ "να κάνετε τη μετατροπή." + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" +#~ "[2]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" +#~ "[3]: https://en.cppreference.com/w/cpp/language/implicit_conversion" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" +#~ "[2]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" +#~ "[3]: https://en.cppreference.com/w/cpp/language/implicit_conversion" + +#, fuzzy +#~ msgid "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" +#~ msgstr "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" + +#, fuzzy +#~ msgid "" +#~ "* Heap: Storage of values outside of function calls.\n" +#~ " * Values have dynamic sizes determined at runtime.\n" +#~ " * Slightly slower than the stack: some book-keeping needed.\n" +#~ " * No guarantee of memory locality." +#~ msgstr "" +#~ "* Σωρός: Αποθήκευση τιμών εκτός κλήσεων συναρτήσεων.\n" +#~ " * Οι τιμές έχουν δυναμικά μεγέθη που καθορίζονται κατά το χρόνο " +#~ "εκτέλεσης.\n" +#~ " * Ελαφρώς πιο αργό από τη στοίβα: χρειάζεται λίγη τήρηση βιβλίων.\n" +#~ " * Καμία εγγύηση εντοπισμού μνήμης." + +#, fuzzy +#~ msgid "" +#~ "* Mention that a `String` is backed by a `Vec`, so it has a capacity and " +#~ "length and can grow if mutable via reallocation on the heap." +#~ msgstr "" +#~ "* Αναφέρετε ότι ένα \"String\" υποστηρίζεται από ένα \"Vec\", επομένως " +#~ "έχει χωρητικότητα και μήκος και μπορεί να αναπτυχθεί εάν είναι μεταβλητό " +#~ "μέσω ανακατανομής στο σωρό." + +#, fuzzy +#~ msgid "" +#~ "* If students ask about it, you can mention that the underlying memory is " +#~ "heap allocated using the [System Allocator] and custom allocators can be " +#~ "implemented using the [Allocator API]" +#~ msgstr "" +#~ "* Εάν οι μαθητές το ρωτήσουν, μπορείτε να αναφέρετε ότι η υποκείμενη " +#~ "μνήμη είναι ένα σωρό που εκχωρείται με χρήση του [System Allocator] και " +#~ "οι προσαρμοσμένοι εκχωρητές μπορούν να υλοποιηθούν χρησιμοποιώντας το " +#~ "[Allocator API]" + +#, fuzzy +#~ msgid "" +#~ "[System Allocator]: https://doc.rust-lang.org/std/alloc/struct.System." +#~ "html\n" +#~ "[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html" +#~ msgstr "" +#~ "[Διανομέας συστήματος]: https://doc.rust-lang.org/std/alloc/struct.System." +#~ "html\n" +#~ "[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html" + +#, fuzzy +#~ msgid "" +#~ "* You may be asked about destructors here, the [Drop] trait is the Rust " +#~ "equivalent." +#~ msgstr "" +#~ "* Μπορεί να ερωτηθείτε για τους καταστροφείς εδώ, το χαρακτηριστικό " +#~ "[Drop] είναι το ισοδύναμο της Σκουριάς." + +#, fuzzy +#~ msgid "" +#~ "[Box]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +#~ "[Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +#~ "[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +#~ "[Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html" +#~ msgstr "" +#~ "[Πλαίσιο]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +#~ "[Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +#~ "[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +#~ "[Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html" + +#, fuzzy +#~ msgid "* In Rust, you clones are explicit (by using `clone`)." +#~ msgstr "" +#~ "* Στο Rust, οι κλώνοι σας είναι ξεκάθαροι (χρησιμοποιώντας «κλώνο»)." + +#, fuzzy +#~ msgid "" +#~ "fn add(p1: &Point, p2: &Point) -> Point {\n" +#~ " Point(p1.0 + p2.0, p1.1 + p2.1)\n" +#~ "}" +#~ msgstr "" +#~ "fn add(p1: &Point, p2: &Point) -> Point {\n" +#~ " Σημείο(p1.0 + p2.0, p1.1 + p2.1)\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "Notes on stack returns:\n" +#~ "* Demonstrate that the return from `add` is cheap because the compiler " +#~ "can eliminate the copy operation. Change the above code to print stack " +#~ "addresses and run it on the [Playground]. In the \"DEBUG\" optimization " +#~ "level, the addresses should change, while the stay the same when changing " +#~ "to the \"RELEASE\" setting:" +#~ msgstr "" +#~ "Σημειώσεις για τις επιστροφές στοίβας:\n" +#~ "* Αποδείξτε ότι η επιστροφή από το «add» είναι φθηνή επειδή ο " +#~ "μεταγλωττιστής μπορεί να εξαλείψει τη λειτουργία αντιγραφής. Αλλάξτε τον " +#~ "παραπάνω κωδικό για να εκτυπώσετε διευθύνσεις στοίβας και εκτελέστε τον " +#~ "στην [Playground]. Στο επίπεδο βελτιστοποίησης \"DEBUG\", οι διευθύνσεις " +#~ "θα πρέπει να αλλάξουν, ενώ θα παραμείνουν οι ίδιες κατά την αλλαγή στη " +#~ "ρύθμιση \"RELEASE\":" + +#, fuzzy +#~ msgid "[Playground]: https://play.rust-lang.org/" +#~ msgstr "[Παιδική χαρά]: https://play.rust-lang.org/" + +#, fuzzy +#~ msgid "" +#~ "fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +#~ " if p1.0 < p2.0 { p1 } else { p2 }\n" +#~ "}" +#~ msgstr "" +#~ "fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +#~ " αν p1.0 < p2.0 { p1 } other { p2 }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +#~ " if p1.0 < p2.0 { p1 } else { p2 }\n" +#~ " }" +#~ msgstr "" +#~ " fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +#~ " αν p1.0 < p2.0 { p1 } other { p2 }\n" +#~ " }" + +#, fuzzy +#~ msgid "* A small book library," +#~ msgstr "* Μια μικρή βιβλιοθήκη," + +#, fuzzy +#~ msgid "[solutions]: solutions-afternoon.md" +#~ msgstr "[λύσεις]: λύσεις-απόγευμα.μδ" + +#, fuzzy +#~ msgid "" +#~ "struct Library {\n" +#~ " books: Vec,\n" +#~ "}" +#~ msgstr "" +#~ "struct Library {\n" +#~ " βιβλία: Vec,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "struct Book {\n" +#~ " title: String,\n" +#~ " year: u16,\n" +#~ "}" +#~ msgstr "" +#~ "struct Βιβλίο {\n" +#~ " τίτλος: String,\n" +#~ " έτος: u16,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Book {\n" +#~ " // This is a constructor, used below.\n" +#~ " fn new(title: &str, year: u16) -> Book {\n" +#~ " Book {\n" +#~ " title: String::from(title),\n" +#~ " year,\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impmpl Book {\n" +#~ " // Αυτός είναι ένας κατασκευαστής, που χρησιμοποιείται παρακάτω.\n" +#~ " fn new(title: &str, year: u16) -> Book {\n" +#~ " Βιβλίο {\n" +#~ " τίτλος: Συμβολοσειρά::από(τίτλος),\n" +#~ " έτος,\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// 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" +#~ "}" +#~ msgstr "" +#~ "// Αυτό καθιστά δυνατή την εκτύπωση τιμών βιβλίου με {}.\n" +#~ "impl std::fmt::Display for Book {\n" +#~ " fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::" +#~ "Αποτέλεσμα {\n" +#~ " write!(f, \"{} ({})\", self.title, self.year)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Library {\n" +#~ " fn new() -> Library {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl Library {\n" +#~ " fn new() -> Library {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " //fn len(self) -> usize {\n" +#~ " // unimplemented!()\n" +#~ " //}" +#~ msgstr "" +#~ " //fn len(self) -> χρήση {\n" +#~ " // δεν εφαρμόζεται!()\n" +#~ " //}" + +#, fuzzy +#~ msgid "" +#~ " //fn is_empty(self) -> bool {\n" +#~ " // unimplemented!()\n" +#~ " //}" +#~ msgstr "" +#~ " //fn is_empty(self) -> bool {\n" +#~ " // δεν εφαρμόζεται!()\n" +#~ " //}" + +#, fuzzy +#~ msgid "" +#~ " //fn add_book(self, book: Book) {\n" +#~ " // unimplemented!()\n" +#~ " //}" +#~ msgstr "" +#~ " //fn add_book(self, book: Book) {\n" +#~ " // δεν εφαρμόζεται!()\n" +#~ " //}" + +#, fuzzy +#~ msgid "" +#~ " //fn print_books(self) {\n" +#~ " // unimplemented!()\n" +#~ " //}" +#~ msgstr "" +#~ " //fn print_books(self) {\n" +#~ " // δεν εφαρμόζεται!()\n" +#~ " //}" + +#, fuzzy +#~ msgid "" +#~ " //fn oldest_book(self) -> Option<&Book> {\n" +#~ " // unimplemented!()\n" +#~ " //}\n" +#~ "}" +#~ msgstr "" +#~ " //fn oldest_book(self) -> Option<&Book> {\n" +#~ " // δεν εφαρμόζεται!()\n" +#~ " //}\n" +#~ "}" + +#, fuzzy +#~ msgid "* Structs, enums, methods." +#~ msgstr "* Δομές, αρίθμηση, μέθοδοι." + +#, fuzzy +#~ msgid "* Pattern matching: destructuring enums, structs, and arrays." +#~ msgstr "* Αντιστοίχιση προτύπων: καταστροφή αριθμών, δομών και πινάκων." + +#, fuzzy +#~ msgid "" +#~ "* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, " +#~ "and\n" +#~ " `continue`." +#~ msgstr "" +#~ "* Κατασκευές ροής ελέγχου: \"if\", \"if let\", \"while\", \"while let\", " +#~ "\"break\" και\n" +#~ " «συνέχεια»." + +#, fuzzy +#~ msgid "" +#~ "* The Standard Library: `String`, `Option` and `Result`, `Vec`, " +#~ "`HashMap`, `Rc`\n" +#~ " and `Arc`." +#~ msgstr "" +#~ "* Η τυπική βιβλιοθήκη: \"String\", \"Option\" και \"Result\", \"Vec\", " +#~ "\"HashMap\", \"Rc\"\n" +#~ " και «Arc»." + +#, fuzzy +#~ msgid "* Modules: visibility, paths, and filesystem hierarchy." +#~ msgstr "* Ενότητες: ορατότητα, μονοπάτια και ιεραρχία συστήματος αρχείων." + +#, fuzzy +#~ msgid "" +#~ "fn compute_thruster_force() -> PoundOfForce {\n" +#~ " todo!(\"Ask a rocket scientist at NASA\")\n" +#~ "}" +#~ msgstr "" +#~ "fn compute_thruster_force() -> PoundOfForce {\n" +#~ " todo! (\"Ρωτήστε έναν επιστήμονα πυραύλων στη NASA\")\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "fn set_thruster_force(force: Newtons) {\n" +#~ " // ...\n" +#~ "}" +#~ msgstr "" +#~ "fn set_thruster_force(δύναμη: Newtons) {\n" +#~ " //...\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Person {\n" +#~ " fn new(name: String, age: u8) -> Person {\n" +#~ " Person { name, age }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impmpl Person {\n" +#~ " fn new(όνομα: String, ηλικία: u8) -> Άτομο {\n" +#~ " Άτομο { όνομα, ηλικία }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "The `new` function could be written using `Self` as a type, as it is " +#~ "interchangeable with the struct type name" +#~ msgstr "" +#~ "Η συνάρτηση \"new\" θα μπορούσε να γραφτεί χρησιμοποιώντας το \"Self\" ως " +#~ "τύπο, καθώς είναι εναλλάξιμη με το όνομα τύπου δομής" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug)]\n" +#~ "enum CoinFlip {\n" +#~ " Heads,\n" +#~ " Tails,\n" +#~ "}" +#~ msgstr "" +#~ "#[παραγωγή (Εντοπισμός σφαλμάτων)]\n" +#~ "enum CoinFlip {\n" +#~ " κεφάλια,\n" +#~ " Ουρές,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "
\n" +#~ " \n" +#~ "Key Points:" +#~ msgstr "" +#~ "<λεπτομέρειες>\n" +#~ " \n" +#~ "Βασικά σημεία:" + +#, fuzzy +#~ msgid "" +#~ "#[rustfmt::skip]\n" +#~ "fn inspect(event: WebEvent) {\n" +#~ " match event {\n" +#~ " WebEvent::PageLoad => println!(\"page loaded\"),\n" +#~ " WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" +#~ " WebEvent::Click { x, y } => println!(\"clicked at x={x}, " +#~ "y={y}\"),\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "#[rustfmt::skip]\n" +#~ "fn inspect(event: WebEvent) {\n" +#~ " αγώνας εκδήλωσης {\n" +#~ " WebEvent::PageLoad => println!(\"σελίδα φορτώθηκε\"),\n" +#~ " WebEvent::KeyPress(c) => println!(\"πατήθηκε '{c}'\"),\n" +#~ " WebEvent::Κάντε κλικ στο { x, y } => println!(\"κλικ στο x={x}, " +#~ "y={y}\"),\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "enum Foo {\n" +#~ " A,\n" +#~ " B,\n" +#~ "}" +#~ msgstr "" +#~ "enum Foo {\n" +#~ " ΕΝΑ,\n" +#~ " ΣΙ,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "#[repr(u32)]\n" +#~ "enum Bar {\n" +#~ " A, // 0\n" +#~ " B = 10000,\n" +#~ " C, // 10001\n" +#~ "}" +#~ msgstr "" +#~ "#[repr(u32)]\n" +#~ "enum Bar {\n" +#~ " Α, // 0\n" +#~ " B = 10000,\n" +#~ " C, // 10001\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "
\n" +#~ " \n" +#~ "Key Points: \n" +#~ " * Internally Rust is using a field (discriminant) to keep track of the " +#~ "enum variant.\n" +#~ " * `Bar` enum demonstrates that there is a way to control the " +#~ "discriminant value and type. If `repr` is removed, the discriminant type " +#~ "takes 2 bytes, becuase 10001 fits 2 bytes.\n" +#~ " * As a niche optimization an enum discriminant is merged with the " +#~ "pointer so that `Option<&Foo>` is the same size as `&Foo`.\n" +#~ " * `Option` is another example of tight packing.\n" +#~ " * For [some types](https://doc.rust-lang.org/std/option/" +#~ "#representation), Rust guarantees that `size_of::()` equals `size_of::" +#~ ">()`.\n" +#~ " * Zero-sized types allow for efficient implementation of `HashSet` using " +#~ "`HashMap` with `()` as the value." +#~ msgstr "" +#~ "<λεπτομέρειες>\n" +#~ " \n" +#~ "Βασικά σημεία:\n" +#~ " * Εσωτερικά το Rust χρησιμοποιεί ένα πεδίο (διακριτικό) για να " +#~ "παρακολουθεί την παραλλαγή enum.\n" +#~ " * Το \"Bar\" enum δείχνει ότι υπάρχει τρόπος να ελέγχεται η τιμή και ο " +#~ "τύπος διάκρισης. Εάν αφαιρεθεί το \"repr\", ο τύπος διάκρισης παίρνει 2 " +#~ "byte, επειδή το 10001 ταιριάζει σε 2 byte.\n" +#~ " * Ως βελτιστοποίηση εξειδικευμένης θέσης, ένα διακριτικό enum " +#~ "συγχωνεύεται με τον δείκτη έτσι ώστε το \"Option<&Foo>\" να έχει το ίδιο " +#~ "μέγεθος με το \"&Foo\".\n" +#~ " * Το \"Option\" είναι ένα άλλο παράδειγμα στενής συσκευασίας.\n" +#~ " * Για [ορισμένους τύπους](https://doc.rust-lang.org/std/option/" +#~ "#representation), η Rust εγγυάται ότι το \"size_of::()\" ισούται με " +#~ "\"size_of::<Επιλογή >()».\n" +#~ " * Οι τύποι μηδενικού μεγέθους επιτρέπουν την αποτελεσματική εφαρμογή του " +#~ "\"HashSet\" χρησιμοποιώντας το \"HashMap\" με το \"()\" ως τιμή." + +#, fuzzy +#~ msgid "" +#~ "impl Race {\n" +#~ " fn new(name: &str) -> Race { // No receiver, a static method\n" +#~ " Race { name: String::from(name), laps: Vec::new() }\n" +#~ " }" +#~ msgstr "" +#~ "impmpl Race {\n" +#~ " fn new(name: &str) -> Race { // Χωρίς δέκτη, μια στατική μέθοδος\n" +#~ " Race { name: String::from(name), laps: Vec::new() }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "fn divide_in_two(n: i32) -> Result {\n" +#~ " if n % 2 == 0 {\n" +#~ " Result::Ok(n / 2)\n" +#~ " } else {\n" +#~ " Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "fn divide_in_two(n: i32) -> Αποτέλεσμα {\n" +#~ " αν n % 2 == 0 {\n" +#~ " Αποτέλεσμα::Ok(n / 2)\n" +#~ " } αλλο {\n" +#~ " Αποτέλεσμα::Err(μορφή!(\"δεν μπορεί να διαιρεθεί το {} σε δύο ίσα " +#~ "μέρη\", n))\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "* Simple struct which tracks health statistics." +#~ msgstr "* Απλή δομή που παρακολουθεί τα στατιστικά στοιχεία υγείας." + +#, fuzzy +#~ msgid "" +#~ "struct User {\n" +#~ " name: String,\n" +#~ " age: u32,\n" +#~ " weight: f32,\n" +#~ "}" +#~ msgstr "" +#~ "struct Χρήστης {\n" +#~ " όνομα: String,\n" +#~ " ηλικία: u32,\n" +#~ " βάρος: f32,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl User {\n" +#~ " pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl Χρήστης {\n" +#~ " pub fn new(όνομα: String, ηλικία: u32, βάρος: f32) -> Self {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn name(&self) -> &str {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn name(&self) -> &str {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn age(&self) -> u32 {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ " παμπ fn age(&self) -> u32 {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn weight(&self) -> f32 {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ " παμπ fn βάρος(&self) -> f32 {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn set_age(&mut self, new_age: u32) {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn set_age(&mut self, new_age: u32) {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn set_weight(&mut self, new_weight: f32) {\n" +#~ " unimplemented!()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " pub fn set_weight(&mut self, new_weight: f32) {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Point {\n" +#~ " // add fields\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Point {\n" +#~ " // προσθήκη πεδίων\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Point {\n" +#~ " // add methods\n" +#~ "}" +#~ msgstr "" +#~ "εμφ. Σημείο {\n" +#~ " // προσθήκη μεθόδων\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Polygon {\n" +#~ " // add fields\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Πολύγωνο {\n" +#~ " // προσθήκη πεδίων\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Polygon {\n" +#~ " // add methods\n" +#~ "}" +#~ msgstr "" +#~ "impmpl Polygon {\n" +#~ " // προσθήκη μεθόδων\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Circle {\n" +#~ " // add fields\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Circle {\n" +#~ " // προσθήκη πεδίων\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Circle {\n" +#~ " // add methods\n" +#~ "}" +#~ msgstr "" +#~ "impmpl Circle {\n" +#~ " // προσθήκη μεθόδων\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub enum Shape {\n" +#~ " Polygon(Polygon),\n" +#~ " Circle(Circle),\n" +#~ "}" +#~ msgstr "" +#~ "pub enum Shape {\n" +#~ " Πολύγωνο (Πολύγωνο),\n" +#~ " Κύκλος (Κύκλος),\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " fn round_two_digits(x: f64) -> f64 {\n" +#~ " (x * 100.0).round() / 100.0\n" +#~ " }" +#~ msgstr "" +#~ " fn round_two_digits(x: f64) -> f64 {\n" +#~ " (x * 100.0).round() / 100.0\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "* [`Option` and `Result`](std/option-result.md) types: used for optional " +#~ "values\n" +#~ " and [error handling](error-handling.md)." +#~ msgstr "" +#~ "* Τύποι ['Option' και 'Result'](std/option-result.md): χρησιμοποιούνται " +#~ "για προαιρετικές τιμές\n" +#~ " και [error handling](error-handling.md)." + +#, fuzzy +#~ msgid "" +#~ "* [`String`](std/string.md): the default string type used for owned data." +#~ msgstr "" +#~ "* [`String`](std/string.md): ο προεπιλεγμένος τύπος συμβολοσειράς που " +#~ "χρησιμοποιείται για ιδιόκτητα δεδομένα." + +#, fuzzy +#~ msgid "* [`Vec`](std/vec.md): a standard extensible vector." +#~ msgstr "* [`Vec`](std/vec.md): ένα τυπικό επεκτάσιμο διάνυσμα." + +#, fuzzy +#~ msgid "" +#~ "* [`HashMap`](std/hashmap.md): a hash map type with a configurable " +#~ "hashing\n" +#~ " algorithm." +#~ msgstr "" +#~ "* [`HashMap`](std/hashmap.md): τύπος χάρτη κατακερματισμού με δυνατότητα " +#~ "διαμόρφωσης κατακερματισμού\n" +#~ " αλγόριθμος." + +#, fuzzy +#~ msgid "* [`Box`](std/box.md): an owned pointer for heap-allocated data." +#~ msgstr "" +#~ "* [`Box`](std/box.md): ένας ιδιόκτητος δείκτης για δεδομένα που " +#~ "εκχωρούνται σε σωρό." + +#, fuzzy +#~ msgid "" +#~ "* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-" +#~ "allocated data." +#~ msgstr "" +#~ "* [`Rc`](std/rc.md): κοινόχρηστος δείκτης μέτρησης αναφοράς για δεδομένα " +#~ "που εκχωρούνται σε σωρό." + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/string/struct.String.html\n" +#~ "[2]: https://doc.rust-lang.org/std/string/struct.String.html#deref-" +#~ "methods-str" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/string/struct.String.html\n" +#~ "[2]: https://doc.rust-lang.org/std/string/struct.String.html#deref-" +#~ "methods-str" + +#, fuzzy +#~ msgid "" +#~ "* `len` returns the size of the `String` in bytes, not its length in " +#~ "characters.\n" +#~ "* `chars` returns an iterator over the actual characters.\n" +#~ "* `String` implements `Deref` which transparently gives it " +#~ "access to `str`'s methods." +#~ msgstr "" +#~ "* Το «len» επιστρέφει το μέγεθος του «String» σε byte, όχι το μήκος του " +#~ "σε χαρακτήρες.\n" +#~ "* Το `chars` επιστρέφει έναν επαναλήπτη πάνω από τους πραγματικούς " +#~ "χαρακτήρες.\n" +#~ "* Το `String` υλοποιεί το `Deref` που του δίνει με " +#~ "διαφάνεια πρόσβαση στις μεθόδους του `str`." + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +#~ "[2]: https://doc.rust-lang.org/std/vec/struct.Vec.html#deref-methods-[T]" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +#~ "[2]: https://doc.rust-lang.org/std/vec/struct.Vec.html#deref-methods-[T]" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +#~ "[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-" +#~ "coercion" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +#~ "[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-" +#~ "coercion" + +#, fuzzy +#~ msgid "" +#~ "* If the `Box` was not used here and we attempted to embed a `List` " +#~ "directly into the `List`,\n" +#~ "the compiler would not compute a fixed size of the struct in memory, it " +#~ "would look infinite." +#~ msgstr "" +#~ "<λεπτομέρειες>\n" +#~ " \n" +#~ "Εάν το \"Πλαίσιο\" δεν χρησιμοποιήθηκε εδώ και προσπαθήσαμε να " +#~ "ενσωματώσουμε μια \"Λίστα\" απευθείας στη \"Λίστα\",\n" +#~ "ο μεταγλωττιστής δεν θα υπολόγιζε ένα σταθερό μέγεθος της δομής στη " +#~ "μνήμη, θα φαινόταν άπειρο.\n" +#~ " \n" +#~ "Το \"Box\" λύνει αυτό το πρόβλημα καθώς έχει το ίδιο μέγεθος με έναν " +#~ "κανονικό δείκτη και απλώς δείχνει τον επόμενο\n" +#~ "στοιχείο της «Λίστας» στο σωρό.\n" +#~ " \n" +#~ "
" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/cell/index.html\n" +#~ "[3]: ../concurrency/shared_state/arc.md\n" +#~ "[4]: https://doc.rust-lang.org/std/rc/struct.Weak.html" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/cell/index.html\n" +#~ "[3]: ../concurrency/shared_state/arc.md" + +#, fuzzy +#~ msgid "" +#~ "1. As a relative path:\n" +#~ " * `foo` or `self::foo` refers to `foo` in the current module,\n" +#~ " * `super::foo` refers to `foo` in the parent module." +#~ msgstr "" +#~ "1. Ως σχετική διαδρομή:\n" +#~ " * Το \"foo\" ή το \"self::foo\" αναφέρεται στο \"foo\" στην τρέχουσα " +#~ "ενότητα,\n" +#~ " * Το «super::foo» αναφέρεται στο «foo» στη γονική μονάδα." + +#, fuzzy +#~ msgid "* Ignore all spaces. Reject number with less than two digits." +#~ msgstr "* Αγνοήστε όλα τα κενά. Απόρριψη αριθμού με λιγότερα από δύο ψηφία." + +#, fuzzy +#~ msgid "" +#~ "* Moving from right to left, double every second digit: for the number " +#~ "`1234`,\n" +#~ " we double `3` and `1`." +#~ msgstr "" +#~ "* Μετακίνηση από τα δεξιά προς τα αριστερά, διπλασιάστε κάθε δεύτερο " +#~ "ψηφίο: για τον αριθμό «1234»,\n" +#~ " διπλασιάζουμε «3» και «1»." + +#, fuzzy +#~ msgid "" +#~ "* After doubling a digit, sum the digits. So doubling `7` becomes `14` " +#~ "which\n" +#~ " becomes `5`." +#~ msgstr "" +#~ "* Μετά τον διπλασιασμό ενός ψηφίου, αθροίστε τα ψηφία. Έτσι ο " +#~ "διπλασιασμός του '7' γίνεται '14' που\n" +#~ " γίνεται «5»." + +#, fuzzy +#~ msgid "* Sum all the undoubled and doubled digits." +#~ msgstr "* Άθροισμα όλων των μη διπλασιασμένων και διπλασιασμένων ψηφίων." + +#, fuzzy +#~ msgid "* The credit card number is valid if the sum ends with `0`." +#~ msgstr "" +#~ "* Ο αριθμός της πιστωτικής κάρτας είναι έγκυρος εάν το άθροισμα τελειώνει " +#~ "με «0»." + +#, fuzzy +#~ msgid "" +#~ "pub fn luhn(cc_number: &str) -> bool {\n" +#~ " unimplemented!()\n" +#~ "}" +#~ msgstr "" +#~ "pub fn luhn(cc_number: &str) -> bool {\n" +#~ " ανεφάρμοστη!()\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +#~ " unimplemented!()\n" +#~ "}" +#~ msgstr "" +#~ "pub fn prefix_matches(πρόθεμα: &str, request_path: &str) -> bool {\n" +#~ " ανεφάρμοστη!()\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "* Traits: deriving traits, default methods, and important standard " +#~ "library\n" +#~ " traits." +#~ msgstr "" +#~ "* Χαρακτηριστικά: εξαγωγή χαρακτηριστικών, προεπιλεγμένες μέθοδοι και " +#~ "σημαντική τυπική βιβλιοθήκη\n" +#~ " χαρακτηριστικά." + +#, fuzzy +#~ msgid "" +#~ "* Generics: generic data types, generic methods, monomorphization, and " +#~ "trait\n" +#~ " objects." +#~ msgstr "" +#~ "* Γενικά: γενικοί τύποι δεδομένων, γενικές μέθοδοι, μονομορφοποίηση και " +#~ "χαρακτηριστικό\n" +#~ " αντικείμενα." + +#, fuzzy +#~ msgid "* Error handling: panics, `Result`, and the try operator `?`." +#~ msgstr "" +#~ "* Διαχείριση σφαλμάτων: πανικός, «Αποτέλεσμα» και ο τελεστής δοκιμής «?»." + +#, fuzzy +#~ msgid "* Testing: unit tests, documentation tests, and integration tests." +#~ msgstr "" +#~ "* Δοκιμές: δοκιμές μονάδων, δοκιμές τεκμηρίωσης και δοκιμές ολοκλήρωσης." + +#, fuzzy +#~ msgid "" +#~ "* Unsafe Rust: raw pointers, static variables, unsafe functions, and " +#~ "extern\n" +#~ " functions." +#~ msgstr "" +#~ "* Μη ασφαλής σκουριά: ακατέργαστες δείκτες, στατικές μεταβλητές, μη " +#~ "ασφαλείς συναρτήσεις και εξωτερικά\n" +#~ " λειτουργίες." + +#, fuzzy +#~ msgid "" +#~ "struct Dog {\n" +#~ " name: String,\n" +#~ "}" +#~ msgstr "" +#~ "struct Dog {\n" +#~ " όνομα: String,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Equals for Centimeter {\n" +#~ " fn equal(&self, other: &Centimeter) -> bool {\n" +#~ " self.0 == other.0\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Ισούται με εκατοστό {\n" +#~ " fn ίσον(&self, other: &Centimeter) -> bool {\n" +#~ " εαυτός.0 == άλλος.0\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "* `IntoIterator` is the trait that makes for loops work. It is " +#~ "implemented by collection types such as\n" +#~ " `Vec` and references to them such as `&Vec` and `&[T]`. Ranges " +#~ "also implement it.\n" +#~ "* The `Iterator` trait implements many common functional programming " +#~ "operations over collections \n" +#~ " (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can " +#~ "find all the documentation\n" +#~ " about them. In Rust these functions should produce the code as " +#~ "efficient as equivalent imperative\n" +#~ " implementations.\n" +#~ " \n" +#~ "
" +#~ msgstr "" +#~ "* Το \"IntoIterator\" είναι το χαρακτηριστικό που κάνει τους βρόχους να " +#~ "λειτουργούν. Υλοποιείται από τύπους συλλογής όπως π.χ\n" +#~ " `Vec` και αναφορές σε αυτά, όπως \"&Vec\" και \"&[T]\". Το " +#~ "εφαρμόζουν και οι Ranges.\n" +#~ "* Το χαρακτηριστικό «Iterator» υλοποιεί πολλές κοινές λειτουργίες " +#~ "λειτουργικού προγραμματισμού σε συλλογές\n" +#~ " (π.χ. \"χάρτης\", \"φίλτρο\", \"μείωση\" κ.λπ.). Αυτό είναι το " +#~ "χαρακτηριστικό όπου μπορείτε να βρείτε όλη την τεκμηρίωση\n" +#~ " Για αυτούς. Στο Rust αυτές οι συναρτήσεις θα πρέπει να παράγουν τον " +#~ "κώδικα τόσο αποτελεσματικό όσο και ισοδύναμη επιταγή\n" +#~ " υλοποιήσεις.\n" +#~ " \n" +#~ "
" + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/iter/trait.Iterator.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/iter/trait.FromIterator.html\n" +#~ "[2]: https://doc.rust-lang.org/std/iter/trait.Iterator.html" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" +#~ "[2]: https://doc.rust-lang.org/std/convert/trait.Into.html" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/io/trait.Read.html\n" +#~ "[2]: https://doc.rust-lang.org/std/io/trait.BufRead.html\n" +#~ "[3]: https://doc.rust-lang.org/std/io/trait.Write.html" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-" +#~ "Mutex%3CT%3E\n" +#~ "[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" + +#, fuzzy +#~ msgid "" +#~ " fn add(self, other: Self) -> Self {\n" +#~ " Self {x: self.x + other.x, y: self.y + other.y}\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " fn add(self, other: Self) -> Self {\n" +#~ " Self {x: self.x + other.x, y: self.y + other.y}\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/ops/index.html" +#~ msgstr "[`Οποιοδήποτε`]: https://doc.rust-lang.org/std/any/index.html" + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/ops/trait.Drop.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" + +#, fuzzy +#~ msgid "" +#~ "impl Default for Implemented {\n" +#~ " fn default() -> Self {\n" +#~ " Self(\"John Smith\".into())\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Widget για παράθυρο {\n" +#~ " fn width(&self) -> use {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/default/trait.Default.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" + +#, fuzzy +#~ msgid "" +#~ "impl Point {\n" +#~ " fn x(&self) -> &T {\n" +#~ " &self.0 // + 10\n" +#~ " }" +#~ msgstr "" +#~ "impl Σημείο {\n" +#~ " fn x(&self) -> &T {\n" +#~ " &self.0 // + 10\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // fn set_x(&mut self, x: T)\n" +#~ "}" +#~ msgstr "" +#~ " // fn set_x(&mut self, x: T)\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "fn get_x(name: impl Display) -> impl Display {\n" +#~ " format!(\"Hello {name}\")\n" +#~ "}" +#~ msgstr "" +#~ "fn get_x(name: impl Display) -> impl Display {\n" +#~ " μορφή! (\"Hello {name}\")\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "enum Option_f64 {\n" +#~ " Some(f64),\n" +#~ " None,\n" +#~ "}" +#~ msgstr "" +#~ "enum Option_f64 {\n" +#~ " Μερικοί (f64),\n" +#~ " Κανένας,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Label {\n" +#~ " label: String,\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Label {\n" +#~ " Ετικέτα: String,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Label {\n" +#~ " fn new(label: &str) -> Label {\n" +#~ " Label {\n" +#~ " label: label.to_owned(),\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Label {\n" +#~ " fn new(label: &str) -> Label {\n" +#~ " Ετικέτα {\n" +#~ " label: label.to_owned(),\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Button {\n" +#~ " label: Label,\n" +#~ " callback: Box,\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Κουμπί {\n" +#~ " ετικέτα: ετικέτα,\n" +#~ " επανάκληση: Box,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Button {\n" +#~ " fn new(label: &str, callback: Box) -> Button {\n" +#~ " Button {\n" +#~ " label: Label::new(label),\n" +#~ " callback,\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "Κουμπί εμφύτευσης {\n" +#~ " fn new(label: &str, callback: Box) -> Button {\n" +#~ " Κουμπί {\n" +#~ " ετικέτα: Ετικέτα::νέο(ετικέτα),\n" +#~ " επανάκληση,\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "pub struct Window {\n" +#~ " title: String,\n" +#~ " widgets: Vec>,\n" +#~ "}" +#~ msgstr "" +#~ "pub struct Παράθυρο {\n" +#~ " τίτλος: String,\n" +#~ " widgets: Vec>,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Window {\n" +#~ " fn new(title: &str) -> Window {\n" +#~ " Window {\n" +#~ " title: title.to_owned(),\n" +#~ " widgets: Vec::new(),\n" +#~ " }\n" +#~ " }" +#~ msgstr "" +#~ "παράθυρο εμφ. {\n" +#~ " fn new(title: &str) -> Παράθυρο {\n" +#~ " Παράθυρο {\n" +#~ " title: title.to_owned(),\n" +#~ " widgets: Vec::new(),\n" +#~ " }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "impl Widget for Label {\n" +#~ " fn width(&self) -> usize {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl Widget για ετικέτα {\n" +#~ " fn width(&self) -> use {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +#~ " unimplemented!()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Widget for Button {\n" +#~ " fn width(&self) -> usize {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl Widget for Button {\n" +#~ " fn width(&self) -> use {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "impl Widget for Window {\n" +#~ " fn width(&self) -> usize {\n" +#~ " unimplemented!()\n" +#~ " }" +#~ msgstr "" +#~ "impl Widget για παράθυρο {\n" +#~ " fn width(&self) -> use {\n" +#~ " ανεφάρμοστη!()\n" +#~ " }" + +#, fuzzy +#~ msgid "This is a small text GUI demo." +#~ msgstr "Αυτό είναι ένα μικρό κείμενο επίδειξης GUI." + +#, fuzzy +#~ msgid "" +#~ " match username_file.read_to_string(&mut username) {\n" +#~ " Ok(_) => Ok(username),\n" +#~ " Err(e) => Err(e),\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " αντιστοίχιση username_file.read_to_string(&mut username) {\n" +#~ " Ok(_) => Ok(όνομα χρήστη),\n" +#~ " Σφάλμα(ε) => Σφάλμα(ε),\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug)]\n" +#~ "enum ReadUsernameError {\n" +#~ " IoError(io::Error),\n" +#~ " EmptyUsername(String),\n" +#~ "}" +#~ msgstr "" +#~ "#[παραγωγή (Εντοπισμός σφαλμάτων)]\n" +#~ "enum ReadUsernameError {\n" +#~ " IoError(io::Error),\n" +#~ " EmptyUsername(String),\n" +#~ "}" + +#, fuzzy +#~ msgid "impl Error for ReadUsernameError {}" +#~ msgstr "impl Σφάλμα για ReadUsernameError {}" + +#, fuzzy +#~ msgid "" +#~ "impl Display for ReadUsernameError {\n" +#~ " fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" +#~ " match self {\n" +#~ " Self::IoError(e) => write!(f, \"IO error: {}\", e),\n" +#~ " Self::EmptyUsername(filename) => write!(f, \"Found no " +#~ "username in {}\", filename),\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Εμφάνιση για ReadUsernameError {\n" +#~ " fn fmt(&self, f: &mut Formatter) -> fmt::Αποτέλεσμα {\n" +#~ " ταίριασμα εαυτού {\n" +#~ " Self::IoError(e) => write!(f, \"IO error: {}\", e),\n" +#~ " Self::EmptyUsername(filename) => write!(f, \"Δεν βρέθηκε " +#~ "όνομα χρήστη στο {}\", όνομα αρχείου),\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl From for ReadUsernameError {\n" +#~ " fn from(err: io::Error) -> ReadUsernameError {\n" +#~ " ReadUsernameError::IoError(err)\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl From για ReadUsernameError {\n" +#~ " fn from(err: io::Error) -> ReadUsernameError {\n" +#~ " ReadUsernameError::IoError(err)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug, Error)]\n" +#~ "enum ReadUsernameError {\n" +#~ " #[error(\"Could not read: {0}\")]\n" +#~ " IoError(#[from] io::Error),\n" +#~ " #[error(\"Found no username in {0}\")]\n" +#~ " EmptyUsername(String),\n" +#~ "}" +#~ msgstr "" +#~ "#[παραγωγή (Εντοπισμός σφαλμάτων, Σφάλμα)]\n" +#~ "enum ReadUsernameError {\n" +#~ " #[σφάλμα (\"Δεν ήταν δυνατή η ανάγνωση: {0}\")]\n" +#~ " IoError(#[from] io::Error),\n" +#~ " #[error(\"Δεν βρέθηκε όνομα χρήστη στο {0}\")]\n" +#~ " EmptyUsername(String),\n" +#~ "}" + +#, fuzzy +#~ msgid "* Unit tests are supported throughout your code." +#~ msgstr "* Οι δοκιμές μονάδας υποστηρίζονται σε όλο τον κώδικά σας." + +#, fuzzy +#~ msgid "[solution]: solutions-afternoon.md" +#~ msgstr "[λύση]: λύσεις-απόγευμα.μδ" + +#, fuzzy +#~ msgid "" +#~ "[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" +#~ "[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" +#~ "[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" +#~ "[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" +#~ msgstr "" +#~ "[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" +#~ "[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" +#~ "[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" +#~ "[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug)]\n" +#~ "struct DirectoryIterator {\n" +#~ " path: CString,\n" +#~ " dir: *mut ffi::DIR,\n" +#~ "}" +#~ msgstr "" +#~ "#[παραγωγή (Εντοπισμός σφαλμάτων)]\n" +#~ "struct DirectoryIterator {\n" +#~ " διαδρομή: CString,\n" +#~ " σκηνοθεσία: *mut ffi::DIR,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl DirectoryIterator {\n" +#~ " fn new(path: &str) -> Result {\n" +#~ " // Call opendir and return a Ok value if that worked,\n" +#~ " // otherwise return Err with a message.\n" +#~ " unimplemented!()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl DirectoryIterator {\n" +#~ " fn new(διαδρομή: &str) -> Αποτέλεσμα {\n" +#~ " // Καλέστε το opendir και επιστρέψτε μια τιμή Ok εάν " +#~ "λειτούργησε,\n" +#~ " // διαφορετικά επιστρέψτε το Err με ένα μήνυμα.\n" +#~ " ανεφάρμοστη!()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Drop for DirectoryIterator {\n" +#~ " fn drop(&mut self) {\n" +#~ " // Call closedir as needed.\n" +#~ " unimplemented!()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl Drop for DirectoryIterator {\n" +#~ " fn drop(&mut self) {\n" +#~ " // Καλέστε το κλείσιμο όπως απαιτείται.\n" +#~ " ανεφάρμοστη!()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "Today we will look at two main topics:" +#~ msgstr "Σήμερα θα εξετάσουμε δύο βασικά θέματα:" + +#, fuzzy +#~ msgid "* Concurrency: threads, channels, shared state, `Send` and `Sync`." +#~ msgstr "" +#~ "* Συγχρονισμός: νήματα, κανάλια, κοινή κατάσταση, \"Αποστολή\" και " +#~ "\"Συγχρονισμός\"." + +#, fuzzy +#~ msgid "" +#~ "* Android: building binaries and libraries, using AIDL, logging, and\n" +#~ " interoperability with C, C++, and Java." +#~ msgstr "" +#~ "* Android: δημιουργία δυαδικών αρχείων και βιβλιοθηκών, χρησιμοποιώντας " +#~ "AIDL, καταγραφή και\n" +#~ " διαλειτουργικότητα με C, C++ και Java." + +#, fuzzy +#~ msgid "" +#~ "* Notice that the thread is stopped before it reaches 10 — the main " +#~ "thread is\n" +#~ " not waiting." +#~ msgstr "" +#~ "* Παρατηρήστε ότι το νήμα σταματά πριν φτάσει στο 10 — το κύριο νήμα " +#~ "είναι\n" +#~ " δεν περιμένει." + +#, fuzzy +#~ msgid "" +#~ "* Use `let handle = thread::spawn(...)` and later `handle.join()` to wait " +#~ "for\n" +#~ " the thread to finish." +#~ msgstr "" +#~ "* Χρησιμοποιήστε το \"let handle = thread::spawn(...)\" και αργότερα το " +#~ "\"handle.join()\" για να περιμένετε\n" +#~ " το νήμα για να τελειώσει." + +#, fuzzy +#~ msgid "" +#~ "* Trigger a panic in the thread, notice how this doesn't affect `main`." +#~ msgstr "" +#~ "* Προκαλέστε έναν πανικό στο νήμα, παρατηρήστε πώς αυτό δεν επηρεάζει το " +#~ "\"κύριο\"." + +#, fuzzy +#~ msgid "" +#~ "* 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 "" +#~ "* Χρησιμοποιήστε την τιμή επιστροφής \"Αποτέλεσμα\" από το \"handle." +#~ "join()\" για να αποκτήσετε πρόσβαση στον πανικό\n" +#~ " φορτίο επί πληρωμή. Αυτή είναι μια καλή στιγμή για να μιλήσουμε για το " +#~ "[`Οποιοδήποτε`]." + +#, fuzzy +#~ msgid "[`Any`]: https://doc.rust-lang.org/std/any/index.html" +#~ msgstr "[`Οποιοδήποτε`]: https://doc.rust-lang.org/std/any/index.html" + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-" +#~ "Mutex%3CT%3E\n" +#~ "[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" +#~ "[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-" +#~ "Mutex%3CT%3E\n" +#~ "[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" + +#, fuzzy +#~ msgid "" +#~ "[`PoisonError`]: https://doc.rust-lang.org/std/sync/struct.PoisonError." +#~ "html \n" +#~ " \n" +#~ "" +#~ msgstr "" +#~ "[\"PoisonError\"]: https://doc.rust-lang.org/std/sync/struct.PoisonError." +#~ "html\n" +#~ " \n" +#~ "" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" +#~ "[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html\n" +#~ "[3]: ../unsafe/unsafe-traits.md" +#~ msgstr "" +#~ "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" +#~ "[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html\n" +#~ "[3]: ../unsafe/unsafe-traits.md" + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Sync.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Sync.html" + +#, fuzzy +#~ msgid "* Dining philosophers: a classic problem in concurrency." +#~ msgstr "* Φιλόσοφοι τραπεζαρίας: ένα κλασικό πρόβλημα συγχρονισμού." + +#, fuzzy +#~ msgid "" +#~ "struct Philosopher {\n" +#~ " name: String,\n" +#~ " // left_fork: ...\n" +#~ " // right_fork: ...\n" +#~ " // thoughts: ...\n" +#~ "}" +#~ msgstr "" +#~ "struct Φιλόσοφος {\n" +#~ " όνομα: String,\n" +#~ " // left_fork: ...\n" +#~ " // right_fork: ...\n" +#~ " // σκέψεις: ...\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "fn main() {\n" +#~ " // Create forks" +#~ msgstr "" +#~ "fn main() {\n" +#~ " // Δημιουργία πιρουνιών" + +#, fuzzy +#~ msgid " // Create philosophers" +#~ msgstr " // Δημιουργία φιλοσόφων" + +#, fuzzy +#~ msgid " // Make them think and eat" +#~ msgstr " // Κάνε τους να σκεφτούν και να φάνε" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Error, Debug)]\n" +#~ "enum Error {\n" +#~ " #[error(\"request error: {0}\")]\n" +#~ " ReqwestError(#[from] reqwest::Error),\n" +#~ "}" +#~ msgstr "" +#~ "#[παραγωγή (Σφάλμα, Εντοπισμός σφαλμάτων)]\n" +#~ "enum Σφάλμα {\n" +#~ " #[error(\"σφάλμα αιτήματος: {0}\")]\n" +#~ " ReqwestError(#[from] reqwest::Error),\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " Ok(valid_urls)\n" +#~ "}" +#~ msgstr "" +#~ " Ok(valid_urls)\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://docs.rs/reqwest/\n" +#~ "[2]: https://docs.rs/scraper/\n" +#~ "[3]: https://docs.rs/thiserror/" +#~ msgstr "" +#~ "[1]: https://docs.rs/reqwest/\n" +#~ "[2]: https://docs.rs/scraper/\n" +#~ "[3]: https://docs.rs/thiserror/" + +#, fuzzy +#~ msgid "" +#~ "[crates]: https://cs.android.com/android/platform/superproject/+/master:" +#~ "external/rust/crates/" +#~ msgstr "" +#~ "[κλουβιά]: https://cs.android.com/android/platform/superproject/+/master:" +#~ "external/rust/crates/" + +#, fuzzy +#~ msgid "impl binder::Interface for BirthdayService {}" +#~ msgstr "impl binder::Διεπαφή για BirthdayService {}" + +#, fuzzy +#~ msgid "" +#~ "/// Connect to the BirthdayService.\n" +#~ "pub fn connect() -> Result, binder::" +#~ "StatusCode> {\n" +#~ " binder::get_interface(SERVICE_IDENTIFIER)\n" +#~ "}" +#~ msgstr "" +#~ "/// Συνδεθείτε στην υπηρεσία BirthdayService.\n" +#~ "pub fn connect() -> Αποτέλεσμα, " +#~ "binder::StatusCode> {\n" +#~ " binder::get_interface(SERVICE_IDENTIFIER)\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "[1]: https://cxx.rs/\n" +#~ "[2]: https://cxx.rs/tutorial.html" +#~ msgstr "" +#~ "[1]: https://cxx.rs/\n" +#~ "[2]: https://cxx.rs/tutorial.html" + +#, fuzzy +#~ msgid "* Call your AIDL service with a client written in Rust." +#~ msgstr "* Καλέστε την υπηρεσία AIDL με έναν πελάτη γραμμένο σε Rust." + +#, fuzzy +#~ msgid "[1]: https://doc.rust-lang.org/std/convert/trait.AsRef.html" +#~ msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: setup\n" +#~ "struct Library {\n" +#~ " books: Vec,\n" +#~ "}" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: ρύθμιση\n" +#~ "struct Library {\n" +#~ " βιβλία: Vec,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// 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" +#~ msgstr "" +#~ "// Αυτό καθιστά δυνατή την εκτύπωση τιμών βιβλίου με {}.\n" +#~ "impl std::fmt::Display for Book {\n" +#~ " fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::" +#~ "Αποτέλεσμα {\n" +#~ " write!(f, \"{} ({})\", self.title, self.year)\n" +#~ " }\n" +#~ "}\n" +#~ "// ANCHOR_END: ρύθμιση" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Library_new\n" +#~ "impl Library {\n" +#~ " fn new() -> Library {\n" +#~ " // ANCHOR_END: Library_new\n" +#~ " Library { books: Vec::new() }\n" +#~ " }" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Library_new\n" +#~ "impl Library {\n" +#~ " fn new() -> Library {\n" +#~ " // ANCHOR_END: Library_new\n" +#~ " Βιβλιοθήκη { βιβλία: Vec::new() }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // ANCHOR: Library_len\n" +#~ " //fn len(self) -> usize {\n" +#~ " // unimplemented!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_len\n" +#~ " fn len(&self) -> usize {\n" +#~ " self.books.len()\n" +#~ " }" +#~ msgstr "" +#~ " // ΑΓΚΥΡΑ: Library_len\n" +#~ " //fn len(self) -> χρήση {\n" +#~ " // δεν εφαρμόζεται!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_len\n" +#~ " fn len(&self) -> χρήση {\n" +#~ " self.books.len()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // ANCHOR: Library_is_empty\n" +#~ " //fn is_empty(self) -> bool {\n" +#~ " // unimplemented!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_is_empty\n" +#~ " fn is_empty(&self) -> bool {\n" +#~ " self.books.is_empty()\n" +#~ " }" +#~ msgstr "" +#~ " // ANCHOR: Library_is_empty\n" +#~ " //fn is_empty(self) -> bool {\n" +#~ " // δεν εφαρμόζεται!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_is_empty\n" +#~ " fn is_empty(&self) -> bool {\n" +#~ " self.books.is_empty()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // ANCHOR: Library_add_book\n" +#~ " //fn add_book(self, book: Book) {\n" +#~ " // unimplemented!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_add_book\n" +#~ " fn add_book(&mut self, book: Book) {\n" +#~ " self.books.push(book)\n" +#~ " }" +#~ msgstr "" +#~ " // ANCHOR: Library_add_book\n" +#~ " //fn add_book(self, book: Book) {\n" +#~ " // δεν εφαρμόζεται!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_add_book\n" +#~ " fn add_book(&mut self, book: Book) {\n" +#~ " self.books.push(βιβλίο)\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " // ANCHOR: Library_oldest_book\n" +#~ " //fn oldest_book(self) -> Option<&Book> {\n" +#~ " // unimplemented!()\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" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " // ANCHOR: Library_oldest_book\n" +#~ " //fn oldest_book(self) -> Option<&Book> {\n" +#~ " // δεν εφαρμόζεται!()\n" +#~ " //}\n" +#~ " // ANCHOR_END: Library_oldest_book\n" +#~ " fn oldest_book(&self) -> Option<&Book> {\n" +#~ " self.books.iter().min_by_key(|βιβλίο| βιβλίο.έτος)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" +#~ "// ANCHOR: Point\n" +#~ "pub struct Point {\n" +#~ " // ANCHOR_END: Point\n" +#~ " x: i32,\n" +#~ " y: i32,\n" +#~ "}" +#~ msgstr "" +#~ "#[παραγωγή (Εντοπισμός σφαλμάτων, Αντιγραφή, Κλώνος, PartialEq, Eq)]\n" +#~ "// Αγκυροβόλι\n" +#~ "pub struct Point {\n" +#~ " // ANCHOR_END: Σημείο\n" +#~ " x: i32,\n" +#~ " y: i32,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Point-impl\n" +#~ "impl Point {\n" +#~ " // ANCHOR_END: Point-impl\n" +#~ " pub fn new(x: i32, y: i32) -> Point {\n" +#~ " Point { x, y }\n" +#~ " }" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Point-immpl\n" +#~ "εμφ. Σημείο {\n" +#~ " // ANCHOR_END: Point-immpl\n" +#~ " pub fn new(x: i32, y: i32) -> Point {\n" +#~ " Σημείο { x, y }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn magnitude(self) -> f64 {\n" +#~ " f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn magnitude(self) -> f64 {\n" +#~ " f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn dist(self, other: Point) -> f64 {\n" +#~ " (self - other).magnitude()\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " pub fn dist(self, other: Point) -> f64 {\n" +#~ " (self - other).magnitude()\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " fn add(self, other: Self) -> Self::Output {\n" +#~ " Self {\n" +#~ " x: self.x + other.x,\n" +#~ " y: self.y + other.y,\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " fn add(self, other: Self) -> Self::Output {\n" +#~ " αυτος {\n" +#~ " x: self.x + other.x,\n" +#~ " y: self.y + other.y,\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " fn sub(self, other: Self) -> Self::Output {\n" +#~ " Self {\n" +#~ " x: self.x - other.x,\n" +#~ " y: self.y - other.y,\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " fn sub(self, other: Self) -> Self::Output {\n" +#~ " αυτος {\n" +#~ " x: εαυτός.χ - άλλος.χ,\n" +#~ " y: self.y - other.y,\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Polygon\n" +#~ "pub struct Polygon {\n" +#~ " // ANCHOR_END: Polygon\n" +#~ " points: Vec,\n" +#~ "}" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Πολύγωνο\n" +#~ "pub struct Πολύγωνο {\n" +#~ " // ANCHOR_END: Πολύγωνο\n" +#~ " σημεία: Vec,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Polygon-impl\n" +#~ "impl Polygon {\n" +#~ " // ANCHOR_END: Polygon-impl\n" +#~ " pub fn new() -> Polygon {\n" +#~ " Polygon { points: Vec::new() }\n" +#~ " }" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Polygon-impl\n" +#~ "impmpl Polygon {\n" +#~ " // ANCHOR_END: Polygon-impl\n" +#~ " pub fn new() -> Πολύγωνο {\n" +#~ " Πολύγωνο { points: Vec::new() }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn left_most_point(&self) -> Option {\n" +#~ " self.points.iter().min_by_key(|p| p.x).copied()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn left_most_point(&self) -> Option {\n" +#~ " self.points.iter().min_by_key(|p| p.x).copied()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn iter(&self) -> impl Iterator {\n" +#~ " self.points.iter()\n" +#~ " }" +#~ msgstr "" +#~ " pub fn iter(&self) -> impl Iterator {\n" +#~ " self.points.iter()\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Circle\n" +#~ "pub struct Circle {\n" +#~ " // ANCHOR_END: Circle\n" +#~ " center: Point,\n" +#~ " radius: i32,\n" +#~ "}" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Κύκλος\n" +#~ "pub struct Circle {\n" +#~ " // ANCHOR_END: Κύκλος\n" +#~ " κεντρικό σημείο,\n" +#~ " ακτίνα: i32,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Circle-impl\n" +#~ "impl Circle {\n" +#~ " // ANCHOR_END: Circle-impl\n" +#~ " pub fn new(center: Point, radius: i32) -> Circle {\n" +#~ " Circle { center, radius }\n" +#~ " }" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Circle-immpl\n" +#~ "impmpl Circle {\n" +#~ " // ANCHOR_END: Circle-impl\n" +#~ " pub fn new(κέντρο: Σημείο, ακτίνα: i32) -> Κύκλος {\n" +#~ " Κύκλος { κέντρο, ακτίνα }\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn circumference(&self) -> f64 {\n" +#~ " 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +#~ " }" +#~ msgstr "" +#~ " pub fn circumference(&self) -> f64 {\n" +#~ " 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ " pub fn dist(&self, other: &Self) -> f64 {\n" +#~ " self.center.dist(other.center)\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ " pub fn dist(&self, other: &Self) -> f64 {\n" +#~ " self.center.dist(other.center)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Shape\n" +#~ "pub enum Shape {\n" +#~ " Polygon(Polygon),\n" +#~ " Circle(Circle),\n" +#~ "}\n" +#~ "// ANCHOR_END: Shape" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Σχήμα\n" +#~ "pub enum Shape {\n" +#~ " Πολύγωνο (Πολύγωνο),\n" +#~ " Κύκλος (Κύκλος),\n" +#~ "}\n" +#~ "// ANCHOR_END: Σχήμα" + +#, fuzzy +#~ msgid "" +#~ "impl From for Shape {\n" +#~ " fn from(poly: Polygon) -> Self {\n" +#~ " Shape::Polygon(poly)\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl From for Shape {\n" +#~ " fn from(poly: Polygon) -> Self {\n" +#~ " Σχήμα::Πολύγωνο(πολύγωνο)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl From for Shape {\n" +#~ " fn from(circle: Circle) -> Self {\n" +#~ " Shape::Circle(circle)\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impl From for Shape {\n" +#~ " fn from(circle: Circle) -> Self {\n" +#~ " Σχήμα::Κύκλος (κύκλος)\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "impl Shape {\n" +#~ " pub fn perimeter(&self) -> f64 {\n" +#~ " match self {\n" +#~ " Shape::Polygon(poly) => poly.length(),\n" +#~ " Shape::Circle(circle) => circle.circumference(),\n" +#~ " }\n" +#~ " }\n" +#~ "}" +#~ msgstr "" +#~ "impmpl Shape {\n" +#~ " pub fn perimeter(&self) -> f64 {\n" +#~ " ταίριασμα εαυτού {\n" +#~ " Shape::Polygon(poly) => poly.length(),\n" +#~ " Σχήμα::Κύκλος(κύκλος) => κύκλος.περιφέρεια(),\n" +#~ " }\n" +#~ " }\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ " sum % 10 == 0\n" +#~ "}" +#~ msgstr "" +#~ " άθροισμα % 10 == 0\n" +#~ "}" + +#, fuzzy +#~ msgid "// ANCHOR_END: setup" +#~ msgstr "// ANCHOR_END: ρύθμιση" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Window-width\n" +#~ "impl Widget for Window {\n" +#~ " fn width(&self) -> usize {\n" +#~ " // ANCHOR_END: Window-width\n" +#~ " std::cmp::max(\n" +#~ " self.title.chars().count(),\n" +#~ " self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +#~ " )\n" +#~ " }" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Παράθυρο-πλάτος\n" +#~ "impl Widget για παράθυρο {\n" +#~ " fn width(&self) -> use {\n" +#~ " // ANCHOR_END: Παράθυρο-πλάτος\n" +#~ " std::cmp::max(\n" +#~ " self.title.chars().count(),\n" +#~ " self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +#~ " )\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Button-width\n" +#~ "impl Widget for Button {\n" +#~ " fn width(&self) -> usize {\n" +#~ " // ANCHOR_END: Button-width\n" +#~ " self.label.width() + 8 // add a bit of padding\n" +#~ " }" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Κουμπί-πλάτος\n" +#~ "impl Widget for Button {\n" +#~ " fn width(&self) -> use {\n" +#~ " // ANCHOR_END: Κουμπί-πλάτος\n" +#~ " self.label.width() + 8 // προσθέστε λίγο padding\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "// ANCHOR: Label-width\n" +#~ "impl Widget for Label {\n" +#~ " fn width(&self) -> usize {\n" +#~ " // ANCHOR_END: Label-width\n" +#~ " self.label\n" +#~ " .lines()\n" +#~ " .map(|line| line.chars().count())\n" +#~ " .max()\n" +#~ " .unwrap_or(0)\n" +#~ " }" +#~ msgstr "" +#~ "// ΑΓΚΥΡΑ: Label-width\n" +#~ "impl Widget για ετικέτα {\n" +#~ " fn width(&self) -> use {\n" +#~ " // ANCHOR_END: Ετικέτα-πλάτος\n" +#~ " αυτο.ετικέτα\n" +#~ " .lines()\n" +#~ " .map(|line| line.chars().count())\n" +#~ " .Μέγιστη()\n" +#~ " .unwrap_or(0)\n" +#~ " }" + +#, fuzzy +#~ msgid "" +#~ "#[derive(Debug)]\n" +#~ "struct DirectoryIterator {\n" +#~ " path: CString,\n" +#~ " dir: *mut ffi::DIR,\n" +#~ "}\n" +#~ "// ANCHOR_END: ffi" +#~ msgstr "" +#~ "#[παραγωγή (Εντοπισμός σφαλμάτων)]\n" +#~ "struct DirectoryIterator {\n" +#~ " διαδρομή: CString,\n" +#~ " σκηνοθεσία: *mut ffi::DIR,\n" +#~ "}\n" +#~ "// ANCHOR_END: ffi" + +#, fuzzy +#~ msgid "" +#~ "struct Philosopher {\n" +#~ " name: String,\n" +#~ " // ANCHOR_END: Philosopher\n" +#~ " left_fork: Arc>,\n" +#~ " right_fork: Arc>,\n" +#~ " thoughts: mpsc::SyncSender,\n" +#~ "}" +#~ msgstr "" +#~ "struct Φιλόσοφος {\n" +#~ " όνομα: String,\n" +#~ " // ANCHOR_END: Φιλόσοφος\n" +#~ " left_fork: Arc>,\n" +#~ " right_fork: Arc>,\n" +#~ " σκέψεις: mpsc::SyncSender,\n" +#~ "}" + +#, fuzzy +#~ msgid "" +#~ "* `Box` is like `std::unique_ptr` in C++.\n" +#~ "* In the above example, you can even leave out the `*` in the `println!` " +#~ "statement thanks to `Deref`." +#~ msgstr "" +#~ "* Το \"Box\" είναι σαν το \"std::unique_ptr\" στη C++.\n" +#~ "* Στο παραπάνω παράδειγμα, μπορείτε ακόμη και να αφήσετε έξω το «*» στη " +#~ "δήλωση «println!» χάρη στο «Deref»." diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..985dda6 --- /dev/null +++ b/po/es.po @@ -0,0 +1,14068 @@ +msgid "" +msgstr "" +"Project-Id-Version: Comprehensive Rust 🦀\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2023-03-31 17:10+0200\n" +"Last-Translator: Walter Javier Franck \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.2.2\n" + +#: src/SUMMARY.md:3 +msgid "Welcome to Comprehensive Rust 🦀" +msgstr "Bienvenido a Comprehensive Rust 🦀" + +#: src/SUMMARY.md:4 +msgid "Running the Course" +msgstr "Seguir el Curso" + +#: src/SUMMARY.md:5 +msgid "Course Structure" +msgstr "Estructura del Curso" + +#: src/SUMMARY.md:6 +msgid "Keyboard Shortcuts" +msgstr "Accesos Rápidos del Teclado" + +#: src/SUMMARY.md:7 +msgid "Translations" +msgstr "Traducciones" + +#: src/SUMMARY.md:8 +msgid "Using Cargo" +msgstr "Usando Cargo" + +#: src/SUMMARY.md:9 +msgid "Rust Ecosystem" +msgstr "Ecosistema Rust" + +#: src/SUMMARY.md:10 +msgid "Code Samples" +msgstr "Ejemplos de Código" + +#: src/SUMMARY.md:11 +msgid "Running Cargo Locally" +msgstr "Correr Cargo Localmente" + +#: src/SUMMARY.md:14 +msgid "Day 1: Morning" +msgstr "Día 1: Mañana" + +#: src/SUMMARY.md:18 src/SUMMARY.md:74 src/SUMMARY.md:127 src/SUMMARY.md:183 +msgid "Welcome" +msgstr "Bienvenido" + +#: src/SUMMARY.md:19 +msgid "What is Rust?" +msgstr "¿Qué es Rust?" + +#: src/SUMMARY.md:20 +msgid "Hello World!" +msgstr "¡Hola Mundo!" + +#: src/SUMMARY.md:21 +msgid "Small Example" +msgstr "Ejemplo Rápido" + +#: src/SUMMARY.md:22 +msgid "Why Rust?" +msgstr "¿Por qué Rust?" + +#: src/SUMMARY.md:23 +msgid "Compile Time Guarantees" +msgstr "Tiempo de Compilación Garantizado" + +#: src/SUMMARY.md:24 +msgid "Runtime Guarantees" +msgstr "Garantías en Tiempo de Ejecución" + +#: src/SUMMARY.md:25 +msgid "Modern Features" +msgstr "Características Modernas" + +#: src/SUMMARY.md:26 +msgid "Basic Syntax" +msgstr "Sintaxis Básica" + +#: src/SUMMARY.md:27 +msgid "Scalar Types" +msgstr "Tipos Escalares" + +#: src/SUMMARY.md:28 +msgid "Compound Types" +msgstr "Tipos Compuestos" + +#: src/SUMMARY.md:29 +msgid "References" +msgstr "Referencias" + +#: src/SUMMARY.md:30 +msgid "Dangling References" +msgstr "Referencias Colgantes" + +#: src/SUMMARY.md:31 +msgid "Slices" +msgstr "Slices" + +#: src/SUMMARY.md:32 +msgid "String vs str" +msgstr "" + +#: src/SUMMARY.md:33 +msgid "Functions" +msgstr "Funciones" + +#: src/SUMMARY.md:34 src/SUMMARY.md:81 +msgid "Methods" +msgstr "Métodos" + +#: src/SUMMARY.md:35 +msgid "Overloading" +msgstr "Sobrecarga" + +#: src/SUMMARY.md:36 src/SUMMARY.md:65 src/SUMMARY.md:89 src/SUMMARY.md:118 src/SUMMARY.md:147 +#: src/SUMMARY.md:175 src/SUMMARY.md:198 src/SUMMARY.md:225 +msgid "Exercises" +msgstr "Ejercicios" + +#: src/SUMMARY.md:37 +msgid "Implicit Conversions" +msgstr "Conversiones Implícitas" + +#: src/SUMMARY.md:38 +msgid "Arrays and for Loops" +msgstr "Arrays y Loops for" + +#: src/SUMMARY.md:40 +msgid "Day 1: Afternoon" +msgstr "Día 1: Tarde" + +#: src/SUMMARY.md:42 +msgid "Variables" +msgstr "Variables" + +#: src/SUMMARY.md:43 +msgid "Type Inference" +msgstr "Infererencia de Tipo" + +#: src/SUMMARY.md:44 +msgid "static & const" +msgstr "static & const" + +#: src/SUMMARY.md:45 +msgid "Scopes and Shadowing" +msgstr "Scopes y Shadowing" + +#: src/SUMMARY.md:46 +msgid "Memory Management" +msgstr "Manejo de Memoria" + +#: src/SUMMARY.md:47 +msgid "Stack vs Heap" +msgstr "" + +#: src/SUMMARY.md:48 +msgid "Stack Memory" +msgstr "Stack de Memoria" + +#: src/SUMMARY.md:49 +msgid "Manual Memory Management" +msgstr "Manejo Manual de Memoria" + +#: src/SUMMARY.md:50 +msgid "Scope-Based Memory Management" +msgstr "Manejo de Memoria basado en Scope (ámbitos)" + +#: src/SUMMARY.md:51 +msgid "Garbage Collection" +msgstr "" + +#: src/SUMMARY.md:52 +msgid "Rust Memory Management" +msgstr "Manejo de la Memoria en Rust" + +#: src/SUMMARY.md:53 +msgid "Comparison" +msgstr "Comparación" + +#: src/SUMMARY.md:54 +msgid "Ownership" +msgstr "Ownership (dueño)" + +#: src/SUMMARY.md:55 +msgid "Move Semantics" +msgstr "Semantica de Transferencia" + +#: src/SUMMARY.md:56 +msgid "Moved Strings in Rust" +msgstr "Mover Strings en Rust" + +#: src/SUMMARY.md:57 +msgid "Double Frees in Modern C++" +msgstr "Frees Dobles en C++ Moderno" + +#: src/SUMMARY.md:58 +msgid "Moves in Function Calls" +msgstr "Transferencia de Objetos en Llamadas de Funciones" + +#: src/SUMMARY.md:59 +msgid "Copying and Cloning" +msgstr "Copiar y Clonar" + +#: src/SUMMARY.md:60 +msgid "Borrowing" +msgstr "Préstamos (Referencias)" + +#: src/SUMMARY.md:61 +msgid "Shared and Unique Borrows" +msgstr "Préstamos Compartidos y Únicos (Referencias)" + +#: src/SUMMARY.md:62 +msgid "Lifetimes" +msgstr "Tiempo de Vida" + +#: src/SUMMARY.md:63 +msgid "Lifetimes in Function Calls" +msgstr "Tiempo de Vida en Llamadas de Funciones" + +#: src/SUMMARY.md:64 +msgid "Lifetimes in Data Structures" +msgstr "Tiempo de Vida de Estructuras de Datos" + +#: src/SUMMARY.md:66 +msgid "Designing a Library" +msgstr "Diseñando una Librería" + +#: src/SUMMARY.md:67 +msgid "Iterators and Ownership" +msgstr "Iteradores y Ownership" + +#: src/SUMMARY.md:70 +msgid "Day 2: Morning" +msgstr "Día 2: Mañana" + +#: src/SUMMARY.md:75 +msgid "Structs" +msgstr "" + +#: src/SUMMARY.md:76 +msgid "Tuple Structs" +msgstr "Estructuras de Tuplas" + +#: src/SUMMARY.md:77 +msgid "Field Shorthand Syntax" +msgstr "Sintaxis Abreviada de Campos" + +#: src/SUMMARY.md:78 +msgid "Enums" +msgstr "" + +#: src/SUMMARY.md:79 +msgid "Variant Payloads" +msgstr "Payloads Variantes" + +#: src/SUMMARY.md:80 +msgid "Enum Sizes" +msgstr "Tamaños de Enum" + +#: src/SUMMARY.md:82 +msgid "Method Receiver" +msgstr "Método Receptor" + +#: src/SUMMARY.md:83 src/SUMMARY.md:158 src/SUMMARY.md:193 +msgid "Example" +msgstr "Ejemplo" + +#: src/SUMMARY.md:84 +msgid "Pattern Matching" +msgstr "Correspondencia de Patrones" + +#: src/SUMMARY.md:85 +msgid "Destructuring Enums" +msgstr "Desestructurando Enums" + +#: src/SUMMARY.md:86 +msgid "Destructuring Structs" +msgstr "Desestructurando Structs" + +#: src/SUMMARY.md:87 +msgid "Destructuring Arrays" +msgstr "Desestructurando Arrays" + +#: src/SUMMARY.md:88 +msgid "Match Guards" +msgstr "Guardas de Match" + +#: src/SUMMARY.md:90 +msgid "Health Statistics" +msgstr "Estadísticas de Estado de Salud" + +#: src/SUMMARY.md:91 +msgid "Points and Polygons" +msgstr "Puntos y Polígonos" + +#: src/SUMMARY.md:93 +msgid "Day 2: Afternoon" +msgstr "Día 2: Tarde" + +#: src/SUMMARY.md:95 +msgid "Control Flow" +msgstr "Control de Flujo" + +#: src/SUMMARY.md:96 +msgid "Blocks" +msgstr "Bloques" + +#: src/SUMMARY.md:97 +msgid "if expressions" +msgstr "expresiones if" + +#: src/SUMMARY.md:98 +msgid "if let expressions" +msgstr "expresiones if let" + +#: src/SUMMARY.md:99 +msgid "while expressions" +msgstr "expresiones while" + +#: src/SUMMARY.md:100 +msgid "while let expressions" +msgstr "expresiones while let" + +#: src/SUMMARY.md:101 +msgid "for expressions" +msgstr "expresiones for" + +#: src/SUMMARY.md:102 +msgid "loop expressions" +msgstr "expresiones loop" + +#: src/SUMMARY.md:103 +msgid "match expressions" +msgstr "expresiones match" + +#: src/SUMMARY.md:104 +msgid "break & continue" +msgstr "break y continue" + +#: src/SUMMARY.md:105 +msgid "Standard Library" +msgstr "Librería Standard" + +#: src/SUMMARY.md:106 +msgid "Option and Result" +msgstr "Option y Result" + +#: src/SUMMARY.md:107 +msgid "String" +msgstr "" + +#: src/SUMMARY.md:108 +msgid "Vec" +msgstr "" + +#: src/SUMMARY.md:109 +msgid "HashMap" +msgstr "" + +#: src/SUMMARY.md:110 +msgid "Box" +msgstr "" + +#: src/SUMMARY.md:111 +msgid "Recursive Data Types" +msgstr "Tipo de Datos Recursivos" + +#: src/SUMMARY.md:112 +msgid "Niche Optimization" +msgstr "Optimización de Nicho" + +#: src/SUMMARY.md:113 +msgid "Rc" +msgstr "Rc" + +#: src/SUMMARY.md:114 +msgid "Modules" +msgstr "Módulos" + +#: src/SUMMARY.md:115 +msgid "Visibility" +msgstr "Visibilidad" + +#: src/SUMMARY.md:116 +msgid "Paths" +msgstr "" + +#: src/SUMMARY.md:117 +msgid "Filesystem Hierarchy" +msgstr "Jerarquía del Sistema de Archivos" + +#: src/SUMMARY.md:119 +msgid "Luhn Algorithm" +msgstr "Algoritmo de Luhn" + +#: src/SUMMARY.md:120 +msgid "Strings and Iterators" +msgstr "Strings e Iteradores" + +#: src/SUMMARY.md:123 +msgid "Day 3: Morning" +msgstr "Día 3: Mañana" + +#: src/SUMMARY.md:128 +msgid "Traits" +msgstr "" + +#: src/SUMMARY.md:129 +msgid "Deriving Traits" +msgstr "Traits Derivados" + +#: src/SUMMARY.md:130 +msgid "Default Methods" +msgstr "Métodos por Default" + +#: src/SUMMARY.md:131 +msgid "Important Traits" +msgstr "Traits Importantes" + +#: src/SUMMARY.md:132 +msgid "Iterator" +msgstr "Iteradores" + +#: src/SUMMARY.md:133 +msgid "FromIterator" +msgstr "FromIterator" + +#: src/SUMMARY.md:134 +msgid "From and Into" +msgstr "From e Into" + +#: src/SUMMARY.md:135 +msgid "Read and Write" +msgstr "Read y Write" + +#: src/SUMMARY.md:136 +msgid "Add, Mul, ..." +msgstr "Add, Mul, …." + +#: src/SUMMARY.md:137 +msgid "Drop" +msgstr "" + +#: src/SUMMARY.md:138 +msgid "Default" +msgstr "" + +#: src/SUMMARY.md:139 +msgid "Generics" +msgstr "Genéricos" + +#: src/SUMMARY.md:140 +msgid "Generic Data Types" +msgstr "Tipos de Datos Genéricos" + +#: src/SUMMARY.md:141 +msgid "Generic Methods" +msgstr "Métodos Genéricos" + +#: src/SUMMARY.md:142 +msgid "Trait Bounds" +msgstr "Límites Trait (Bounds)" + +#: src/SUMMARY.md:143 +msgid "impl Trait" +msgstr "impl Trait" + +#: src/SUMMARY.md:144 +msgid "Closures" +msgstr "Cláusulas" + +#: src/SUMMARY.md:145 +msgid "Monomorphization" +msgstr "Monomorphization" + +#: src/SUMMARY.md:146 +msgid "Trait Objects" +msgstr "Objetos Trait" + +#: src/SUMMARY.md:148 +msgid "A Simple GUI Library" +msgstr "Una Libraría Simple GUI" + +#: src/SUMMARY.md:150 +msgid "Day 3: Afternoon" +msgstr "Día 3: Tarde" + +#: src/SUMMARY.md:152 +msgid "Error Handling" +msgstr "Manejo de Errores" + +#: src/SUMMARY.md:153 +msgid "Panics" +msgstr "" + +#: src/SUMMARY.md:154 +msgid "Catching Stack Unwinding" +msgstr "Catching Stack Unwinding" + +#: src/SUMMARY.md:155 +msgid "Structured Error Handling" +msgstr "Manejo de Errores de Estructura" + +#: src/SUMMARY.md:156 +msgid "Propagating Errors with ?" +msgstr "Propagación de Errores con ?" + +#: src/SUMMARY.md:157 +msgid "Converting Error Types" +msgstr "Convirtiendo Tipos de Errores" + +#: src/SUMMARY.md:159 +msgid "Deriving Error Enums" +msgstr "Derivando Errores Enum" + +#: src/SUMMARY.md:160 +msgid "Dynamic Error Types" +msgstr "Tipos de Errores Dinámicos" + +#: src/SUMMARY.md:161 +msgid "Adding Context to Errors" +msgstr "Dando Contexto a los Errores" + +#: src/SUMMARY.md:162 +msgid "Testing" +msgstr "Testeando" + +#: src/SUMMARY.md:163 +msgid "Unit Tests" +msgstr "Testeo Unitario" + +#: src/SUMMARY.md:164 +msgid "Test Modules" +msgstr "Módulos de Test" + +#: src/SUMMARY.md:165 +msgid "Documentation Tests" +msgstr "Documentación de Test" + +#: src/SUMMARY.md:166 +msgid "Integration Tests" +msgstr "Tests de Integración" + +#: src/SUMMARY.md:167 +msgid "Unsafe Rust" +msgstr "Rust No Seguro (Unsafe)" + +#: src/SUMMARY.md:168 +msgid "Dereferencing Raw Pointers" +msgstr "Desreferenciar Punteros Raw" + +#: src/SUMMARY.md:169 +msgid "Mutable Static Variables" +msgstr "Variables Mutables Estáticas" + +#: src/SUMMARY.md:170 +msgid "Unions" +msgstr "Unions" + +#: src/SUMMARY.md:171 +msgid "Calling Unsafe Functions" +msgstr "Llamando Funciones No Seguras" + +#: src/SUMMARY.md:172 +msgid "Writing Unsafe Functions" +msgstr "Escribiendo Funciones No Seguras" + +#: src/SUMMARY.md:173 +msgid "Extern Functions" +msgstr "Funciones Externas" + +#: src/SUMMARY.md:174 +msgid "Implementing Unsafe Traits" +msgstr "Implementando Traits No Seguros" + +#: src/SUMMARY.md:176 +msgid "Safe FFI Wrapper" +msgstr "Wrappers FFI Seguros" + +#: src/SUMMARY.md:179 +msgid "Day 4: Morning" +msgstr "Día 4: Mañana" + +#: src/SUMMARY.md:184 +msgid "Concurrency" +msgstr "Concurrencia" + +#: src/SUMMARY.md:185 +msgid "Threads" +msgstr "Hilos" + +#: src/SUMMARY.md:186 +msgid "Scoped Threads" +msgstr "Ámbito de los Hilos" + +#: src/SUMMARY.md:187 +msgid "Channels" +msgstr "Canales" + +#: src/SUMMARY.md:188 +msgid "Unbounded Channels" +msgstr "Canales Ilimitados" + +#: src/SUMMARY.md:189 +msgid "Bounded Channels" +msgstr "Canales Limitados" + +#: src/SUMMARY.md:190 +msgid "Shared State" +msgstr "Estado Compartido" + +#: src/SUMMARY.md:191 +msgid "Arc" +msgstr "" + +#: src/SUMMARY.md:192 +msgid "Mutex" +msgstr "" + +#: src/SUMMARY.md:194 +msgid "Send and Sync" +msgstr "Send y Sync" + +#: src/SUMMARY.md:194 +msgid "Send" +msgstr "" + +#: src/SUMMARY.md:194 +msgid "Sync" +msgstr "Sync" + +#: src/SUMMARY.md:197 +msgid "Examples" +msgstr "Ejemplo" + +#: src/SUMMARY.md:199 +msgid "Dining Philosophers" +msgstr "Filosofía de la Cena" + +#: src/SUMMARY.md:200 +msgid "Multi-threaded Link Checker" +msgstr "Chequeo de Links Multi-hilos" + +#: src/SUMMARY.md:202 +msgid "Day 4: Afternoon" +msgstr "Día 4: Tarde" + +#: src/SUMMARY.md:206 +msgid "Android" +msgstr "" + +#: src/SUMMARY.md:207 +msgid "Setup" +msgstr "" + +#: src/SUMMARY.md:208 +msgid "Build Rules" +msgstr "Reglas de Compilación (Build)" + +#: src/SUMMARY.md:209 +msgid "Binary" +msgstr "Binarios" + +#: src/SUMMARY.md:210 +msgid "Library" +msgstr "Librería" + +#: src/SUMMARY.md:211 +msgid "AIDL" +msgstr "" + +#: src/SUMMARY.md:212 +msgid "Interface" +msgstr "" + +#: src/SUMMARY.md:213 +msgid "Implementation" +msgstr "Implementación" + +#: src/SUMMARY.md:214 +msgid "Server" +msgstr "Servidor" + +#: src/SUMMARY.md:215 +msgid "Deploy" +msgstr "" + +#: src/SUMMARY.md:216 +msgid "Client" +msgstr "Cliente" + +#: src/SUMMARY.md:217 +msgid "Changing API" +msgstr "Cambiando de API" + +#: src/SUMMARY.md:218 +msgid "Logging" +msgstr "" + +#: src/SUMMARY.md:219 +msgid "Interoperability" +msgstr "Interoperabilidad" + +#: src/SUMMARY.md:220 +msgid "With C" +msgstr "Con C" + +#: src/SUMMARY.md:221 +msgid "Calling C with Bindgen" +msgstr "Invocar C desde Bindgen" + +#: src/SUMMARY.md:222 +msgid "Calling Rust from C" +msgstr "Invocar Rust desde C" + +#: src/SUMMARY.md:223 +msgid "With C++" +msgstr "Con C++" + +#: src/SUMMARY.md:224 +msgid "With Java" +msgstr "Con Java" + +#: src/SUMMARY.md:227 +msgid "Final Words" +msgstr "Palabras Finales" + +#: src/SUMMARY.md:229 +msgid "Thanks!" +msgstr "Gracias!" + +#: src/SUMMARY.md:230 +msgid "Other Resources" +msgstr "Otros Recursos" + +#: src/SUMMARY.md:231 +msgid "Credits" +msgstr "Créditos" + +#: src/SUMMARY.md:235 +msgid "Solutions" +msgstr "Soluciones" + +#: src/SUMMARY.md:240 +msgid "Day 1 Morning" +msgstr "Día 1 Mañana" + +#: src/SUMMARY.md:241 +msgid "Day 1 Afternoon" +msgstr "Día 1 Tarde" + +#: src/SUMMARY.md:242 +msgid "Day 2 Morning" +msgstr "Día 2 Mañana" + +#: src/SUMMARY.md:243 +msgid "Day 2 Afternoon" +msgstr "Día 2 Tarde" + +#: src/SUMMARY.md:244 +msgid "Day 3 Morning" +msgstr "Día 3 Mañana" + +#: src/SUMMARY.md:245 +msgid "Day 3 Afternoon" +msgstr "Día 3 Tarde" + +#: src/SUMMARY.md:246 +msgid "Day 4 Morning" +msgstr "Día 4 Mañana" + +#: src/welcome.md:1 +msgid "# Welcome to Comprehensive Rust 🦀" +msgstr "# Bienvenido a Comprehensive Rust 🦀" + +#: src/welcome.md:3 +msgid "" +"This is a four 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 "" +"Este es un curso de Rust de cuatro días desarrollado por el team de Android. El curso cubre\n" +"el espectro completo de Rust, desde la sintaxis básica a tópicos avanzados como genéricos\n" +"y el manejo de errores. Para el último día también incluye contenido específico a Android." + +#: src/welcome.md:7 +msgid "" +"The goal of the course is to teach you Rust. We assume you don't know anything\n" +"about Rust and hope to:" +msgstr "" +"El objetivo del curso es enseñarte Rust. Asumimos que no sabes nada\n" +"Acerca de Rust y esperamos que:" + +#: src/welcome.md:10 +msgid "" +"* Give you a comprehensive understanding of the Rust syntax and language.\n" +"* Enable you to modify existing programs and write new programs in Rust.\n" +"* Show you common Rust idioms." +msgstr "" +"* Darte un entendimiento comprensivo de la sintaxis y lenguaje Rust.\n" +"* Permitirte modificar programas de Rust y escribir otros nuevos.\n" +"* Brindarte idiomática propia de Rust." + +#: src/welcome.md:14 +msgid "On Day 4, we will cover Android-specific things such as:" +msgstr "En el Día 4, cubriremos cosas específicas a Android como:" + +#: src/welcome.md:16 +msgid "" +"* Building Android components in Rust.\n" +"* AIDL servers and clients.\n" +"* Interoperability with C, C++, and Java." +msgstr "" +"* Construir componentes en Rust.\n" +"* Clientes y servidores AIDL. \n" +"* Interoperabilidad con C, C++, y Java." + +#: src/welcome.md:20 +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 importante destacar que este curso no cubre desarrollo de **aplicaciones** \n" +"Android en Rust, y que las partes específicas a Android son acerca de\n" +"escribir código para Android en sí, el sistema operativo. " + +#: src/welcome.md:24 +msgid "## Non-Goals" +msgstr "## No tiene por Objetivo" + +#: src/welcome.md:26 +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:" +msgstr "" +"Rust es un lenguaje extenso y no podemos cubrir todo de él en algunos días.\n" +"Algo de los No Objetivos es:" + +#: src/welcome.md:29 +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 "" +"* Aprender cómo usar Rust asincrónico —solo mencionaremos Rust async cuando\n" +"cubramos las primitivas de concurrencia tradicional. Por favor ver [Asynchronous\n" +" Programming in Rust](https://rust-lang.github.io/async-book/) para más detalles.\n" +"* Aprender como escribir macros, en cambio por favor ver [Capítulo 19.5 en el Libro de\n" +"Rust](https://doc.rust-lang.org/book/ch19-06-macros.html) y [Rust by\n" +" Example](https://doc.rust-lang.org/rust-by-example/macros.html)." + +#: src/welcome.md:37 +msgid "## Assumptions" +msgstr "## Suposiciones" + +#: src/welcome.md:39 +msgid "" +"The course assumes that you already know how to program. Rust is a statically\n" +"typed language and we will sometimes make comparisons with C and C++ to better\n" +"explain or contrast the Rust approach." +msgstr "" +"El curso asume que ya sabes programar. Rust es un lenguaje de tipado estático y \n" +"algunas veces trataremos comparaciones con C y C++ para explicar mejor o\n" +"contrastar la aproximación de Rust." + +#: src/welcome.md:43 +msgid "" +"If you know how to program in a dynamically typed language such as Python or\n" +"JavaScript, then you will be able to follow along just fine too." +msgstr "" +"Si sabes como programar en un lenguaje de tapado dinámico como Python o\n" +"JavaScript, también podrás seguir el contenido a lo largo del curso." + +#: src/welcome.md:46 src/cargo/rust-ecosystem.md:19 src/cargo/code-samples.md:22 +#: 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/string-slices.md:25 src/basic-syntax/functions.md:33 +#: 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/structs/tuple-structs.md:35 +#: src/structs/field-shorthand.md:25 src/enums/variant-payloads.md:33 src/methods.md:28 +#: src/pattern-matching/destructuring-enums.md:33 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/match-expressions.md:25 +#: 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:24 src/exercises/day-2/afternoon.md:5 +#: src/traits.md:39 src/traits/iterator.md:30 src/traits/from-iterator.md:15 +#: src/traits/operators.md:24 src/traits/drop.md:32 src/traits/default.md:38 +#: src/generics/methods.md:23 src/generics/trait-bounds.md:33 src/generics/impl-trait.md:22 +#: src/generics/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/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/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/concurrency/threads.md:28 +#: src/concurrency/channels.md:25 src/concurrency/shared_state/arc.md:27 +#: 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/afternoon.md:10 +msgid "
" +msgstr "
" + +#: src/welcome.md:48 +msgid "" +"This is an example of a _speaker note_. We will use these to add additional\n" +"information to the slides. This could be key points which the instructor should\n" +"cover as well as answers to typical questions which come up in class." +msgstr "" +"Este es un ejemplo de _nota del speaker_. Usaremos esto para agregar información \n" +"adicional a las diapositivas. Esto puede ser el punto clave en el cual el instructor podría\n" +"cubrir respuestas a preguntas comunes." + +#: src/welcome.md:52 src/cargo/rust-ecosystem.md:67 src/cargo/code-samples.md:35 +#: 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:36 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/functions.md:54 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 +#: src/memory-management/rust.md:18 src/ownership/move-semantics.md:26 +#: src/ownership/moves-function-calls.md:26 src/ownership/borrowing.md:51 +#: src/ownership/shared-unique-borrows.md:29 src/ownership/lifetimes-function-calls.md:60 +#: src/exercises/day-1/afternoon.md:15 src/exercises/day-1/book-library.md:103 src/structs.md:41 +#: src/enums/variant-payloads.md:41 src/enums/sizes.md:136 src/methods/example.md:53 +#: src/pattern-matching/destructuring-enums.md:39 src/pattern-matching/destructuring-arrays.md:46 +#: src/exercises/day-2/morning.md:15 src/exercises/day-2/points-polygons.md:125 +#: src/control-flow/if-let-expressions.md:26 src/control-flow/for-expressions.md:29 +#: src/control-flow/loop-expressions.md:27 src/std.md:31 src/std/option-result.md:25 +#: src/std/string.md:33 src/std/vec.md:49 src/std/hashmap.md:66 src/std/rc.md:66 src/modules.md:32 +#: src/modules/visibility.md:48 src/modules/filesystem.md:53 src/exercises/day-2/afternoon.md:11 +#: src/traits.md:54 src/traits/from-iterator.md:26 src/traits/operators.md:38 src/traits/drop.md:42 +#: src/traits/default.md:47 src/generics/methods.md:31 src/generics/closures.md:38 +#: src/exercises/day-3/morning.md:11 src/error-handling/try-operator.md:55 +#: 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/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/concurrency/threads.md:45 +#: src/concurrency/channels.md:32 src/concurrency/shared_state/arc.md:38 +#: src/concurrency/shared_state/example.md:60 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/afternoon.md:15 +msgid "
" +msgstr "
" + +#: src/running-the-course.md:1 +msgid "# Running the Course" +msgstr "# Ejecutar el Curso" + +#: src/running-the-course.md:3 src/running-the-course/course-structure.md:3 +msgid "> This page is for the course instructor." +msgstr "> Esta página es para el instructor del curso." + +#: src/running-the-course.md:5 +msgid "" +"Here is a bit of background information about how we've been running the course\n" +"internally at Google." +msgstr "" +"Aquí hay un poco de información de fondo acerca de como nosotros hemos llevado a cabo el curso\n" +"Internamente en Google." + +#: src/running-the-course.md:8 +msgid "To run the course, you need to:" +msgstr "Para hacer el curso, necesitas:" + +#: src/running-the-course.md:10 +msgid "" +"1. Make yourself familiar with the course material. We've included speaker notes\n" +" on some of the pages to help highlight the key points (please help us by\n" +" contributing more speaker notes!). You should make sure to open the speaker\n" +" notes in a popup (click the link with a little arrow next to \"Speaker\n" +" Notes\"). This way you have a clean screen to present to the class." +msgstr "" +"1. Estar familiarizado con el material del curso. Incluimos notas para el orador\n" +"en algunas páginas para ayudar a destacar algunos puntos clave (por favor ayúdanos \n" +"sumando con más notas!). Deberías estar seguro de abrir notas en un popup (click en el \n" +"link con una pequeña flecha al lado de \"Speaker Notes\"). De esta manera tendrás\n" +"la pantalla limpia para los oyentes de la clase." + +#: src/running-the-course.md:16 +msgid "" +"2. 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" +" they find it helpful to have a gap in the course since it helps them process\n" +" all the information we give them." +msgstr "" +"2. Determina las fechas. Debido que el curso es largo, recomendamos que\n" +"planifiques un calendario de cuatro días en dos semanas. Los participantes del curso \n" +"deben encontrar útil tener un espacio en el curso ya que ayuda a procesar\n" +"toda la información que daremos." + +#: src/running-the-course.md:21 +msgid "" +"3. 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" +" asking questions --- it's also small enough that one instructor will have\n" +" time to answer the questions." +msgstr "" +"3. Encuentra un lugar grande lo suficiente para los participantes. Recomendamos una \n" +"clase del tamaño de 15-20 personas. Es lo mínimo necesario para estar cómodos \n" +"respondiendo preguntas ---y también para que un instructor tenga tiempo \n" +"para responder las preguntas." + +#: src/running-the-course.md:26 +msgid "" +"4. On the day of your course, show up to the room a little early to set things\n" +" up. We recommend presenting directly using `mdbook serve` running on your\n" +" laptop (see the [installation instructions][5]). This ensures optimal performance with no lag " +"as you change pages.\n" +" Using your laptop will also allow you to fix typos as you or the course\n" +" participants spot them." +msgstr "" +"4. En el día del curso, llega al lugar antes para tener las cosas listas.\n" +" Recomendamos hacer la presentación usando directamente `mdbook serve` corriendo en tu\n" +" notebook (vea la [instrucción de instalación][5]). Esto asegura la mejor performance si lag al cambiar de página.\n" +" Usar tu laptop te permitirá corregir errores tipográficos que tú o los participantes encuentren en el curso." + +#: src/running-the-course.md:32 +msgid "" +"5. Let people solve the exercises by themselves or in small groups. 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." +msgstr "" +"5. Permite a las personas resolver los ejercicios ellos mismos o en grupos pequeños. Asegúrate de\n" +" preguntar a las personas si están trabadas o si hay algo en que puedas ayudarlos. Cuando\n" +" Veas varias personas tienen el mismo problema, háblalo con todos y ofrece una solución, por ejemplo, mostrando a las personas dónde encontrar información de librerías estándar." + +#: src/running-the-course.md:38 +msgid "" +"6. If you don't skip the Android specific parts on Day 4, you will need an [AOSP\n" +" checkout][1]. Make a checkout of the [course repository][2] on the same\n" +" machine and move the `src/android/` directory into the root of your AOSP\n" +" checkout. This will ensure that the Android build system sees the\n" +" `Android.bp` files in `src/android/`." +msgstr "" +"6. Si no saltas la parte del Día 4 específica de Android, necesitarás un [AOSP\n" +" checkout][1]. Haz un checkout del [repositorio del curso][2] en la misma\n" +" Máquina y moviendo el directorio `src/android/` a la raíz de tu archivos AOSP de ‘Android.bp’ en `src/android/`." + +#: src/running-the-course.md:44 +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." +msgstr "" +" Asegúrate que `adb sync` funciona con tu emulador o en un dispositivo físico y haz pre-build\n" +" en todos los ejemplos de Android usando `src/android/build_all.sh`. Lee el script para ver\n" +" los comandos que corren y asegúrate que funcionan cuando lo corres a mano." + +#: src/running-the-course.md:48 +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!" +msgstr "" +"Esto es todo, buena suerte haciendo el curso! Esperamos que hacerlo sea tan placentero para\n" +"ti como lo fue para nosotros!" + +#: src/running-the-course.md:51 +msgid "" +"Please [provide feedback][3] 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" +"better. Your students are also very welcome to [send us feedback][4]!" +msgstr "" +"Por favor luego [proporciona comentarios][3] para que podamos mejorar el curso.\n" +"Nos encantaría saber cómo fue y qué podríamos hacer mejor.\n" +"Los estudiantes también son bienvenidos para que [nos envíen feedback][4]!" + +#: src/running-the-course.md:55 +msgid "" +"[1]: https://source.android.com/docs/setup/download/downloading\n" +"[2]: https://github.com/google/comprehensive-rust\n" +"[3]: https://github.com/google/comprehensive-rust/discussions/86\n" +"[4]: https://github.com/google/comprehensive-rust/discussions/100\n" +"[5]: https://github.com/google/comprehensive-rust#building" +msgstr "" +"[1]: https://source.android.com/docs/setup/download/downloading\n" +"[2]: https://github.com/google/comprehensive-rust\n" +"[3]: https://github.com/google/comprehensive-rust/discussions/86\n" +"[4]: https://github.com/google/comprehensive-rust/discussions/100\n" +"[5]: https://github.com/google/comprehensive-rust#building" + +#: src/running-the-course/course-structure.md:1 +msgid "# Course Structure" +msgstr "# Estructura del Curso" + +#: src/running-the-course/course-structure.md:5 +msgid "The course is fast paced and covers a lot of ground:" +msgstr "Este curso es acelerado y cubre muchos temas:" + +#: src/running-the-course/course-structure.md:7 +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 interoperability with other languages" +msgstr "" +"* Día 1: Rust Básico, propiedad y chequeo de préstamos.\n" +"* Día 2: Tipos de datos compuestos, coincidencia de patrones, la librería estándar.\n" +"* Día 3: Traits y Genéricos, manejo de errores, testing, Rust no seguro.\n" +"* Día 4: Concurrencia en Rust e interoperatiblidad con otros lenguajes" + +#: src/running-the-course/course-structure.md:12 +msgid "" +"> **Exercise for Day 4:** Do you interface with some C/C++ code in your project\n" +"> which we could attempt to move to Rust? The fewer dependencies the better.\n" +"> Parsing code would be ideal." +msgstr "" +"> **Ejecicio del Día 4:** Comunicarte con alegan código C/C++ en tu proyecto\n" +"> que podrías migrar a Rust? Con menos dependencias es lo mejor.\n" +"> Parsear el código sería lo ideal." + +#: src/running-the-course/course-structure.md:16 +msgid "## Format" +msgstr "## Formato" + +#: src/running-the-course/course-structure.md:18 +msgid "" +"The course is meant to be very interactive and we recommend letting the\n" +"questions drive the exploration of Rust!" +msgstr "" +"El curso tiene la intención de ser muy interactivo y recomendamos dejar que las preguntas lleven a " +"explorar Rust!" + +#: src/running-the-course/keyboard-shortcuts.md:1 +msgid "# Keyboard Shortcuts" +msgstr "# Atajos de Teclado" + +#: src/running-the-course/keyboard-shortcuts.md:3 +msgid "There are several useful keyboard shortcuts in mdBook:" +msgstr "Tenemos varios atajos de teclados útiles en mdBook:" + +#: src/running-the-course/keyboard-shortcuts.md:5 +msgid "" +"* Arrow-Left: Navigate to the previous page.\n" +"* Arrow-Right: Navigate to the next page.\n" +"* Ctrl + Enter: Execute the code sample that has focus.\n" +"* s: Activate the search bar." +msgstr "" +"* Arrow-Left: Navigar a la página anterior.\n" +"* Arrow-Right: Navigar a la página siguiente.\n" +"* Ctrl + Enter: Ejecuta el código de ejemplo seleccionado.\n" +"* s: Activa la barra de búsqueda." + +#: src/running-the-course/translations.md:1 +msgid "# Translations" +msgstr "# Traducción" + +#: src/running-the-course/translations.md:3 +msgid "" +"The course has been translated into other languages by a set of wonderful\n" +"volunteers:" +msgstr "" +"El curso ha sido traducido a otros lenguajes por una serie de maravillosos\n" +"voluntarios:" + +#: src/running-the-course/translations.md:6 +msgid "" +"* [Brazilian Portuguese][pt-BR] by [@rastringer] and [@hugojacob].\n" +"* [Korean][ko] by [@keispace], [@jiyongp] and [@jooyunghan]." +msgstr "" +"* [Brazilian Portuguese][pt-BR] por [@rastringer] and [@hugojacob].\n" +"* [Korean][ko] por [@keispace], [@jiyongp] and [@jooyunghan].\n" +"* [Spanish][es] por [@wfranck]." + +#: src/running-the-course/translations.md:9 +msgid "Use the language picker in the top-right corner to switch between languages." +msgstr "" +"Selecciona el lenguaje en el globo en la esquina superior derecha para cambiar entre lenguajes." + +#: src/running-the-course/translations.md:11 +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]." +msgstr "" +"Si gustas contribuir con traducciones, por favor revisa [nuestras instrucciones] para \n" +"saber cómo. Las traducciones son coordinadas en el [issue tracker]." + +#: src/running-the-course/translations.md:14 +msgid "" +"[pt-BR]: https://google.github.io/comprehensive-rust/pt-BR/\n" +"[ko]: https://google.github.io/comprehensive-rust/ko/\n" +"[@rastringer]: https://github.com/rastringer\n" +"[@hugojacob]: https://github.com/hugojacob\n" +"[@keispace]: https://github.com/keispace\n" +"[@jiyongp]: https://github.com/jiyongp\n" +"[@jooyunghan]: https://github.com/jooyunghan\n" +"[our instructions]: https://github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md\n" +"[issue tracker]: https://github.com/google/comprehensive-rust/issues/282" +msgstr "" +"[es]: https://google.github.io/comprehensive-rust/es/\n" +"[pt-BR]: https://google.github.io/comprehensive-rust/pt-BR/\n" +"[ko]: https://google.github.io/comprehensive-rust/ko/\n" +"[@wfranck]: https://github.com/wfranck\n" +"[@rastringer]: https://github.com/rastringer\n" +"[@hugojacob]: https://github.com/hugojacob\n" +"[@keispace]: https://github.com/keispace\n" +"[@jiyongp]: https://github.com/jiyongp\n" +"[@jooyunghan]: https://github.com/jooyunghan\n" +"[our instructions]: https://github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md\n" +"[issue tracker]: https://github.com/google/comprehensive-rust/issues/282" + +#: src/cargo.md:1 +msgid "# Using Cargo" +msgstr "# Usando Cargo" + +#: src/cargo.md:3 +msgid "" +"When you start reading about Rust, you will soon meet [Cargo](https://doc.rust-lang.org/cargo/), " +"the standard tool\n" +"used in the Rust ecosystem to build and run Rust applications. Here we want to\n" +"give a brief overview of what Cargo is and how it fits into the wider ecosystem\n" +"and how it fits into this training." +msgstr "" +"Cuando comienzas a leer acerca de Rust, descubrirás [Cargo](https://doc.rust-lang.org/cargo/), la herramienta estándar\n" +"Usada en el ecosistema Rust para construir y correr aplicaciones Rust. Aquí queremos\n" +"Dar una breve reseña de qué es Cargo y cómo forma parte del amplio ecosistema y\n" +"como encaja en este curso." + +#: src/cargo.md:8 +msgid "## Installation" +msgstr "## Instalación" + +#: src/cargo.md:10 +msgid "### Rustup (Recommended)" +msgstr "### Rustup (Recomendado)" + +#: src/cargo.md:12 +msgid "" +"You can follow the instructions to install cargo and rust compiler, among other standard ecosystem " +"tools with the [rustup][3] tool, which is maintained by the Rust Foundation." +msgstr "Puedes seguir las instrucciones para instalar cargo y el compilador de Rust, además de otras herramientas estándar con la herramienta [rustup][3], que es mantenida por la Fundación Rust." + +#: src/cargo.md:14 +msgid "" +"Along with cargo and rustc, Rustup will install itself as a command line utility that you can use " +"to install/switch toolchains, setup cross compilation, etc." +msgstr "Con cargo y rustc, Rustup por sí mismo se instalará como una utilidad de línea de comando que puedes usar para instalar/cambiar entre herramientas, configurar compilaciones cruzadas, etc." + +#: src/cargo.md:16 +msgid "### Package Managers" +msgstr "### Package Managers" + +#: src/cargo.md:18 +msgid "#### Debian" +msgstr "" + +#: src/cargo.md:20 +msgid "On Debian/Ubuntu, you can install Cargo, the Rust source and the [Rust formatter][6] with" +msgstr "En Debian/Ubuntu, puedes instalar Cargo, el código fuente de Rust y el [Rust formatter][6] con" + +#: src/cargo.md:22 +msgid "" +"```shell\n" +"$ sudo apt install cargo rust-src rustfmt\n" +"```" +msgstr "" + +#: src/cargo.md:26 +msgid "" +"This will allow [rust-analyzer][1] to jump to the definitions. We suggest using\n" +"[VS Code][2] to edit the code (but any LSP compatible editor works)." +msgstr "" +"Esto permitirá a [rust-analyzer][1] saltar a las definiciones. Sugerimos usar\n" +"[VS Code][2] para editar código (pero cualquier editor LSP compatible funcionará)." + +#: src/cargo.md:29 +msgid "" +"Some folks also like to use the [JetBrains][4] family of IDEs, which do their own analysis but " +"have their own tradeoffs. If you prefer them, you can install the [Rust Plugin][5]. Please take " +"note that as of January 2023 debugging only works on the CLion version of the JetBrains IDEA suite." +msgstr "" +"A algunos colegas también les gusta usar IDEs [JetBrains][4], que hacen su propio análisis y tienen diferentes ventajas. Si prefieres usarlos, puedes instalar el [Rust Plugin].\n" +"Por favor tén en cuenta que a Enero 2023 el debugging solo funciona en la versión CLion de JetBrains IDEA." + +#: src/cargo.md:31 +msgid "" +"[1]: https://rust-analyzer.github.io/\n" +"[2]: https://code.visualstudio.com/\n" +"[3]: https://rustup.rs/\n" +"[4]: https://www.jetbrains.com/clion/\n" +"[5]: https://www.jetbrains.com/rust/\n" +"[6]: https://github.com/rust-lang/rustfmt" +msgstr "" + +#: src/cargo/rust-ecosystem.md:1 +msgid "# The Rust Ecosystem" +msgstr "# El Ecosistema Rust" + +#: src/cargo/rust-ecosystem.md:3 +msgid "The Rust ecosystem consists of a number of tools, of which the main ones are:" +msgstr "El ecosistema Rust consiste en un número de herramientas, entre las cuales contamos como principales:" + +#: src/cargo/rust-ecosystem.md:5 +msgid "" +"* `rustc`: the Rust compiler which turns `.rs` files into binaries and other\n" +" intermediate formats." +msgstr "" +"* `rustc`: el compilador Rustque cambia archivos`.rs` a binarios y a otros\n" +" formatos intermedios." + +#: src/cargo/rust-ecosystem.md:8 +msgid "" +"* `cargo`: the Rust dependency manager and build tool. Cargo knows how to\n" +" download dependencies hosted on and it will pass them to\n" +" `rustc` when building your project. Cargo also comes with a built-in test\n" +" runner which is used to execute unit tests." +msgstr "" +"* `cargo`: la herramienta de manejo y build de Rust. Cargo sabe como \n" +"descargar dependencias guardadas en y enviará ellas a\n" +"`rustc` cuando arme tu proyecto. Cargo también trae incluida una herramienta de test \n" +"que es usada para ejecutar test unitarios." + +#: src/cargo/rust-ecosystem.md:13 +msgid "" +"* `rustup`: the Rust toolchain installer and updater. This tool is used to\n" +" install and update `rustc` and `cargo` when new versions of Rust is released.\n" +" In addition, `rustup` can also download documentation for the standard\n" +" library. You can have multiple versions of Rust installed at once and `rustup`\n" +" will let you switch between them as needed." +msgstr "" +"* `rustup`: es la herramienta Rust para hacer instalaciones y actualizaciones. Esta herramienta es " +"usada para\n" +"Instalar y actualizar `rustc` y `cargo` cuando salen nuevas versiones de Rust.\n" +"Además, `rustup` también puede descargar documentación para las librerías estándar.\n" +"Puedes tener múltiples versiones de Rust instaladas al mismo tiempo y `rustup`\n" +"te dejará cambiar entre ellas cuando lo necesites." + +#: 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/error-handling/try-operator.md:50 src/error-handling/converting-error-types-example.md:50 +#: src/concurrency/threads.md:30 +msgid "Key points:" +msgstr "Puntos clave:" + +#: src/cargo/rust-ecosystem.md:23 +msgid "" +"* Rust has a rapid release schedule with a new release coming out\n" +" every six weeks. New releases maintain backwards compatibility with\n" +" old releases --- plus they enable new functionality." +msgstr "" +"* Rust tiene un programa de lanzamientos rápidos con una nueva versión \n" +"cada seis semanas. Cada nuevo lanzamiento será retrocompatible con \n" +"viejas versiones --- además que agregan nueva funcionalidad." + +#: src/cargo/rust-ecosystem.md:27 +msgid "* There are three release channels: \"stable\", \"beta\", and \"nightly\"." +msgstr "* Para las raleases tenemos tres canales: \"estable\", \"beta\", y \"nightly\"." + +#: src/cargo/rust-ecosystem.md:29 +msgid "" +"* New features are being tested on \"nightly\", \"beta\" is what becomes\n" +" \"stable\" every six weeks." +msgstr "" +"* Nuevas características se testean en \"nightly\" y \"beta\" pasa a \n" +"\"restable\" cada seis semanas." + +#: src/cargo/rust-ecosystem.md:32 +msgid "" +"* Rust also has [editions]: the current edition is Rust 2021. Previous\n" +" editions were Rust 2015 and Rust 2018." +msgstr "" +"* Rust también tiene [ediciones]: la edición actual es Rust 2021. Las ediciones anteriores fueron " +"Rust 2015 y Rust 2018." + +#: src/cargo/rust-ecosystem.md:35 +msgid "" +" * The editions are allowed to make backwards incompatible changes to\n" +" the language." +msgstr " * Las ediciones nuevas introducen cambios al lenguaje que no son retrocompatibles." + +#: src/cargo/rust-ecosystem.md:38 +msgid "" +" * To prevent breaking code, editions are opt-in: you select the\n" +" edition for your crate via the `Cargo.toml` file." +msgstr "" +" Para prevenir romper el código, se elige la versión: seleccionas la edición\n" +" para tu paquete vía el archivo `Cargo.toml`." + +#: src/cargo/rust-ecosystem.md:41 +msgid "" +" * To avoid splitting the ecosystem, Rust compilers can mix code\n" +" written for different editions." +msgstr "" +" * Para evitar dividir los ecosistemas, los compiladores de Rust pueden mezclar código\n" +" escrito para diferentes ediciones." + +#: src/cargo/rust-ecosystem.md:44 +msgid "" +" * Mention that it is quite rare to ever use the compiler directly not through `cargo` (most " +"users never do)." +msgstr "" +" * Hay que decir que es raro necesitar usar el compilador directamente y no a travez de `cargo` " +"(la mayoría de los usuarios jamás lo hace)." + +#: src/cargo/rust-ecosystem.md:46 +msgid "" +" * It might be worth alluding that Cargo itself is an extremely powerful and comprehensive tool. " +"It is capable of many advanced features including but not limited to: \n" +" * Project/package structure\n" +" * [workspaces]\n" +" * Dev Dependencies and Runtime Dependency management/caching\n" +" * [build scripting]\n" +" * [global installation]\n" +" * It is also extensible with sub command plugins as well (such as [cargo clippy]).\n" +" * Read more from the [official Cargo Book]" +msgstr "" +" * Vale la pena mencionar que Cargo en sí es una herramienta extremadamente poderosa e integral. " +"Es capaz de hacer muchas cosas avanzadas y no limitadas a: \n" +" * Estructura del proyecto/package \n" +" * [workspaces] \n" +" * Manejo/Caché de Dependencias de Desarrollo y de Runtime \n" +" * [build scripting] \n" +" * [instalación global] \n" +" * También es extensible con plugins de subcomandos (como es [cargo clippy]). \n" +" * Lee más en el [Libro Oficial de Cargo]" + +#: src/cargo/rust-ecosystem.md:55 +msgid "[editions]: https://doc.rust-lang.org/edition-guide/" +msgstr "[ediciones]: https://doc.rust-lang.org/edition-guide/" + +#: src/cargo/rust-ecosystem.md:57 +msgid "[workspaces]: https://doc.rust-lang.org/cargo/reference/workspaces.html" +msgstr "" + +#: src/cargo/rust-ecosystem.md:59 +msgid "[build scripting]: https://doc.rust-lang.org/cargo/reference/build-scripts.html" +msgstr "" + +#: src/cargo/rust-ecosystem.md:61 +msgid "[global installation]: https://doc.rust-lang.org/cargo/commands/cargo-install.html" +msgstr "[instalación global]: https://doc.rust-lang.org/cargo/commands/cargo-install.html" + +#: src/cargo/rust-ecosystem.md:63 +msgid "[cargo clippy]: https://github.com/rust-lang/rust-clippy" +msgstr "" + +#: src/cargo/rust-ecosystem.md:65 +msgid "[official Cargo Book]: https://doc.rust-lang.org/cargo/" +msgstr "[Libro Oficial de Cargo]: https://doc.rust-lang.org/cargo/" + +#: src/cargo/code-samples.md:1 +msgid "# Code Samples in This Training" +msgstr "# Códigos de Ejemplo en Esta Práctica" + +#: src/cargo/code-samples.md:3 +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" +"ensures a consistent experience for everyone." +msgstr "" +"Para esta práctica, principalmente exploraremos el lenguaje Rust a través de ejemplos\n" +"los cuales pueden correrse en el browser. Esto hace la configuración mucho mas fácil y\n" +"asegura consistencia en la experiencia de cada uno." + +#: src/cargo/code-samples.md:7 +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 "" +"Claro que se sigue recomendando instalar Cargo: será más fácil para tí para hacer los\n" +"ejercicios. En el último día haremos un ejercicio el cual te mostrará cómo\n" +"Trabajar con dependencias y para eso necesitarás Cargo." + +#: src/cargo/code-samples.md:11 +msgid "The code blocks in this course are fully interactive:" +msgstr "Los bloques de código en este curso son totalmente interactivos:" + +#: src/cargo/code-samples.md:13 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" println!(\"Edit me!\");\n" +"}\n" +"```" +msgstr "" +"```rust,editable\n" +"fn main() {\n" +" println!(\"Modifícame!\");\n" +"}\n" +"```" + +#: src/cargo/code-samples.md:19 +msgid "" +"You can use Ctrl + Enter to execute the code when focus is in the\n" +"text box." +msgstr "Puedes usar Ctrl + Enter paraejecutar código cuando se hace foco en el text box." + +#: src/cargo/code-samples.md:24 +msgid "" +"Most code samples are editable like shown above. A few code samples\n" +"are not editable for various reasons:" +msgstr "" +"La mayor parte de los ejemplos son editables como se muestra arriba. Unos pocos ejemplos\n" +"no son editables por varias razones:" + +#: src/cargo/code-samples.md:27 +msgid "" +"* The embedded playgrounds cannot execute unit tests. Copy-paste the\n" +" code and open it in the real Playground to demonstrate unit tests." +msgstr "" +"* En los bloques de código embebido no pueden ejecutarse test unitarios. Copia y pega el código y " +"ábrelo en un entorno real para comprobar test unitarios." + +#: src/cargo/code-samples.md:30 +msgid "" +"* The embedded playgrounds lose their state the moment you navigate\n" +" away from the page! This is the reason that the students should\n" +" solve the exercises using a local Rust installation or via the\n" +" Playground." +msgstr "" +"* Los espacios de código embebido pierden su estado en el momento que navegas\n" +"fuera de la página! Eta es la razón por la que los estudiantes deben\n" +"resolver los ejercicios usando una instalación local de Rust o vía esos\n" +"espacios de trabajo con código." + +#: src/cargo/running-locally.md:1 +msgid "# Running Code Locally with Cargo" +msgstr "# Correr Código Localmente con Cargo" + +#: src/cargo/running-locally.md:3 +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 "" +"Si quieres probar código en tu computadora, primero necesitarás \n" +"instalar Rust. Para esto sigue las [instrucciones en el Libro de \n" +"Rust][1]. Esto debería darte para usar un `rustc` y `cargo`. Al tiempo que se \n" +"escribe esto, la última versión estable de Rust tiene estos números de versiones:" + +#: src/cargo/running-locally.md:8 +msgid "" +"```shell\n" +"% rustc --version\n" +"rustc 1.61.0 (fe5b13d68 2022-05-18)\n" +"% cargo --version\n" +"cargo 1.61.0 (a028ae4 2022-04-29)\n" +"```" +msgstr "" + +#: src/cargo/running-locally.md:15 +msgid "" +"With this is in place, then follow these steps to build a Rust binary from one\n" +"of the examples in this training:" +msgstr "" +"Con esto en su lugar, sigue las instrucciones para hacer un build de los binarios de Rust desde\n" +"uno de los ejemplos de este curso:" + +#: src/cargo/running-locally.md:18 +msgid "1. Click the \"Copy to clipboard\" button on the example you want to copy." +msgstr "1. Click sobre el botón \"Copy to clipboard\" en el ejemplo que quieres copiar." + +#: src/cargo/running-locally.md:20 +msgid "2. Use `cargo new exercise` to create a new `exercise/` directory for your code:" +msgstr "2. Usa `cargo new ejercicio` para crear una nueva carpeta `ejercicio/` para tu código:" + +#: src/cargo/running-locally.md:22 +msgid "" +" ```shell\n" +" $ cargo new exercise\n" +" Created binary (application) `exercise` package\n" +" ```" +msgstr "" +" ```shell\n" +" $ cargo new ejercicio\n" +" Created binary (application) `ejercicio` package\n" +" ```" + +#: src/cargo/running-locally.md:27 +msgid "3. Navigate into `exercise/` and use `cargo run` to build and run your binary:" +msgstr "3. Ve hasta `ejercicio/` y usa `cargo run` para hacer build y ejecutar tus binarios:" + +#: src/cargo/running-locally.md:29 +msgid "" +" ```shell\n" +" $ cd exercise\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +" Running `target/debug/exercise`\n" +" Hello, world!\n" +" ```" +msgstr "" +" ```shell\n" +" $ cd ejercicio\n" +" $ cargo run\n" +" Compiling ejercicio v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +" Running `target/debug/exercise`\n" +" Hola Mundo!\n" +" ```" + +#: src/cargo/running-locally.md:38 +msgid "" +"4. Replace the boiler-plate code in `src/main.rs` with your own code. For\n" +" example, using the example on the previous page, make `src/main.rs` look like" +msgstr "" +"4. Reemplaza el código base en `src/main.rs` con tu propio código. Por\n" +" ejemplo, usando el ejemplo de la página anterior, haciendo que `src/main.rs` quede como" + +#: src/cargo/running-locally.md:41 +msgid "" +" ```rust\n" +" fn main() {\n" +" println!(\"Edit me!\");\n" +" }\n" +" ```" +msgstr "" +" ```rust\n" +" fn main() {\n" +" println!(\"Modifícame!\");\n" +" }\n" +" ```" + +#: src/cargo/running-locally.md:47 +msgid "5. Use `cargo run` to build and run your updated binary:" +msgstr "5. Usa `cargo run` para hacer build y ejecutar tu binario actualizado:" + +#: src/cargo/running-locally.md:49 +msgid "" +" ```shell\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +" Running `target/debug/exercise`\n" +" Edit me!\n" +" ```" +msgstr "" +" ```shell\n" +" $ cargo run\n" +" Compiling ejercicio v0.1.0 (/home/mgeisler/tmp/ejercicio)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +" Running `target/debug/ejercicio`\n" +" Modifícame!\n" +" ```" + +#: src/cargo/running-locally.md:57 +msgid "" +"6. Use `cargo check` to quickly check your project for errors, use `cargo build`\n" +" to compile it without running it. You will find the output in `target/debug/`\n" +" for a normal debug build. Use `cargo build --release` to produce an optimized\n" +" release build in `target/release/`." +msgstr "" +"6. Usa `cargo check` para controlar rápido tu proyecto por errores, usando `cargo build`\n" +"para compilar sin ejecutarlo. Podrás encontrar el resultado en `target/debug/`\n" +"para un debug de build normal. Usa `cargo build —release` para hacer un release\n" +"optimizado del build en `target/release/`." + +#: src/cargo/running-locally.md:62 +msgid "" +"7. You can add dependencies for your project by editing `Cargo.toml`. When you\n" +" run `cargo` commands, it will automatically download and compile missing\n" +" dependencies for you." +msgstr "" +"7. Puedes agregar dependencias para trueque proyecto editando `cargo.toml`. Cuando corres\n" +"el comando `cargo`, automáticamente descargará y compilará las dependencias faltantes." + +#: src/cargo/running-locally.md:66 +msgid "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" +msgstr "" + +#: src/cargo/running-locally.md:70 +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 "" +"Trata de motivar a los participantes de la clase para instalar Cargo y usar un editor\n" +"de código local. Esto hará que tu vida sea más fácil porque tienen un IDE normal." + +#: src/welcome-day-1.md:1 +msgid "# Welcome to Day 1" +msgstr "# Bienvenido al Día 1" + +#: src/welcome-day-1.md:3 +msgid "" +"This is the first day of Comprehensive Rust. We will cover a lot of ground\n" +"today:" +msgstr "Este es el primer día de Comprehensive Rust. Cubririemos un montón de contenido:" + +#: src/welcome-day-1.md:6 +msgid "" +"* Basic Rust syntax: variables, scalar and compound types, enums, structs,\n" +" references, functions, and methods." +msgstr "" +"* sintaxis básica Rust: variables, scalar y tipos compuestos, enums, structs, \n" +" references, funciones, y métodos." + +#: src/welcome-day-1.md:9 +msgid "" +"* Memory management: stack vs heap, manual memory management, scope-based memory\n" +" management, and garbage collection." +msgstr "" +"* Manejo de memoria: stack vs heap, manejo manual de memoria, manejo de memoria \n" +"scope-based, y garaje collection." + +#: src/welcome-day-1.md:12 +msgid "* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." +msgstr "* Ownsership: manejo semántico, copiar y clonar, préstamos, y tiempo de vida." + +#: src/welcome-day-1.md:16 +msgid "Please remind the students that:" +msgstr "Por favor recuerda a los estudiantes que:" + +#: src/welcome-day-1.md:18 +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" +"* 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 "" +"* Deben hacer las preguntas cuando surgen, no las guarden hasta el final.\n" +"* La clase tiene la intención de ser interactiva y también para abrir espacios de debate.\n" +" * Como instructor, debes intentar llevar discusiones relevantes, por ejemplo,\n" +" mantener relación de cómo Rust hace las cosas vs otros lenguajes. Puede\n" +" costar encontrar un balance adecuado, pero permite llevar un debate\n" +" que atraiga la atención de la gente por sobre un discurso unidireccional.\n" +"* Las preguntas deberían ser sobre cosas acerca del contenido de los slides.\n" +" * Esto está perfecto! Repetir es una parte importante del aprendizaje. Recuerda\n" +" que los slides son solo un soporte y tienes libertad de saltearlos cuando quieras." + +#: src/welcome-day-1.md:29 +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 "" +"La idea del primer día es mostar _solo lo necesario_ de Rust para permitir hablar\n" +"sobre el famoso borrow checker. La manera que Rust maneja la memoria es la principal " +"característica\n" +"y debemos mostrar a los estudiantes la manera correcta." + +#: src/welcome-day-1.md:33 +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 "" +"Si estás enseñando esto en una clase, es un buen lugar para repasar el\n" +"horario. Sugerimos dividir el día en dos partes (guiándose por los slides):" + +#: src/welcome-day-1.md:36 +msgid "" +"* Morning: 9:00 to 12:00,\n" +"* Afternoon: 13:00 to 16:00." +msgstr "" +"* Mañana: 9:00 to 12:00,\n" +"* Tarde: 13:00 to 16:00." + +#: src/welcome-day-1.md:39 +msgid "" +"You can of course adjust this as necessary. Please make sure to include breaks,\n" +"we recommend a break every hour!" +msgstr "" +"Claro que puedes modificarlo si es necesario. Por favor asegúrate de incluir breaks,\n" +"Recomendamos un break cada hora!" + +#: src/welcome-day-1/what-is-rust.md:1 +msgid "# What is Rust?" +msgstr "# Qué es Rust?" + +#: src/welcome-day-1/what-is-rust.md:3 +msgid "Rust is a new programming language which had its [1.0 release in 2015][1]:" +msgstr "Rust es un nuevo lenguaje que tiene su [release 1.0 en 2015][1]:" + +#: src/welcome-day-1/what-is-rust.md:5 +msgid "" +"* Rust is a statically compiled language in a similar role as C++\n" +" * `rustc` uses LLVM as its backend.\n" +"* Rust supports many [platforms and\n" +" architectures](https://doc.rust-lang.org/nightly/rustc/platform-support.html):\n" +" * x86, ARM, WebAssembly, ...\n" +" * Linux, Mac, Windows, ...\n" +"* Rust is used for a wide range of devices:\n" +" * firmware and boot loaders,\n" +" * smart displays,\n" +" * mobile phones,\n" +" * desktops,\n" +" * servers." +msgstr "" +"* Rust es un lenguaje compilado estático similar a C++\n" +" * `rustc` usa LLVM como backend.\n" +"* Rust soporta muchas [platformas y\n" +" arquitecturas](https://doc.rust-lang.org/nightly/rustc/platform-support.html):\n" +" * x86, ARM, WebAssembly, …\n" +" * Linux, Mac, Windows, …\n" +"* Rust es usado en muchos dispositivos:\n" +" * firmware y boot loaders,\n" +" * smart displays,\n" +" * mobile phones,\n" +" * desktops,\n" +" * servers." + +#: src/welcome-day-1/what-is-rust.md:21 +msgid "Rust fits in the same area as C++:" +msgstr "Rust encaja en el mismo área de C++:" + +#: src/welcome-day-1/what-is-rust.md:23 +msgid "" +"* High flexibility.\n" +"* High level of control.\n" +"* Can be scaled down to very constrained devices like mobile phones.\n" +"* Has no runtime or garbage collection.\n" +"* Focuses on reliability and safety without sacrificing performance." +msgstr "" +"* Alta flexibilidad.\n" +"* Alto nivel de control.\n" +"* Puede usarse en dispositivos limitados como teléfonos celulares\n" +"* No tiene runtime o garbage colector.\n" +"* Se enfoca en la confiabilidad y seguridad sin sacrificar performance." + +#: src/welcome-day-1/what-is-rust.md:31 +msgid "[1]: https://blog.rust-lang.org/2015/05/15/Rust-1.0.html" +msgstr "" + +#: src/hello-world.md:1 +msgid "# Hello World!" +msgstr "# Hola Mundo!" + +#: src/hello-world.md:3 +msgid "" +"Let us jump into the simplest possible Rust program, a classic Hello World\n" +"program:" +msgstr "Vayamos al ejemplo de programa Rust más simple, un clásico Hola Mundo:" + +#: src/hello-world.md:6 +msgid "" +"```rust\n" +"fn main() {\n" +" println!(\"Hello 🌍!\");\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn main() {\n" +" println!(\"Hola 🌍!\");\n" +"}\n" +"```" + +#: src/hello-world.md:12 +msgid "What you see:" +msgstr "Qué ves:" + +#: src/hello-world.md:14 +msgid "" +"* Functions are introduced with `fn`.\n" +"* Blocks are delimited by curly braces like in C and C++.\n" +"* The `main` function is the entry point of the program.\n" +"* Rust has hygienic macros, `println!` is an example of this.\n" +"* Rust strings are UTF-8 encoded and can contain any Unicode character." +msgstr "" +"* Funciones agregadas con `fn`.\n" +"* Bloques delimitados por llaves como en C y C++.\n" +"* La función `main` que es el punto de entrada al programa.\n" +"* Rust tiene macros limpios, `println!` es un ejemplo de esto.\n" +"* Strings Rust son codificados UTF-8 y pueden contener cualquier carácter Unicode." + +#: src/hello-world.md:22 +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 "" +"Este slide intenta que los estudiantes se sientan cómodos con código Rust. Verán\n" +"mucho de esto los siguientes cuatro días ase que empezaremos con algo rápido y familiar." + +#: src/hello-world.md:27 +msgid "" +"* Rust is very much like other languages in the C/C++/Java tradition. It is\n" +" imperative (not functional) and it doesn't try to reinvent things unless\n" +" absolutely necessary." +msgstr "" +"* Rust es similar a otros lenguajes tradicionales como C/C++/Java. Es\n" +"imperativo (no funcional) y no trata de reinventar cosas a menos que\n" +"sea absolutamente necesario." + +#: src/hello-world.md:31 +msgid "* Rust is modern with full support for things like Unicode." +msgstr "*Rust es moderno con soporte completo para cosas como Unicode." + +#: src/hello-world.md:33 +msgid "" +"* Rust uses macros for situations where you want to have a variable number of\n" +" arguments (no function [overloading](basic-syntax/functions-interlude.md))." +msgstr "" +"* Rust usa macros para situaciones donde quieres tener una variable number o\n" +"arguments (no funciones [overloading](basic-syntax/functions-interlude.md))." + +#: src/hello-world/small-example.md:1 +msgid "# Small Example" +msgstr "# Ejemplo Rápido" + +#: src/hello-world/small-example.md:3 +msgid "Here is a small example program in Rust:" +msgstr "Aquí tenemos un ejemplo de un programa Rust:" + +#: src/hello-world/small-example.md:5 +msgid "" +"```rust,editable\n" +"fn main() { // Program entry point\n" +" let mut x: i32 = 6; // Mutable variable binding\n" +" print!(\"{x}\"); // Macro for printing, like printf\n" +" while x != 1 { // No parenthesis around expression\n" +" if x % 2 == 0 { // Math like in other languages\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +" print!(\" -> {x}\");\n" +" }\n" +" println!();\n" +"}\n" +"```" +msgstr "" +"```rust,editable\n" +"fn main() { // Punto de entrada del programa\n" +" let mut x: i32 = 6; // Variable mutable vinculante\n" +" print!(\"{x}\"); // Macro para printing, como printf\n" +" while x != 1 { // Sin paréntesis alrededor de las expresiones\n" +" if x % 2 == 0 { // Operaciones matemáticas como en otros lenguajes\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +" print!(\" -> {x}\");\n" +" }\n" +" println!();\n" +"}\n" +"```" + +#: src/hello-world/small-example.md:23 +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 "" +"El código implementa la conjetura de Collatz: que dice que un bucle\n" +"siempre termina, pero no siempre se prueba. Modifica el código y prueba\n" +"diferentes inputs." + +#: src/hello-world/small-example.md:29 +msgid "" +"* Explain that all variables are statically typed. Try removing `i32` to trigger\n" +" type inference. Try with `i8` instead and trigger a runtime integer overflow." +msgstr "" +"* Explica que todas las variables son de tipo estáticas. Prueba removiendo `i32` para\n" +"que se dispare la inferencia de tipos. Intenta con `i8` y ejecuta un overflow de integer." + +#: src/hello-world/small-example.md:32 +msgid "* Change `let mut x` to `let x`, discuss the compiler error." +msgstr "* Cambia `let mut x` a `let x`, debatan sobre el error de compilación." + +#: src/hello-world/small-example.md:34 +msgid "" +"* Show how `print!` gives a compilation error if the arguments don't match the\n" +" format string." +msgstr "" +"* Muestra como `print!` da un error de compilación si el argumento no es el mismo del\n" +"formato del string." + +#: src/hello-world/small-example.md:37 +msgid "" +"* Show how you need to use `{}` as a placeholder if you want to print an\n" +" expression which is more complex than just a single variable." +msgstr "" +"* Muestra como necesitas usar `{}` como placeholder si quieres imprimir una\n" +" expresión la cual es más compleja que una simple variable." + +#: src/hello-world/small-example.md:40 +msgid "" +"* Show the students the standard library, show them how to search for `std::fmt`\n" +" 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 "" +"* Muestra a los estudiantes la librería estándar, muestra como buscar con `std::fmt`\n" +" la cual quiene reglas de un mini-lenguaje de formato. Es importante que los\n" +" estudiantes se familiaricen con las búsquedas en la librería estándar." + +#: src/why-rust.md:1 +msgid "# Why Rust?" +msgstr "# ¿Por qué Rust?" + +#: src/why-rust.md:3 +msgid "Some unique selling points of Rust:" +msgstr "Algunas características únicas de Rust:" + +#: src/why-rust.md:5 +msgid "" +"* Compile time memory safety.\n" +"* Lack of undefined runtime behavior.\n" +"* Modern language features." +msgstr "" +"* Tiempo de compilación Garantizado.\n" +"* Garantía en Tiempo de Ejecución.\n" +"* Características Modernas." + +#: src/why-rust.md:11 +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 "" +"Asegúrate de preguntar a la clase en qué lenguajes tienen experiencia. Dependiendo\n" +"de la respuesta puedes destacar diferentes características de Rust:" + +#: src/why-rust.md:14 +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" +" have the memory unsafety issues. In addition, you get a modern language with\n" +" constructs like pattern matching and built-in dependency management." +msgstr "" +"* Experiencia con C o C++: Rust elimina todos los _runtime erorrs_\n" +"vía el _borrow checker_. Puedes obtener misma performance de C y C++, pero no\n" +"tienes errores con manejo de memoria no seguro. Además, tienes un lenguaje moderno con\n" +"con constructores como patera matching y manejo de dependencias integrado." + +#: src/why-rust.md:19 +msgid "" +"* Experience with Java, Go, Python, JavaScript...: You get the same memory safety\n" +" as in those languages, plus a similar high-level language feeling. In addition\n" +" 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 "" +"* Experiencia con Java, Go, Python, JavaScript…: Tienes el mismo manejo de memoria\n" +" seguro en esos lenguajes, más una sensación de performance similar a un lenguaje de alto nivel. " +"Además\n" +" tienes la performance de C y C++ (sin garaje colector)\n" +" Así como acceso de bajo nivel a hardware (podrías necesitarlo)" + +#: src/why-rust/compile-time.md:1 +msgid "# Compile Time Guarantees" +msgstr "# Tiempo de Compilación Garantizado" + +#: src/why-rust/compile-time.md:3 +msgid "Static memory management at compile time:" +msgstr "Manejo de memoria estático en tiempo de compilación:" + +#: src/why-rust/compile-time.md:5 +msgid "" +"* No uninitialized variables.\n" +"* No memory leaks (_mostly_, see notes).\n" +"* No double-frees.\n" +"* No use-after-free.\n" +"* No `NULL` pointers.\n" +"* No forgotten locked mutexes.\n" +"* No data races between threads.\n" +"* No iterator invalidation." +msgstr "" +"* No hay variables sin inicializar.\n" +"* No hay memory leaks (_casi siempre_, ver notas).\n" +"* No hay double-frees.\n" +"* No use-after-free.\n" +"* No `NULL` pointers.\n" +"* No puedes olvidar mutexes bloqueados.\n" +"* No hay race-conditions por datos entre hilos.\n" +"* No hay iteradores inválidos." + +#: src/why-rust/compile-time.md:16 +msgid "" +"It is possible to produce memory leaks in (safe) Rust. Some examples\n" +"are:" +msgstr "" +"Es posible hacer memory learks en Rust (seguro). Algunos ejemplos\n" +"son:" + +#: src/why-rust/compile-time.md:19 +msgid "" +"* You can for 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" +"* You can also accidentally create a [reference cycle] with `Rc` or\n" +" `Arc`.\n" +"* In fact, some will consider infinitely populating a collection a memory\n" +" leak and Rust does not protect from those." +msgstr "" +"* Puedes usar [`Box::leak`] para hacer un leak de un puntero. El uso de de esto puede\n" +"ser para obtener variables inicializadas en tiempo de ejecución o modificando su tamaño.\n" +"* Puedes usar [`std::mem::forget`] para hacer que el compilador \"olvide\" un valor (así no se corre el destructor).\n" +"* También accidentalmente puedes crear un [ciclo de referencia] con `Rc` o `Arc`.\n" +"* De hecho, algunos considerarán cargar datos infinitamente una colección un\n" +"desbordamiento de memoria que Rust no protegerá." + +#: src/why-rust/compile-time.md:28 +msgid "" +"For the purpose of this course, \"No memory leaks\" should be understood\n" +"as \"Pretty much no *accidental* memory leaks\"." +msgstr "" +"Para el propósito de este curso, \"No memory leak\" debe entenderse\n" +"como \"Ningún tipo de memory leak *accidental*\"." + +#: src/why-rust/compile-time.md:31 +msgid "" +"[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak\n" +"[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" +"[reference cycle]: https://doc.rust-lang.org/book/ch15-06-reference-cycles.html" +msgstr "" +"[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak\n" +"[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" +"[ciclo de referencia]: https://doc.rust-lang.org/book/ch15-06-reference-cycles.html" + +#: src/why-rust/runtime.md:1 +msgid "# Runtime Guarantees" +msgstr "# Garantías en Tiempo de Ejecución" + +#: src/why-rust/runtime.md:3 +msgid "No undefined behavior at runtime:" +msgstr "Sin estados indefinidos en runtime:" + +#: src/why-rust/runtime.md:5 +msgid "" +"* Array access is bounds checked.\n" +"* Integer overflow is defined." +msgstr "" +"* Se verifican los límites de acceso a un Array.\n" +"* Se define el overflow de Integer." + +#: src/why-rust/runtime.md:12 +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" +" semantics. By default, you get panics in debug mode (`cargo build`)\n" +" and wrap-around in release mode (`cargo build --release`)." +msgstr "" +"* El overflow en Integer es definido vía un flan en tiempo de compilación. Las opciones son\n" +"alertas panic (un crash controlado del programa) o una semántica que lo envuelve. Por defecto, " +"obtienes el alerta en modo depuración (`cargo build`) y envolviéndolo en el modo release (`cargo " +"build —release`)." + +#: src/why-rust/runtime.md:17 +msgid "" +"* Bounds checking cannot be disabled with a compiler flag. It can also\n" +" not be disabled directly with the `unsafe` keyword. However,\n" +" `unsafe` allows you to call functions such as `slice::get_unchecked`\n" +" which does not do bounds checking." +msgstr "" +"* El chequeo de límites no puede ser desactivado con el flag de compilador. Tampoco\n" +" puede deshabilitarse directamente usando `unsafe`. Sin embargo,\n" +" `unsafe` permite que llames a la función como `slice::get_unchecked`\n" +" que no brinda chequeos de límites." + +#: src/why-rust/modern.md:1 +msgid "# Modern Features" +msgstr "# Características Modernas" + +#: src/why-rust/modern.md:3 +msgid "Rust is built with all the experience gained in the last 40 years." +msgstr "Rust está hecho con toda la experiencia ganada en 40 años." + +#: src/why-rust/modern.md:5 +msgid "## Language Features" +msgstr "## Características del Lenguaje" + +#: src/why-rust/modern.md:7 +msgid "" +"* Enums and pattern matching.\n" +"* Generics.\n" +"* No overhead FFI.\n" +"* Zero-cost abstractions." +msgstr "" +"* Enums y pattern matching.\n" +"* Genericos.\n" +"* No overhead FFI.\n" +"* Abstracciones Zero-cost." + +#: src/why-rust/modern.md:12 +msgid "## Tooling" +msgstr "## Herramientas" + +#: src/why-rust/modern.md:14 +msgid "" +"* Great compiler errors.\n" +"* Built-in dependency manager.\n" +"* Built-in support for testing.\n" +"* Excellent Language Server Protocol support." +msgstr "" +"* Gran compilador de errores.\n" +"* Manejador de Dependencias integrado.\n" +"* Soporte de testing integrado.\n" +"* Excelente soporte al Protocolo de Lenguaje de Servidor." + +#: src/why-rust/modern.md:23 +msgid "" +"* Zero-cost abstractions, similar to C++, means that you don't have to 'pay'\n" +" for higher-level programming constructs with memory or CPU. For example,\n" +" writing a loop using `for` should result in roughly the same low level\n" +" instructions as using the `.iter().fold()` construct." +msgstr "" +"* Sin costo en abstracciones, similar a C++, quiere decir que no tienes que ‘pagar’\n" +" por tener un un lenguaje de alto nivel con memoria o CPU. Por ejemplo,\n" +" escribiendo un loop usando `for` debe resultar a bajo nivel\n" +" en una instrucción que usa `.iter().fold()`." + +#: src/why-rust/modern.md:28 +msgid "" +"* It may be worth mentioning that Rust enums are 'Algebraic Data Types', also\n" +" known as 'sum types', which allow the type system to express things like\n" +" `Option` and `Result`." +msgstr "" +"* Cabe mencionar que los enums de Rust son ‘Tipos de Datos Algebraicos’, también\n" +" conocidos como ‘tipos sumados’, los cuales permiten el tipo de sistema para expresas cosas como\n" +" `Option` y `Result`." + +#: src/why-rust/modern.md:32 +msgid "" +"* Remind people to read the errors --- many developers have gotten used to\n" +" ignore lengthy compiler output. The Rust compiler is significantly more\n" +" talkative than other compilers. It will often provide you with _actionable_\n" +" feedback, ready to copy-paste into your code." +msgstr "" +"* Recuerda a las personas de leer los errores --- muchos programadores olvidan leer\n" +" la salida del compilador. El compilador de Rust es significativamente más\n" +" descriptivo que otros compiladores. Y frecuentemente provee un feedback\n" +" _para tomar acción_, con código listo para copiar y pegar." + +#: src/why-rust/modern.md:37 +msgid "" +"* The Rust standard library is small compared to languages like Java, Python,\n" +" and Go. Rust does not come with several things you might consider standard and\n" +" essential:" +msgstr "" +"* La librería estándar de Rust es pequeña comparada a otros lenguajes como Java, Python y Go.\n" +"Rust no viene con varias cosas que puedes considerar estándar y\n" +"esencial:" + +#: src/why-rust/modern.md:41 +msgid "" +" * a random number generator, but see [rand].\n" +" * support for SSL or TLS, but see [rusttls].\n" +" * support for JSON, but see [serde_json]." +msgstr "" +" * un generador de número random, pero mira [rand].\n" +" * soporte para SSL o TLS, pero mira [rusttls].\n" +" * soporte para JSON, pero mira [serde_json]." + +#: src/why-rust/modern.md:45 +msgid "" +" The reasoning behind this is that functionality in the standard library cannot\n" +" go away, so it has to be very stable. For the examples above, the Rust\n" +" community is still working on finding the best solution --- and perhaps there\n" +" isn't a single \"best solution\" for some of these things." +msgstr "" +" Las razones detrás de esta funcionalidad es la librería estándar que no puede\n" +"separarse, porque este tiene que ser muy estable. Para ejemplos de arriba, la comunidad\n" +"Rust sigue trabajando en encontrar la mejor solución --- y por ejemplo no hay\n" +"una única \"mejor solución\" para alguna de esas cosas." + +#: src/why-rust/modern.md:50 +msgid "" +" Rust comes with a built-in package manager in the form of Cargo and this makes\n" +" it trivial to download and compile third-party crates. A consequence of this\n" +" is that the standard library can be smaller." +msgstr "" +" Rust trae incluido un package manager en la forma de Cargo y hace\n" +"trivial descargar y compilador cosas autocontenidas. Como consecuencia\n" +"la librería estándar puede ser pequeña." + +#: src/why-rust/modern.md:54 +msgid "" +" Discovering good third-party crates can be a problem. Sites like\n" +" help with this by letting you compare health metrics for\n" +" crates to find a good and trusted one.\n" +" \n" +"* [rust-analyzer] is a well supported LSP implementation used in major\n" +" IDEs and text editors." +msgstr "" +" Descubrir paquetes de terceros puede ser un problema. Sitios como\n" +" ayudará con esto permitiéndote comparar calidad de\n" +" paquetes para encontrar uno bueno y seguro.\n" +"\n" +"* [rust-analizer] es un LSP bien soportado e implementado usado en los \n" +" principales IDEs y editores." + +#: src/why-rust/modern.md:61 +msgid "" +"[rand]: https://docs.rs/rand/\n" +"[rusttls]: https://docs.rs/rustls/\n" +"[serde_json]: https://docs.rs/serde_json/\n" +"[rust-analyzer]: https://rust-analyzer.github.io/" +msgstr "" +"[rand]: https://docs.rs/rand/\n" +"[rusttls]: https://docs.rs/rustls/\n" +"[serde_json]: https://docs.rs/serde_json/\n" +"[rust-analyzer]: https://rust-analyzer.github.io/" + +#: src/basic-syntax.md:1 +msgid "# Basic Syntax" +msgstr "# Sintáxis Básica" + +#: src/basic-syntax.md:3 +msgid "Much of the Rust syntax will be familiar to you from C, C++ or Java:" +msgstr "Mucho de la sintaxis de Rust es parecido a C, C++ o Java:" + +#: src/basic-syntax.md:5 +msgid "" +"* Blocks and scopes are delimited by curly braces.\n" +"* Line comments are started with `//`, block comments are delimited by `/* ...\n" +" */`.\n" +"* Keywords like `if` and `while` work the same.\n" +"* Variable assignment is done with `=`, comparison is done with `==`." +msgstr "" +"* Bloques y ámbitos delimitados por llaves.\n" +"* Comentarios de línea que comienzan con `//`, bloques de comentarios delimitados por `/*…\n" +" */`.\n" +"* Palabras claves como `if` y `while` funcionan igual.\n" +"* Asignación de variables hechas con `=`, comparaciones con `==`." + +#: src/basic-syntax/scalar-types.md:1 +msgid "# Scalar Types" +msgstr "# Tipos Escalares" + +#: src/basic-syntax/scalar-types.md:3 +msgid "" +"| | Types | " +"Literals |\n" +"|------------------------|--------------------------------------------|-------------------------------|\n" +"| Signed integers | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `-10`, `0`, `1_000`, " +"`123i64` |\n" +"| Unsigned integers | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, " +"`10u16` |\n" +"| Floating point numbers | `f32`, `f64` | `3.14`, `-10.0e20`, " +"`2f32` |\n" +"| Strings | `&str` | `\"foo\"`, `r#\"\\\\" +"\"#` |\n" +"| Unicode scalar values | `char` | `'a'`, `'α'`, " +"`'∞'` |\n" +"| Byte strings | `&[u8]` | `b\"abc\"`, `br#\" \" " +"\"#` |\n" +"| Booleans | `bool` | `true`, " +"`false` |" +msgstr "" + +#: src/basic-syntax/scalar-types.md:13 +msgid "The types have widths as follows:" +msgstr "Los tipos tienen una capacidad así:" + +#: src/basic-syntax/scalar-types.md:15 +msgid "" +"* `iN`, `uN`, and `fN` are _N_ bits wide,\n" +"* `isize` and `usize` are the width of a pointer,\n" +"* `char` is 32 bit wide,\n" +"* `bool` is 8 bit wide." +msgstr "" +"* `iN`, `uN`, and `fN` son _N_ bits de capacidad,\n" +"* `isize` y `usize` tienen el tamaño de un puntero,\n" +"* `char` es 32 bit de grande,\n" +"* `bool` es 8 bit de grande." + +#: src/basic-syntax/compound-types.md:1 +msgid "# Compound Types" +msgstr "# Tipos Compuestos" + +#: src/basic-syntax/compound-types.md:3 +msgid "" +"| | Types | Literals |\n" +"|--------|-------------------------------|-----------------------------------|\n" +"| Arrays | `[T; N]` | `[20, 30, 40]`, `[0; 3]` |\n" +"| Tuples | `()`, `(T,)`, `(T1, T2)`, ... | `()`, `('x',)`, `('x', 1.2)`, ... |" +msgstr "" + +#: src/basic-syntax/compound-types.md:8 +msgid "Array assignment and access:" +msgstr "Asignación y acceso a los Arrays:" + +#: src/basic-syntax/compound-types.md:10 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut a: [i8; 10] = [42; 10];\n" +" a[5] = 0;\n" +" println!(\"a: {:?}\", a);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/compound-types.md:18 +msgid "Tuple assignment and access:" +msgstr "Asignación y acceso a Tuplas:" + +#: src/basic-syntax/compound-types.md:20 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let t: (i8, bool) = (7, true);\n" +" println!(\"1st index: {}\", t.0);\n" +" println!(\"2nd index: {}\", t.1);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/compound-types.md:32 +msgid "Arrays:" +msgstr "" + +#: src/basic-syntax/compound-types.md:34 +msgid "" +"* Arrays have elements of the same type, `T`, and length, `N`, which is a compile-time constant.\n" +" Note that the length of the array is *part of its type*, which means that `[u8; 3]` and\n" +" `[u8; 4]` are considered two different types." +msgstr "" +"* Los Arrays tienen elementos del mismo tipo, `T`, y tamaño, `N` que es constante en compilación.\n" +" Nota que el tamaño del array es *parte del tipo*, lo que quiere decir que `[u8; 3]` y \n" +" `[u8; 4]`son considerados dos tipos diferentes." + +#: src/basic-syntax/compound-types.md:38 +msgid "* We can use literals to assign values to arrays." +msgstr "* Podemos usar literales para asignar valores a arreglos." + +#: src/basic-syntax/compound-types.md:40 +msgid "" +"* In the main function, the print statement asks for the debug implementation with the `?` format\n" +" parameter: `{}` gives the default output, `{:?}` gives the debug output. We\n" +" could also have used `{a}` and `{a:?}` without specifying the value after the\n" +" format string." +msgstr "" +"* En la función main, la palabra print pregunta por la implementación de debug con `?` para el " +"formato de parámetro: `{}` que da una salida estándar, `{:?}`. También podemos usar `{a}` y `{a:?} " +"sin especificar los valores luego del formato string." + +#: src/basic-syntax/compound-types.md:45 +msgid "* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read." +msgstr "" +"* Agregar `#`, por ejemplo `{a:#?}` invoca un formato para imprimir más lindo, más fácil de leer." + +#: src/basic-syntax/compound-types.md:47 +msgid "Tuples:" +msgstr "Tuplas:" + +#: src/basic-syntax/compound-types.md:49 +msgid "* Like arrays, tuples have a fixed length." +msgstr "* Como los array, las duplas tienen un tamaño fijo." + +#: src/basic-syntax/compound-types.md:51 +msgid "* Tuples group together values of different types into a compound type." +msgstr "* Las Tuplas es un grupo de valores con diferentes tipos formando un tipo compuesto." + +#: src/basic-syntax/compound-types.md:53 +msgid "" +"* Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`." +msgstr "" +"* Los campos de una Tuplas se acceden con un punto y el índice del valor, por ejemplo: `t.0`, " +"`t.1`." + +#: src/basic-syntax/compound-types.md:55 +msgid "" +"* The empty tuple `()` is also known as the \"unit type\". It is both a type, and\n" +" the only valid value of that type - that is to say both the type and its value\n" +" are expressed as `()`. It is used to indicate, for example, that a function or\n" +" expression has no return value, as we'll see in a future slide. \n" +" * You can think of it as `void` that can be familiar to you from other \n" +" programming languages." +msgstr "" +"* A una Tupla vacía `()` se la conoce también como \"unit type\". Ambos son tipos, y\n" +"la única manera válida de valor de ese tipo es nombrar ambos tipos y sus valores\n" +"que son expresados como `()`. Se usa para indicar, por ejemplo, que la función o\n" +"expresión no devuelve valor, como veremos más adelante.\n" +" * Puedes pensar en este como un `void` de otros lenguajes de programación." + +#: src/basic-syntax/references.md:1 +msgid "# References" +msgstr "# Referencias" + +#: src/basic-syntax/references.md:3 +msgid "Like C++, Rust has references:" +msgstr "Como C++, Rust tiene referencias:" + +#: src/basic-syntax/references.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x: i32 = 10;\n" +" let ref_x: &mut i32 = &mut x;\n" +" *ref_x = 20;\n" +" println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/references.md:14 +msgid "Some notes:" +msgstr "Algunos comentarios:" + +#: src/basic-syntax/references.md:16 +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 "" +"* Debemos referencias `ref_x` cuando lo asignamos, similar a los punteros de C o C++.\n" +"* Rust puede auto-referencias en algunos casos, en particular cuando hace invoca \n" +"métodos (intenta `ref_x.count_ones()`).\n" +"* Las referencias se declaran como `mut` y pueden cambiar de valor." + +#: src/basic-syntax/references.md:21 +msgid "" +"
\n" +"Key points:" +msgstr "" +"
\n" +"Presta atención:" + +#: src/basic-syntax/references.md:24 +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 "" +"* Asegúrate de poder diferenciar entre `let mut ref_x: &i32` y `let ref_x:\n" +" &mut i32`. El primero representa una referencia mutable que puede \n" +"cambiar de valor, mientras que el segundo representa una referencia con un valor que puede cambiar." + +#: src/basic-syntax/references-dangling.md:1 +msgid "# Dangling References" +msgstr "# Referencias Colgantes" + +#: src/basic-syntax/references-dangling.md:3 +msgid "Rust will statically forbid dangling references:" +msgstr "Rust estáticamente olvidará las referencias colgantes:" + +#: src/basic-syntax/references-dangling.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let ref_x: &i32;\n" +" {\n" +" let x: i32 = 10;\n" +" ref_x = &x;\n" +" }\n" +" println!(\"ref_x: {ref_x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/references-dangling.md:16 +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 "" +"* Se dice que una referencia \"toma prestado\" el valor al que se refiere.\n" +"* Rust registra la vida de todas las referencias para asegurar que perduran lo necesario.\n" +"* Hablaremos más de esto cuando veamos _ownership_." + +#: src/basic-syntax/slices.md:1 +msgid "# Slices" +msgstr "# Slices" + +#: src/basic-syntax/slices.md:3 +msgid "A slice gives you a view into a larger collection:" +msgstr "Un _slice_ nos da la visión a una colección:" + +#: src/basic-syntax/slices.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" +" println!(\"a: {a:?}\");" +msgstr "" + +#: src/basic-syntax/slices.md:10 +msgid "" +" let s: &[i32] = &a[2..4];\n" +" println!(\"s: {s:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/slices.md:15 +msgid "" +"* Slices borrow data from the sliced type.\n" +"* Question: What happens if you modify `a[3]`?" +msgstr "" +"* Slice toma prestado datos de un tipo _slice_.\n" +"* Pregunta: ¿Qué pasa si modificas `a[3]`?" + +#: src/basic-syntax/slices.md:20 +msgid "" +"* We create a slice by borrowing `a` and specifying the starting and ending indexes in brackets." +msgstr "" +"* Creamos un slice prestando `a` y especificando el comienzo y final de los índices entre " +"corchetes." + +#: src/basic-syntax/slices.md:22 +msgid "" +"* If the slice starts at index 0, Rust’s range syntax allows us to drop the starting index, " +"meaning that `&a[0..a.len()]` and `&a[..a.len()]` are identical.\n" +" \n" +"* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are identical." +msgstr "" +"* Si el slice empieza con índice 0, la sintaxis de rango de Rust nos permite borrar el índice del " +"comienzo, generando que `&a[0..a.len()]` y `&a[..a.len()]` sean idénticos.\n" +"\n" +"* Lo mismo es para el último índice, así que `&a[2..a.len()]` y `&a[2..]` son lo mismo." + +#: src/basic-syntax/slices.md:26 +msgid "* To easily create a slice of the full array, we can therefore use `&a[..]`." +msgstr "* Para crear fácil un slice de un array completo, podemos usar &a[..]." + +#: src/basic-syntax/slices.md:28 +msgid "" +"* `s` is a reference to a slice of `i32`s. Notice that the type of `s` (`&[i32]`) no longer " +"mentions the array length. This allows us to perform computation on slices of different sizes.\n" +" \n" +"* Slices always borrow from another object. In this example, `a` has to remain 'alive' (in scope) " +"for at least as long as our slice. \n" +" \n" +"* The question about modifying `a[3]` can spark an interesting discussion, but the answer is that " +"for memory safety reasons\n" +" you cannot do it through `a` after you created a slice, but you can read the data from both `a` " +"and `s` safely. \n" +" More details will be explained in the borrow checker section." +msgstr "" +"* `s` es una referencia a un slice de `i32`s. Tener en cuenta que en el tipo de `s` (`&[i32]`) no " +"se menciona el tamaño del array. Esto permite realizar cálculos en silces de diferentes tamaños.\n" +"* Los silbes siempre se prestan de otro objeto. En este ejemplo, `a` tiene que permanecer " +"\"viva\" (en el scope) durante, al menos, el tiempo que dure nuestro segmento.\n" +"* La pregunta sobre modificar `a[3]` puede darnos un punto para una interesante discusión, pero la " +"respuesta es que por razones de memoria segura no puedes hacerlo a través de `a` luego de crear un " +"slice, pero puedes leer los datos para ambos de `a` y `s` de forma segura.\n" +"Se verá en más detalle en la sección de chequeo de préstamos." + +#: src/basic-syntax/string-slices.md:1 +msgid "# `String` vs `str`" +msgstr "" + +#: src/basic-syntax/string-slices.md:3 +msgid "We can now understand the two string types in Rust:" +msgstr "Ahora podemos entender los dos tipos de string en Rust:" + +#: src/basic-syntax/string-slices.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: &str = \"World\";\n" +" println!(\"s1: {s1}\");" +msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let s1: &str = \"Mundo\";\n" +" println!(\"s1: {s1}\");" + +#: src/basic-syntax/string-slices.md:10 +msgid "" +" let mut s2: String = String::from(\"Hello \");\n" +" println!(\"s2: {s2}\");\n" +" s2.push_str(s1);\n" +" println!(\"s2: {s2}\");\n" +" \n" +" let s3: &str = &s2[6..];\n" +" println!(\"s3: {s3}\");\n" +"}\n" +"```" +msgstr "" +" let mut s2: String = String::from(\"Hola \");\n" +" println!(\"s2: {s2}\");\n" +" s2.push_str(s1);\n" +" println!(\"s2: {s2}\");\n" +" \n" +" let s3: &str = &s2[6..];\n" +" println!(\"s3: {s3}\");\n" +"}\n" +"```" + +#: src/basic-syntax/string-slices.md:20 +msgid "Rust terminology:" +msgstr "Terminología Rust:" + +#: src/basic-syntax/string-slices.md:22 +msgid "" +"* `&str` an immutable reference to a string slice.\n" +"* `String` a mutable string buffer." +msgstr "" +"* `&str` es una referencia inmutable a un slice string.\n" +"* `String` es un buffer de string mutable." + +#: src/basic-syntax/string-slices.md:27 +msgid "" +"* `&str` introduces a string slice, which is an immutable reference to UTF-8 encoded string data \n" +" stored in a block of memory. String literals (`”Hello”`), are stored in the program’s binary." +msgstr "" +"* `&str` pone un string slice, que es una referencia inmutable a codificada con datos string " +"UTF-8 \n" +"guardados en un bloque de memoria. El literal String (`\"Hola\"`), se guarda en el binario del " +"programa." + +#: src/basic-syntax/string-slices.md:30 +msgid "" +"* Rust’s `String` type is a wrapper around a vector of bytes. As with a `Vec`, it is owned.\n" +" \n" +"* As with many other types `String::from()` creates a string from a string literal; `String::" +"new()` \n" +" creates a new empty string, to which string data can be added using the `push()` and " +"`push_str()` methods." +msgstr "" +"* El tipo `String` de Rust es un wrapper para un vector de bytes. Como con un `Vec`, tiene " +"dueño.\n" +"* Como con otros tipos `String::from()` crea un string desde un string literal; `String::new()` \n" +" crea un string vacío, con datos que pueden usarse con métodos `push()` y `push_str()`." + +#: src/basic-syntax/string-slices.md:35 +msgid "" +"* The `format!()` macro is a convenient way to generate an owned string from dynamic values. It \n" +" accepts the same format specification as `println!()`.\n" +" \n" +"* You can borrow `&str` slices from `String` via `&` and optionally range selection.\n" +" \n" +"* For C++ programmers: think of `&str` as `const char*` from C++, but the one that always points \n" +" to a valid string in memory. Rust `String` is a rough equivalent of `std::string` from C++ \n" +" (main difference: it can only contain UTF-8 encoded bytes and will never use a small-string " +"optimization).\n" +" \n" +"
" +msgstr "" +"* El macro `format!()` es una manera conveniente de generar un string con dueño desde un valor " +"dinámico. Esto\n" +" acepta los mismos formateo especificados como `println!()`.\n" +"* Puedes prestar silces `&str` de `String` con `&` y opcionalmente un rango seleccionado.\n" +"* Para programadores C++: piensa en `&str` como `const char` de C++, pero de una forma que los " +"punteros siempre son string válidos en memoria. El `String` Rust es un equivalente tosco a `std::" +"string` de C++ \n" +"(La principal diferencia: solo puede contener bytes codificados UTF-8 y nunca usar optimización de " +"small-string).\n" +"\n" +"
" + +#: src/basic-syntax/functions.md:1 +msgid "# Functions" +msgstr "# Funciones" + +#: src/basic-syntax/functions.md:3 +msgid "" +"A Rust version of the famous [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz) interview " +"question:" +msgstr "" +"Una versión Rust de la famosa pregunta para entrevistas con [FizzBuzz](https://en.wikipedia.org/" +"wiki/Fizz_buzz):" + +#: src/basic-syntax/functions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" fizzbuzz_to(20); // Defined below, no forward declaration needed\n" +"}" +msgstr "" +"```rust,editable\n" +"fn main() {\n" +" fizzbuzz_to(20); // Definida abajo, no necesitas declararla antes\n" +"}" + +#: src/basic-syntax/functions.md:10 +msgid "" +"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" +"}" +msgstr "" +"fn is_divisible_by(lhs: u32, rhs: u32) -> bool {\n" +" if rhs == 0 {\n" +" return false; // Un caso extremo, vuelve rápido\n" +" }\n" +" lhs % rhs == 0 // La última expreción en el bloque es la que devuelve valor\n" +"}" + +#: src/basic-syntax/functions.md:17 +msgid "" +"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" +"}" +msgstr "" +"fn fizzbuzz(n: u32) -> () { // No devolver valor implica devolver un tipo unit `()`\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" +"}" + +#: src/basic-syntax/functions.md:26 +msgid "" +"fn fizzbuzz_to(n: u32) { // `-> ()` is normally omitted\n" +" for i in 1..=n {\n" +" fizzbuzz(i);\n" +" }\n" +"}\n" +"```" +msgstr "" +"fn fizzbuzz_to(n: u32) { // `-> ()` por lo general se omite\n" +" for i in 1..=n {\n" +" fizzbuzz(i);\n" +" }\n" +"}\n" +"```" + +#: src/basic-syntax/functions.md:35 +msgid "" +"* We refer in `main` to a function written below. Neither forward declarations nor headers are " +"necessary. \n" +"* Declaration parameters are followed by a type (the reverse of some programming languages), then " +"a return type.\n" +"* The last expression in a function body (or any block) becomes the return value. Simply omit the " +"`;` 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." +msgstr "" +"* En `main` invocamos a una función escrita debajo. No es necesario hacer declaraciones para referenciar.\n" +"* La declaración de parámetros es por tipo (lo contrario a otros lenguajes), y devuelven tipo.\n" +"* La última expresión en una función (u otro bloque) es el tipo que devuelve. Y omite el `;` al final.\n" +"* Algunas funciones no devuelven valor y devuelven el `tipo unit`, `()`. El compilador va a inferir `->()` si es tipo a devolver es omitido.\n" +"* Las expresiones `for` en `fizzbuzz_to()` contienen `=n`, que incluye el límite superior.\n" +"* Los `match` en `fizzbuzz()` hacen mucho. Se detalla debajo." + +#: src/basic-syntax/functions.md:42 +msgid " (Type annotations added for clarity, but they can be elided.)" +msgstr " (Las anotaciones dan claridad, pero se pueden omitir)" + +#: src/basic-syntax/functions.md:44 +msgid "" +" ```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" +" ```" +msgstr "" + +#: src/basic-syntax/functions.md:52 +msgid " " +msgstr "" + +#: src/basic-syntax/methods.md:1 src/methods.md:1 +msgid "# Methods" +msgstr "# Métodos" + +#: src/basic-syntax/methods.md:3 +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:" +msgstr "" +"Rust tiene métodos, pero simplemente son funciones que están asociadas a un tipo particular. El " +"primer argumento de un método es una instancia de un tipo asociado con:" + +#: src/basic-syntax/methods.md:6 +msgid "" +"```rust,editable\n" +"struct Rectangle {\n" +" width: u32,\n" +" height: u32,\n" +"}" +msgstr "" + +#: src/basic-syntax/methods.md:12 +msgid "" +"impl Rectangle {\n" +" fn area(&self) -> u32 {\n" +" self.width * self.height\n" +" }" +msgstr "" + +#: src/basic-syntax/methods.md:17 +msgid "" +" fn inc_width(&mut self, delta: u32) {\n" +" self.width += delta;\n" +" }\n" +"}" +msgstr "" + +#: src/basic-syntax/methods.md:22 +msgid "" +"fn main() {\n" +" let mut rect = Rectangle { width: 10, height: 5 };\n" +" println!(\"old area: {}\", rect.area());\n" +" rect.inc_width(5);\n" +" println!(\"new area: {}\", rect.area());\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/methods.md:30 +msgid "* We will look much more at methods in today's exercise and in tomorrow's class." +msgstr "* Observaremos mucho más acerca de métodos en la clase de hoy a la tarde." + +#: src/basic-syntax/functions-interlude.md:1 +msgid "# Function Overloading" +msgstr "# Sobrecarga de Funciones" + +#: src/basic-syntax/functions-interlude.md:3 +msgid "Overloading is not supported:" +msgstr "La Sobrecarga no es soportada:" + +#: src/basic-syntax/functions-interlude.md:5 +msgid "" +"* Each function has a single implementation:\n" +" * Always takes a fixed number of parameters.\n" +" * Always takes a single set of parameter types.\n" +"* Default values are not supported:\n" +" * All call sites have the same number of arguments.\n" +" * Macros are sometimes used as an alternative." +msgstr "" +"* Cada función tiene una implementación simple:\n" +" * Siempre tiene un número fijo de parámetros.\n" +" * Siempre tiene un único conjunto de tipos de parámetros.\n" +"* Los valores por defecto no están soportados:\n" +" * Todas las llamadas tienen el mismo tipo de parámetro.\n" +" * Algunas veces como alternativa se usan macros." + +#: src/basic-syntax/functions-interlude.md:12 +msgid "However, function parameters can be generic:" +msgstr "Sin embargo, los parámetros de funciones pueden ser _generics_:" + +#: src/basic-syntax/functions-interlude.md:14 +msgid "" +"```rust,editable\n" +"fn pick_one(a: T, b: T) -> T {\n" +" if std::process::id() % 2 == 0 { a } else { b }\n" +"}" +msgstr "" +"```rust,editable\n" +"fn elegir_uno(a: T, b: T) -> T {\n" +" if std::process::id() % 2 == 0 { a } else { b }\n" +"}" + +#: src/basic-syntax/functions-interlude.md:19 +msgid "" +"fn main() {\n" +" println!(\"coin toss: {}\", pick_one(\"heads\", \"tails\"));\n" +" println!(\"cash prize: {}\", pick_one(500, 1000));\n" +"}\n" +"```" +msgstr "" +"fn main() {\n" +" println!(\"arrojar la moneda: {}\", elegir_uno(\"cara\", \"cruz\"));\n" +" println!(\"premio: {}\", elegir_uno(500, 1000));\n" +"}\n" +"```" + +#: src/basic-syntax/functions-interlude.md:27 +msgid "" +"* When using generics, the standard library's `Into` can provide a kind of limited\n" +" polymorphism on argument types. We will see more details in a later section." +msgstr "" +"* Cuando usas genéricos, la librería estándar `Into` puede dar un limitado \n" +" polimorfismo con tipo de parámetro. Lo veremos en detalle más adelante." + +#: src/basic-syntax/functions-interlude.md:30 +msgid "" +msgstr "" + +#: src/exercises/day-1/morning.md:1 +msgid "# Day 1: Morning Exercises" +msgstr "# Día 1: Ejercicios de la Mañana" + +#: src/exercises/day-1/morning.md:3 +msgid "In these exercises, we will explore two parts of Rust:" +msgstr "En estos ejercicios, exploraremos dos partes de Rust:" + +#: src/exercises/day-1/morning.md:5 +msgid "* Implicit conversions between types." +msgstr "* Conversiones implícitas entre tipos." + +#: src/exercises/day-1/morning.md:7 +msgid "* Arrays and `for` loops." +msgstr "* Arrays y loops `for`." + +#: src/exercises/day-1/morning.md:11 +msgid "A few things to consider while solving the exercises:" +msgstr "Algunas cosas a considerar mientras resolvemos los ejercicios:" + +#: src/exercises/day-1/morning.md:13 +msgid "" +"* Use a local Rust installation, if possible. This way you can get\n" +" auto-completion in your editor. See the page about [Using Cargo] for details\n" +" on installing Rust." +msgstr "" +"* Usar una instalación de Rust local, si es posible. De esta manera puedes tener\n" +" auto-complete en el editor. Puedes ver la página [Usando Cargo] para más detalles\n" +" en la instalación de Rust." + +#: src/exercises/day-1/morning.md:17 +msgid "* Alternatively, use the Rust Playground." +msgstr "* Como alternativa, puedes usar el Rust embebido." + +#: src/exercises/day-1/morning.md:19 +msgid "" +"The code snippets are not editable on purpose: the inline code snippets lose\n" +"their state if you navigate away from the page." +msgstr "" +"Los scnippets de código no son editables a propósito: el código de snippets inline pierden\n" +"su estado si navegas fuera de la página." + +#: 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 +msgid "After looking at the exercises, you can look at the [solutions] provided." +msgstr "Luego de ver los ejercicios, puedes ver las [soluciones] que se brindan." + +#: src/exercises/day-1/morning.md:24 src/exercises/day-2/morning.md:13 +#: src/exercises/day-3/morning.md:9 src/exercises/day-4/morning.md:14 +msgid "[solutions]: solutions-morning.md" +msgstr "[soluciones]: solutions-morning.md" + +#: src/exercises/day-1/morning.md:26 +msgid "[Using Cargo]: ../../cargo.md" +msgstr "[Usando Cargo]: ../../cargo.md" + +#: src/exercises/day-1/implicit-conversions.md:1 +msgid "# Implicit Conversions" +msgstr "# Conversiones Implícitas" + +#: src/exercises/day-1/implicit-conversions.md:3 +msgid "" +"Rust will not automatically apply _implicit conversions_ between types ([unlike\n" +"C++][3]). You can see this in a program like this:" +msgstr "" +"Rust no aplicará automáticamente _conversiones implícitas_ entre tipos ([como \n" +"C++][3]). Puedes ver esto en programas como este:" + +#: src/exercises/day-1/implicit-conversions.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"fn multiply(x: i16, y: i16) -> i16 {\n" +" x * y\n" +"}" +msgstr "" + +#: src/exercises/day-1/implicit-conversions.md:11 +msgid "" +"fn main() {\n" +" let x: i8 = 15;\n" +" let y: i16 = 1000;" +msgstr "" + +#: src/exercises/day-1/implicit-conversions.md:15 +msgid "" +" println!(\"{x} * {y} = {}\", multiply(x, y));\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/implicit-conversions.md:19 +msgid "" +"The Rust integer types all implement the [`From`][1] and [`Into`][2]\n" +"traits to let us convert between them. The `From` trait has a single `from()`\n" +"method and similarly, the `Into` trait has a single `into()` method.\n" +"Implementing these traits is how a type expresses that it can be converted into\n" +"another type." +msgstr "" +"El tipo integer de Rust implementa el [`From`][1] y [`Into`][2]\n" +"y trata de dejarnos para dejarnos convertir entre ellos. El `From` se trata como un simple \n" +"método `from()` y similar, el `Into` se trata como un simple método `into()`.\n" +"Implementando esto es como expresamos un tipo que puede convertirse a otro." + +#: src/exercises/day-1/implicit-conversions.md:25 +msgid "" +"The standard library has an implementation of `From for i16`, which means\n" +"that we can convert a variable `x` of type `i8` to an `i16` by calling \n" +"`i16::from(x)`. Or, simpler, with `x.into()`, because `From for i16`\n" +"implementation automatically create an implementation of `Into for i8`." +msgstr "" +"La librería estándar tiene una implementación de `From para i16`, que significa\n" +"Que podemos convertir la variable `x`de tipo `i8` a una `i16` llamando \n" +"`i16::from(x)`. O, más simple, con `x.into()`, porque la implementación `From para i16`\n" +"crea automáticamente una implementación de `Into para i8`." + +#: src/exercises/day-1/implicit-conversions.md:30 +msgid "" +"The same applies for your own `From` implementations for your own types, so it is\n" +"sufficient to only implement `From` to get a respective `Into` implementation automatically." +msgstr "" +"Lo mismo aplica para tu propia implementación `From` para tus propios tipos, así es\n" +"suficiente solo implementar `From` para obtener la respectiva implementación automática `Into`." + +#: src/exercises/day-1/implicit-conversions.md:33 +msgid "1. Execute the above program and look at the compiler error." +msgstr "1. Ejecuta el programa de arriba y mira el error de compilación." + +#: src/exercises/day-1/implicit-conversions.md:35 +msgid "2. Update the code above to use `into()` to do the conversion." +msgstr "2. Actualiza el código de arriba usando `into()` para hacer la conversión." + +#: src/exercises/day-1/implicit-conversions.md:37 +msgid "" +"3. Change the types of `x` and `y` to other things (such as `f32`, `bool`,\n" +" `i128`) to see which types you can convert to which other types. Try\n" +" converting small types to big types and the other way around. Check the\n" +" [standard library documentation][1] to see if `From` is implemented for\n" +" the pairs you check." +msgstr "" +"3. Cambia los tipos de `x` e `y` para otras cosas (como con `f32`, `bool`,\n" +"`i128`) para ver qué tipos puedes convertir a otros tipos. Intenta\n" +"convirtiendo tipos pequeños a grandes y a otros tipos disponibles. Revisa la\n" +"[documentación de la librería estándar][1] para ver si `From` se puede\n" +"implementar." + +#: src/exercises/day-1/implicit-conversions.md:43 +msgid "" +"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" +"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" +"[3]: https://en.cppreference.com/w/cpp/language/implicit_conversion" +msgstr "" + +#: src/exercises/day-1/for-loops.md:1 +msgid "# Arrays and `for` Loops" +msgstr "# Arrays y Loops `for`" + +#: src/exercises/day-1/for-loops.md:3 +msgid "We saw that an array can be declared like this:" +msgstr "Vimos que un array puede ser declarado así:" + +#: src/exercises/day-1/for-loops.md:5 +msgid "" +"```rust\n" +"let array = [10, 20, 30];\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:9 +msgid "You can print such an array by asking for its debug representation with `{:?}`:" +msgstr "Puedes imprimirlo para verlo y depurar código con `{:?}`:" + +#: src/exercises/day-1/for-loops.md:11 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" println!(\"array: {array:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:18 +msgid "" +"Rust lets you iterate over things like arrays and ranges using the `for`\n" +"keyword:" +msgstr "Rust permite iterar sobre cosas como array y arreglos usando `for`:" + +#: src/exercises/day-1/for-loops.md:21 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" print!(\"Iterating over array:\");\n" +" for n in array {\n" +" print!(\" {n}\");\n" +" }\n" +" println!();" +msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" print!(\"Iterando sobre el array:\");\n" +" for n in array {\n" +" print!(\" {n}\");\n" +" }\n" +" println!();" + +#: src/exercises/day-1/for-loops.md:30 +msgid "" +" print!(\"Iterating over range:\");\n" +" for i in 0..3 {\n" +" print!(\" {}\", array[i]);\n" +" }\n" +" println!();\n" +"}\n" +"```" +msgstr "" +" print!(\"Iterando sobre el rango:\");\n" +" for i in 0..3 {\n" +" print!(\" {}\", array[i]);\n" +" }\n" +" println!();\n" +"}\n" +"```" + +#: src/exercises/day-1/for-loops.md:38 +msgid "" +"Use the above to write a function `pretty_print` which pretty-print a matrix and\n" +"a function `transpose` which will transpose a matrix (turn rows into columns):" +msgstr "" +"Usa lo de arriba para escribir la función `linda_impresion` que es una matriz y\n" +"una función `trasponer` que trasponerá una matriz (cambia filas a columnas):" + +#: src/exercises/day-1/for-loops.md:41 +msgid "" +"```bob\n" +" ⎛⎡1 2 3⎤⎞ ⎡1 4 7⎤\n" +"\"transpose\"⎜⎢4 5 6⎥⎟ \"==\"⎢2 5 8⎥\n" +" ⎝⎣7 8 9⎦⎠ ⎣3 6 9⎦\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:47 +msgid "Hard-code both functions to operate on 3 × 3 matrices." +msgstr "Hardcodea ambas funciones para operar con matrices 3 x 3." + +#: src/exercises/day-1/for-loops.md:49 +msgid "" +"Copy the code below to and implement the\n" +"functions:" +msgstr "" +"Copia el código debajo para e implementa las\n" +"funciones:" + +#: src/exercises/day-1/for-loops.md:52 src/exercises/day-1/book-library.md:20 +#: src/exercises/day-2/health-statistics.md:13 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]" +msgstr "" +"```rust,should_panic\n" +"// TODO: borra esto cuando termines de implementarlo.\n" +"#![allow(unused_variables, dead_code)]" + +#: src/exercises/day-1/for-loops.md:56 +msgid "" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" unimplemented!()\n" +"}" +msgstr "" + +#: src/exercises/day-1/for-loops.md:60 +msgid "" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" unimplemented!()\n" +"}" +msgstr "" + +#: src/exercises/day-1/for-loops.md:64 +msgid "" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];" +msgstr "" + +#: src/exercises/day-1/for-loops.md:71 src/exercises/day-1/solutions-morning.md:70 +msgid "" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);" +msgstr "" + +#: src/exercises/day-1/for-loops.md:74 +msgid "" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:80 +msgid "## Bonus Question" +msgstr "## Preguntas Bonus" + +#: src/exercises/day-1/for-loops.md:82 +msgid "" +"Could you use `&[i32]` slices instead of hard-coded 3 × 3 matrices for your\n" +"argument and return types? Something like `&[&[i32]]` for a two-dimensional\n" +"slice-of-slices. Why or why not?" +msgstr "" +"Puedes usar silbes `&[i32]` en vez de hardcodear matrices 3 x 3 para tus\n" +"parámetros y devolver tipos? Cosas como `&[&[i32]]` para dos dimensiones,\n" +"slices de slices. Por qué sí o por qué no?" + +#: src/exercises/day-1/for-loops.md:87 +msgid "" +"See the [`ndarray` crate](https://docs.rs/ndarray/) for a production quality\n" +"implementation." +msgstr "" +"Mira el [ crates `ndarray`](https://docs.rs/ndarray/) para implementación con calidad de producción\n" +"de calidad." + +#: src/exercises/day-1/for-loops.md:92 +msgid "" +"The solution and the answer to the bonus section are available in the \n" +"[Solution](solutions-morning.md#arrays-and-for-loops) section." +msgstr "" +"Las soluciones y respuestas a la sección bonus están disponibles en\n" +"la sección [Solución](solutions-morning.md#arrays-and-for-loops)." + +#: src/basic-syntax/variables.md:1 +msgid "# Variables" +msgstr "" + +#: src/basic-syntax/variables.md:3 +msgid "" +"Rust provides type safety via static typing. Variable bindings are immutable by\n" +"default:" +msgstr "" +"Rust provee tipos seguros por tipado estático. El enlace a variables es inmutable\n" +"por defecto:" + +#: src/basic-syntax/variables.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x: i32 = 10;\n" +" println!(\"x: {x}\");\n" +" // x = 20;\n" +" // println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/variables.md:17 +msgid "" +"* Due to type inference the `i32` is optional. We will gradually show the types less and less as " +"the course progresses.\n" +"* Note that since `println!` is a macro, `x` is not moved, even using the function like syntax of " +"`println!(\"x: {}\", x)`" +msgstr "" +"* Dado a la inferencia de tipos `i32` es opcional. Poco a poco veremos los tipos a medida que " +"avance el curso.\n" +"* Nota que a partir que `println!` es una macro, `x` no se mueve, incluso usando una función como " +"`println!(\"x: {}\", x)`" + +#: src/basic-syntax/type-inference.md:1 +msgid "# Type Inference" +msgstr "# Tipo de inferencia" + +#: src/basic-syntax/type-inference.md:3 +msgid "Rust will look at how the variable is _used_ to determine the type:" +msgstr "Rust verá como _es usada_ la variable para determinar el tipo:" + +#: src/basic-syntax/type-inference.md:5 +msgid "" +"```rust,editable\n" +"fn takes_u32(x: u32) {\n" +" println!(\"u32: {x}\");\n" +"}" +msgstr "" + +#: src/basic-syntax/type-inference.md:10 +msgid "" +"fn takes_i8(y: i8) {\n" +" println!(\"i8: {y}\");\n" +"}" +msgstr "" + +#: src/basic-syntax/type-inference.md:14 +msgid "" +"fn main() {\n" +" let x = 10;\n" +" let y = 20;" +msgstr "" + +#: src/basic-syntax/type-inference.md:18 +msgid "" +" takes_u32(x);\n" +" takes_i8(y);\n" +" // takes_u32(y);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/type-inference.md:26 +msgid "" +"This slide demonstrates how the Rust compiler infers types based on constraints given by variable " +"declarations and usages.\n" +" \n" +"It is very important to emphasize that variables declared like this are not of some sort of " +"dynamic \"any type\" that can\n" +"hold any data. The machine code generated by such declaration is identical to the explicit " +"declaration of a type.\n" +"The compiler does the job for us and helps us write more concise code." +msgstr "" +"Este slide demuestra cómo el compilador de Rust infiere tipos basados en constrainst dadas por la " +"declaración de variables y los usos.\n" +"Es importante enfatizar que las variables declaradas como esta no son un conjunto dinámico de " +"\"cualquier tipo\" que puede contener todo tipo de datos. El código generado por esa declaración " +"es idéntica a la declaración explícita de un tipo.\n" +"El compilador hace el trabajo por nosotros y nos ayuda a escribir código más conciso." + +#: src/basic-syntax/type-inference.md:32 +msgid "" +"The following code tells the compiler to copy into a certain generic container without the code " +"ever explicitly specifying the contained type, using `_` as a placeholder:" +msgstr "" +"El siguiente código dice al compilador que copie en un contenedor genérico determinado sin que " +"explicitar específicamente el tipo contenido, usando `_` como un placeholder:" + +#: src/basic-syntax/type-inference.md:34 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut v = Vec::new();\n" +" v.push((10, false));\n" +" v.push((20, true));\n" +" println!(\"v: {v:?}\");" +msgstr "" + +#: src/basic-syntax/type-inference.md:41 +msgid "" +" let vv = v.iter().collect::>();\n" +" println!(\"vv: {vv:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/type-inference.md:46 +msgid "" +"[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.collect) relies " +"on `FromIterator`, which [`HashSet`](https://doc.rust-lang.org/std/iter/trait.FromIterator.html) " +"implements." +msgstr "" +"[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.collect) se basa " +"en `FromIterator` que lo implementa el [`HashSet`](https://doc.rust-lang.org/std/iter/trait." +"FromIterator.html)." + +#: src/basic-syntax/static-and-const.md:1 +msgid "# Static and Constant Variables" +msgstr "# Variables Estáticas y Constantes" + +#: src/basic-syntax/static-and-const.md:3 +msgid "Global state is managed with static and constant variables." +msgstr "El estado global es manejado con variables estáticas y constantes." + +#: src/basic-syntax/static-and-const.md:5 +msgid "## `const`" +msgstr "" + +#: src/basic-syntax/static-and-const.md:7 +msgid "You can declare compile-time constants:" +msgstr "Puedes declarar constantes en tiempo de compilación:" + +#: src/basic-syntax/static-and-const.md:9 +msgid "" +"```rust,editable\n" +"const DIGEST_SIZE: usize = 3;\n" +"const ZERO: Option = Some(42);" +msgstr "" + +#: src/basic-syntax/static-and-const.md:13 +msgid "" +"fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {\n" +" let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];\n" +" for (idx, &b) in text.as_bytes().iter().enumerate() {\n" +" digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE].wrapping_add(b);\n" +" }\n" +" digest\n" +"}" +msgstr "" + +#: src/basic-syntax/static-and-const.md:21 +msgid "" +"fn main() {\n" +" let digest = compute_digest(\"Hello\");\n" +" println!(\"Digest: {digest:?}\");\n" +"}\n" +"```" +msgstr "" +"fn main() {\n" +" let digest = compute_digest(\"Hola\");\n" +" println!(\"Digest: {digest:?}\");\n" +"}\n" +"```" + +#: src/basic-syntax/static-and-const.md:27 +msgid "According the the [Rust RFC Book][1] these are inlined upon use." +msgstr "De acuerdo con [Rust RFC Book][1] eso está en línea del uso." + +#: src/basic-syntax/static-and-const.md:29 +msgid "## `static`" +msgstr "" + +#: src/basic-syntax/static-and-const.md:31 +msgid "You can also declare static variables:" +msgstr "También puedes declarar variables estáticas:" + +#: src/basic-syntax/static-and-const.md:33 +msgid "" +"```rust,editable\n" +"static BANNER: &str = \"Welcome to RustOS 3.14\";" +msgstr "" + +#: src/basic-syntax/static-and-const.md:36 +msgid "" +"fn main() {\n" +" println!(\"{BANNER}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/static-and-const.md:41 +msgid "" +"As noted in the [Rust RFC Book][1], these are not inlined upon use and have an actual associated " +"memory location. This is useful for unsafe and embedded code, and the variable lives through the " +"entirety of the program execution." +msgstr "" +"Como se ve en [Rust RFC Book][1], esto no está en línea del uso y puede estar asociado a una " +"locación de memoria. Es útil para código no seguro o embebido, y las variables viven enteramente " +"dentro de la ejecución del programa." + +#: src/basic-syntax/static-and-const.md:44 +msgid "We will look at mutating static data in the [chapter on Unsafe Rust](../unsafe.md)." +msgstr "Veremos cambiar datos estáticos en el [capítulo Rust No Seguro](../unsafe.md)." + +#: src/basic-syntax/static-and-const.md:48 +msgid "" +"* Mention that `const` behaves semantically similar to C++'s `constexpr`.\n" +"* `static`, on the other hand, is much more similar to a `const` or mutable global variable in C+" +"+.\n" +"* It isn't super common that one would need a runtime evaluated constant, but it is helpful and " +"safer than using a static." +msgstr "" +"* Aclaremos que `const` semánticamente se comporta similar a `constexpr` de C++.\n" +"* `static`, por lo contrario, es mucho más similar a `const` o una variable mutable global de C+" +"+.\n" +"* No es muy común que necesitemos evaluar contantes en runtime, pero ayuda y es más seguro que " +"usando un _static_." + +#: src/basic-syntax/static-and-const.md:54 +msgid "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:1 +msgid "# Scopes and Shadowing" +msgstr "# Scopes y Shadowing" + +#: src/basic-syntax/scopes-shadowing.md:3 +msgid "" +"You can shadow variables, both those from outer scopes and variables from the\n" +"same scope:" +msgstr "Puedes hacer seguimiento de variables, esto se puede hacer para variables dentro y fuera del scope actual:" + +#: src/basic-syntax/scopes-shadowing.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a = 10;\n" +" println!(\"before: {a}\");" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:11 +msgid "" +" {\n" +" let a = \"hello\";\n" +" println!(\"inner scope: {a}\");" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:15 +msgid "" +" let a = true;\n" +" println!(\"shadowed in inner scope: {a}\");\n" +" }" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:19 +msgid "" +" println!(\"after: {a}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:25 +msgid "" +"* Definition: Shadowing is different from mutation, because after shadowing both variable's memory " +"locations exist at the same time. Both are available under the same name, depending where you use " +"it in the code. \n" +"* A shadowing variable can have a different type. \n" +"* Shadowing looks obscure at first, but is convenient for holding on to values after `.unwrap()`.\n" +"* The following code demonstrates why the compiler can't simply reuse memory locations when " +"shadowing an immutable variable in a scope, even if the type does not change." +msgstr "" +"* Definición: Shadowing es diferente de mutación, porque luego de shadowing ambos espacio de " +"memorias de las variables existen al mismo tiempo. Ambas están disponibles bajo el mismo nombre, " +"dependiendo donde uses el código.\n" +"* Un shadowing de variable puede tener un tipo diferente.\n" +"* El siguiente código demuestra por qué el compilador no puede simplemente reutilizar las " +"locaciones de memoria mientras hacemos shadowing a una variable inmutable en un cope, incluso si " +"el tipo no cambia." + +#: src/basic-syntax/scopes-shadowing.md:30 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a = 1;\n" +" let b = &a;\n" +" let a = a + 1;\n" +" println!(\"{a} {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management.md:1 +msgid "# Memory Management" +msgstr "# Manejo de memoria" + +#: src/memory-management.md:3 +msgid "Traditionally, languages have fallen into two broad categories:" +msgstr "Por lo general, los lenguajes caen en dos amplias categorías:" + +#: src/memory-management.md:5 +msgid "" +"* Full control via manual memory management: C, C++, Pascal, ...\n" +"* Full safety via automatic memory management at runtime: Java, Python, Go, Haskell, ..." +msgstr "" +"* Control total manual del manejo de memoria: C, C++, Pascal, …\n" +"* Total Seguridad vía manejo automático de memoria en tiempo de ejecución: Java, Python, Go, " +"Haskell, …" + +#: src/memory-management.md:8 +msgid "Rust offers a new mix:" +msgstr "Rust ofrece un nuevo mix:" + +#: src/memory-management.md:10 +msgid "" +"> Full control *and* safety via compile time enforcement of correct memory\n" +"> management." +msgstr "" +"> Control total y seguro vía tiempo de compilación con aseguramiento del correcto\n" +"> manejo de memoria." + +#: src/memory-management.md:13 +msgid "It does this with an explicit ownership concept." +msgstr "Esto da el concepto concepto explícito de _ownership_." + +#: src/memory-management.md:15 +msgid "First, let's refresh how memory management works." +msgstr "Empecemos refrescando cómo funciona el manejo de memoria." + +#: src/memory-management/stack-vs-heap.md:1 +msgid "# The Stack vs The Heap" +msgstr "" + +#: src/memory-management/stack-vs-heap.md:3 +msgid "" +"* Stack: Continuous area of memory for local variables.\n" +" * Values have fixed sizes known at compile time.\n" +" * Extremely fast: just move a stack pointer.\n" +" * Easy to manage: follows function calls.\n" +" * Great memory locality." +msgstr "" +"* Stack: Es un área de memoria continua para variables locales.\n" +" * Los valores son de tamaño fijo conocidos en tiempo de compilación.\n" +" * Extremadamente rápido: solo mueve un puntero de Stack.\n" +" * Fácil de manejar: sigue funciones de llamada.\n" +" * Mucha memoria local." + +#: src/memory-management/stack-vs-heap.md:9 +msgid "" +"* Heap: Storage of values outside of function calls.\n" +" * Values have dynamic sizes determined at runtime.\n" +" * Slightly slower than the stack: some book-keeping needed.\n" +" * No guarantee of memory locality." +msgstr "" +"* Heap: Guardar valores fuera de llamadas de funciones.\n" +" * Los valores tienen tamaños dinámicos determinados en tiempo de ejecución.\n" +" * Algo más lento que Stack: son necesarios algunos índices.\n" +" * No se garantiza memoria local." + +#: src/memory-management/stack.md:1 +msgid "# Stack Memory" +msgstr "" + +#: src/memory-management/stack.md:3 +msgid "" +"Creating a `String` puts fixed-sized data on the stack and dynamically sized\n" +"data on the heap:" +msgstr "" +"Crear un `String` pune datos de tamaño fijo en el stack y con tamaño dado dinámicamente en el heap:" + +#: src/memory-management/stack.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1 = String::from(\"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:12 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | e | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:28 +msgid "" +"* Mention that a `String` is backed by a `Vec`, so it has a capacity and length and can grow if " +"mutable via reallocation on the heap." +msgstr "" +"* Ve que un `String` es respaldado por un `Vec`, así tiene capacidad y tamaño que puede " +"incrementarse si la mutable por relocalicación en el _heap_." + +#: src/memory-management/stack.md:30 +msgid "" +"* If students ask about it, you can mention that the underlying memory is heap allocated using the " +"[System Allocator] and custom allocators can be implemented using the [Allocator API]" +msgstr "" +"* Si los estudiantes preguntan sobre esto, puedes mencionar que por debajo la memoria es colocada " +"por _heap_ usando el [Sistema de Colocación] y la colocación personalizada puede ser implementada " +"usando la [Allocator API]" + +#: src/memory-management/stack.md:32 +msgid "" +"* We can inspect the memory layout with `unsafe` code. However, you should point out that this is " +"rightfully unsafe!" +msgstr "" +"* Podemos inspeccionar el layout de memoria con la cláusula `unsafe`. Sin embargo, debes aclarar " +"que esto no es seguro!" + +#: src/memory-management/stack.md:34 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could lead to\n" +" // undefined behavior.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +" }\n" +"}\n" +"```" +msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // NO HAGAS ESTO EN CASA! Sólo con propósitos educativos.\n" +" // El String no provee garantías en su layout, esto puede derivar en\n" +" // comportamientos no deseados.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +" }\n" +"}\n" +"```" + +#: src/memory-management/stack.md:51 +msgid "" +"[System Allocator]: https://doc.rust-lang.org/std/alloc/struct.System.html\n" +"[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html" +msgstr "" +"[Sistema de Colocación]: https://doc.rust-lang.org/std/alloc/struct.System.html\n" +"[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html" + +#: src/memory-management/manual.md:1 +msgid "# Manual Memory Management" +msgstr "# Manejo Manual de Memoria" + +#: src/memory-management/manual.md:3 +msgid "You allocate and deallocate heap memory yourself." +msgstr "Tú mismo puedes asignar o desasignar pilas (_heap_) de memoria." + +#: src/memory-management/manual.md:5 +msgid "" +"If not done with care, this can lead to crashes, bugs, security vulnerabilities, and memory leaks." +msgstr "" +"Si no lo haces con cuidado, puede derivar en crasheo, errores, vulnerabilidad de seguridad, memory " +"leaks." + +#: src/memory-management/manual.md:7 +msgid "## C Example" +msgstr "# Ejemplo en C" + +#: src/memory-management/manual.md:9 +msgid "You must call `free` on every pointer you allocate with `malloc`:" +msgstr "Debes llamar a `free` en cada puntero que pongas usando `malloc`:" + +#: src/memory-management/manual.md:11 +msgid "" +"```c\n" +"void foo(size_t n) {\n" +" int* int_array = (int*)malloc(n * sizeof(int));\n" +" //\n" +" // ... lots of code\n" +" //\n" +" free(int_array);\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/manual.md:21 +msgid "" +"Memory is leaked if the function returns early between `malloc` and `free`: the\n" +"pointer is lost and we cannot deallocate the memory." +msgstr "" +"La memoria es _leaked_ si la función vuelve rápido entre `malloc` y `free`: se pierde el puntero y " +"no podemos desasignar la memoria." + +#: src/memory-management/scope-based.md:1 +msgid "# Scope-Based Memory Management" +msgstr "# Ámbitos de Manejo de Memoria" + +#: src/memory-management/scope-based.md:3 +msgid "Constructors and destructors let you hook into the lifetime of an object." +msgstr "Los constructores y destructores te permiten mantener en _lifetime_ un objeto." + +#: src/memory-management/scope-based.md:5 +msgid "" +"By wrapping a pointer in an object, you can free memory when the object is\n" +"destroyed. The compiler guarantees that this happens, even if an exception is\n" +"raised." +msgstr "" +"Envolviendo un puntero con un objeto, puedes liberar memoria cuando el objeto es\n" +"destruido. El compilador garantiza que eso pase, incluso si se alcanzó una excepción." + +#: src/memory-management/scope-based.md:9 +msgid "" +"This is often called _resource acquisition is initialization_ (RAII) and gives\n" +"you smart pointers." +msgstr "" +"A menudo se dice que la adquisición de recursos es inicializada ó, _resource acquisition is " +"initialization_ (RAII),\n" +"y brinda punteros inteligentes." + +#: src/memory-management/scope-based.md:12 +msgid "## C++ Example" +msgstr "## Ejemplo C++" + +#: src/memory-management/scope-based.md:14 +msgid "" +"```c++\n" +"void say_hello(std::unique_ptr person) {\n" +" std::cout << \"Hello \" << person->name << std::endl;\n" +"}\n" +"```" +msgstr "" +"```c++\n" +"void say_hello(std::unique_ptr person) {\n" +" std::cout << \"Hola \" << person->name << std::endl;\n" +"}\n" +"```" + +#: src/memory-management/scope-based.md:20 +msgid "" +"* The `std::unique_ptr` object is allocated on the stack, and points to\n" +" memory allocated on the heap.\n" +"* At the end of `say_hello`, the `std::unique_ptr` destructor will run.\n" +"* The destructor frees the `Person` object it points to." +msgstr "" +"* El objeto `std::unique_ptr` se ubica en el stack, y los punteros a \n" +" memoria apuntando a el heap.\n" +"* Al final de `say_hello`, correrá el destructor `std::unique_ptr`.\n" +"* El destructor libera el objeto `Person`que apunta a él." + +#: src/memory-management/scope-based.md:25 +msgid "Special move constructors are used when passing ownership to a function:" +msgstr "Un movimiento especial de constructor es usado cuando se pasa la propiedad a una función:" + +#: src/memory-management/scope-based.md:27 +msgid "" +"```c++\n" +"std::unique_ptr person = find_person(\"Carla\");\n" +"say_hello(std::move(person));\n" +"```" +msgstr "" + +#: src/memory-management/garbage-collection.md:1 +msgid "# Automatic Memory Management" +msgstr "# Manejo Automático de Memoria" + +#: src/memory-management/garbage-collection.md:3 +msgid "" +"An alternative to manual and scope-based memory management is automatic memory\n" +"management:" +msgstr "Una alternativa al manejo manual es el automático:" + +#: src/memory-management/garbage-collection.md:6 +msgid "" +"* The programmer never allocates or deallocates memory explicitly.\n" +"* A garbage collector finds unused memory and deallocates it for the programmer." +msgstr "" +"* El programador nunca asigna o desasgan memoria explícitamente.\n" +"* Un garbage collector encuentra memoria sin usar y la libera para el programador." + +#: src/memory-management/garbage-collection.md:9 +msgid "## Java Example" +msgstr "## Ejemplo Java" + +#: src/memory-management/garbage-collection.md:11 +msgid "The `person` object is not deallocated after `sayHello` returns:" +msgstr "El objeto `persona` no se libera luego que vuelva `sayHello`:" + +#: src/memory-management/garbage-collection.md:13 +msgid "" +"```java\n" +"void sayHello(Person person) {\n" +" System.out.println(\"Hello \" + person.getName());\n" +"}\n" +"```" +msgstr "" +"```java\n" +"void sayHello(Person person) {\n" +" System.out.println(\"Hola \" + person.getName());\n" +"}\n" +"```" + +#: src/memory-management/rust.md:1 +msgid "# Memory Management in Rust" +msgstr "# Manejo de la Memoria en Rust" + +#: src/memory-management/rust.md:3 +msgid "Memory management in Rust is a mix:" +msgstr "El manejo de memoria en Rust es una mezcla:" + +#: src/memory-management/rust.md:5 +msgid "" +"* Safe and correct like Java, but without a garbage collector.\n" +"* Depending on which abstraction (or combination of abstractions) you choose, can be a single " +"unique pointer, reference counted, or atomically reference counted.\n" +"* Scope-based like C++, but the compiler enforces full adherence.\n" +"* A Rust user can choose the right abstraction for the situation, some even have no cost at " +"runtime like C." +msgstr "" +"* Segura y correcta como en Java, pero sin un Garbage Collector.\n" +"* Dependiendo qué abstracción (o combinación de abstracción) eliges, puedes ser un puntero simple, " +"referencia contada, o atómicamente referencia contada.\n" +"* El ámbito basado en C++, pero que el compilador fuerza a incluirlo por completo.\n" +"* Un usuario de Rust puede elegir la abstracción correcta para la situación, algunos incluso no " +"tienen costo en runtime como C++." + +#: src/memory-management/rust.md:10 +msgid "It achieves this by modeling _ownership_ explicitly." +msgstr "Esto se logra modelando el _ownership_ explícitamente." + +#: src/memory-management/rust.md:14 +msgid "" +"* If asked how at this point, you can mention that in Rust this is usually handled by RAII wrapper " +"types such as [Box], [Vec], [Rc], or [Arc]. These encapsulate ownership and memory allocation via " +"various means, and prevent the potential errors in C." +msgstr "" +"* Si en este punto preguntas, puedes decir que Rust usualmente es tomado por tipos wrapper RAII " +"como [Box], [Vec], [Rc], or [Arc]. Esto encapsula el _ownsership_ y la ubicación de memoria con " +"varios significados, y previene potenciales errores en C." + +#: src/memory-management/rust.md:16 +msgid "* You may be asked about destructors here, the [Drop] trait is the Rust equivalent." +msgstr "* Puedes preguntar acerca de destructores, el [Drop] es el equivalente de Rust." + +#: src/memory-management/rust.md:20 +msgid "" +"[Box]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +"[Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +"[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +"[Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +"[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html" +msgstr "" + +#: src/memory-management/comparison.md:1 +msgid "# Comparison" +msgstr "# Comparación" + +#: src/memory-management/comparison.md:3 +msgid "Here is a rough comparison of the memory management techniques." +msgstr "Aquí una rústica comparación de técnicas de manejo de memoria." + +#: src/memory-management/comparison.md:5 +msgid "## Pros of Different Memory Management Techniques" +msgstr "## Ventajas de las Diferentes Técnicas de Manejo de Memoria" + +#: src/memory-management/comparison.md:7 +msgid "" +"* Manual like C:\n" +" * No runtime overhead.\n" +"* Automatic like Java:\n" +" * Fully automatic.\n" +" * Safe and correct.\n" +"* Scope-based like C++:\n" +" * Partially automatic.\n" +" * No runtime overhead.\n" +"* Compiler-enforced scope-based like Rust:\n" +" * Enforced by compiler.\n" +" * No runtime overhead.\n" +" * Safe and correct." +msgstr "" +"* Manual como en C:\n" +" * No runtime overhead.\n" +"* Automático como en Java:\n" +" * Totalmente automático.\n" +" * Correcto y Seguro.\n" +"* Scope-based como en C++:\n" +" * Parcialmente automático.\n" +" * No runtime overhead.\n" +"* Compiler-enforced y scope-based como en Rust:\n" +" * Asgurado por el compilador.\n" +" * No runtime overhead.\n" +" * Correcto y Seguro." + +#: src/memory-management/comparison.md:20 +msgid "## Cons of Different Memory Management Techniques" +msgstr "## Contras de las Diferentes Técnicas de Manejo de Memoria" + +#: src/memory-management/comparison.md:22 +msgid "" +"* Manual like C:\n" +" * Use-after-free.\n" +" * Double-frees.\n" +" * Memory leaks.\n" +"* Automatic like Java:\n" +" * Garbage collection pauses.\n" +" * Destructor delays.\n" +"* Scope-based like C++:\n" +" * Complex, opt-in by programmer.\n" +" * Potential for use-after-free.\n" +"* Compiler-enforced and scope-based like Rust:\n" +" * Some upfront complexity.\n" +" * Can reject valid programs." +msgstr "" +"* Manual como en C:\n" +" * Use-after-free.\n" +" * Double-frees.\n" +" * Memory leaks.\n" +"* Automático como en Java:\n" +" * Pausas en Garbage Colletion.\n" +" * Destructor delays.\n" +"* Scope-based como en C++:\n" +" * Complejo, a elección del programador.\n" +" * Potencial de use-after-free.\n" +"* Compiler-enforced y scope-based como Rust:\n" +" * Alguna upfront complexity.\n" +" * Puede denegar programas válidos." + +#: src/ownership.md:1 +msgid "# Ownership" +msgstr "" + +#: src/ownership.md:3 +msgid "" +"All variable bindings have a _scope_ where they are valid and it is an error to\n" +"use a variable outside its scope:" +msgstr "" +"Todos los enlaces de variables tienen un _scope_ donde son válidas y es un error\n" +"usar la variable fuera de este _scope_:" + +#: src/ownership.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"struct Point(i32, i32);" +msgstr "" + +#: src/ownership.md:9 +msgid "" +"fn main() {\n" +" {\n" +" let p = Point(3, 4);\n" +" println!(\"x: {}\", p.0);\n" +" }\n" +" println!(\"y: {}\", p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership.md:18 +msgid "" +"* At the end of the scope, the variable is _dropped_ and the data is freed.\n" +"* A destructor can run here to free up resources.\n" +"* We say that the variable _owns_ the value." +msgstr "" +"* Al final del _scope_, se borra la variable y se liberan los datos.\n" +"* Un destructor puede correr aquí y liberar los recursos.\n" +"* Podemos decir que la variable es dueña del valor." + +#: src/ownership/move-semantics.md:1 +msgid "# Move Semantics" +msgstr "" + +#: src/ownership/move-semantics.md:3 +msgid "An assignment will transfer ownership between variables:" +msgstr "Una asignación transferirá su propiedad entre variables:" + +#: src/ownership/move-semantics.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Hello!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" +msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Hola!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" + +#: src/ownership/move-semantics.md:14 +msgid "" +"* The assignment of `s1` to `s2` transfers ownership.\n" +"* The data was _moved_ from `s1` and `s1` is no longer accessible.\n" +"* When `s1` goes out of scope, nothing happens: it has no ownership.\n" +"* When `s2` goes out of scope, the string data is freed.\n" +"* There is always _exactly_ one variable binding which owns a value." +msgstr "" +"* La asignación de `s1` a `s2` transfiere el _ownership_.\n" +"* Los datos se mueven de `s1` y `s2` si no se accede más.\n" +"* Cuando `s1` sale del ámbito, no sucede nada: no tiene dueño.\n" +"* Cuando `s2` sale del ámbito, el dato del string es liberado.\n" +"* Allí siempre hay _exactamente_ una variable enlazada que es dueña del valor." + +#: src/ownership/move-semantics.md:22 +msgid "" +"* Mention that this is the opposite of the defaults in C++, which copies by value unless you use " +"`std::move` (and the move constructor is defined!)." +msgstr "" +"* Hay que destacar que el contrario de los defaults en C++, que copia por valor a menos que uses " +"`std::move` (y el movimiento del constructor está definido!)." + +#: src/ownership/move-semantics.md:24 +msgid "* In Rust, clones are explicit (by using `clone`)." +msgstr "* En Rust los clones son explícitos (usando `clone`)." + +#: src/ownership/moved-strings-rust.md:1 +msgid "# Moved Strings in Rust" +msgstr "# Mover Strings en Rust" + +#: src/ownership/moved-strings-rust.md:3 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Rust\");\n" +" let s2: String = s1;\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:10 +msgid "" +"* The heap data from `s1` is reused for `s2`.\n" +"* When `s1` goes out of scope, nothing happens (it has been moved from)." +msgstr "" +"* La pila (heap) de datos de `s1` es rehusado para `s2`.\n" +"* Cuando `s1` sale del scope, no sucede nada (se movió de)." + +#: src/ownership/moved-strings-rust.md:13 +msgid "Before move to `s2`:" +msgstr "Antes de mover a `s2`:" + +#: src/ownership/moved-strings-rust.md:15 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| R | u | s | t | :\n" +": | len | 4 | : : +----+----+----+----+ :\n" +": | capacity | 4 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - -'\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:30 +msgid "After move to `s2`:" +msgstr "Luego de mover a `s2`:" + +#: src/ownership/moved-strings-rust.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 \"(inaccessible)\" : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" +": | len | 4 | : | : +----+----+----+----+ :\n" +": | capacity | 4 | : | : :\n" +": +-----------+-------+ : | : :\n" +": : | `- - - - - - - - - - - - - -'\n" +": s2 : |\n" +": +-----------+-------+ : |\n" +": | ptr | o---+---+--'\n" +": | len | 4 | :\n" +": | capacity | 4 | :\n" +": +-----------+-------+ :\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:1 +msgid "# Double Frees in Modern C++" +msgstr "# Liberar Doble en C++ moderno" + +#: src/ownership/double-free-modern-cpp.md:3 +msgid "Modern C++ solves this differently:" +msgstr "El C++ moderno lo resuelve diferente:" + +#: src/ownership/double-free-modern-cpp.md:5 +msgid "" +"```c++\n" +"std::string s1 = \"Cpp\";\n" +"std::string s2 = s1; // Duplicate the data in s1.\n" +"```" +msgstr "" +"```c++\n" +"std::string s1 = \"Cpp\";\n" +"std::string s2 = s1; // Duplica los datos en s1.\n" +"```" + +#: src/ownership/double-free-modern-cpp.md:10 +msgid "" +"* The heap data from `s1` is duplicated and `s2` gets its own independent copy.\n" +"* When `s1` and `s2` go out of scope, they each free their own memory." +msgstr "" +"* La pila de datos de `s1` duplicada en `s2` obtiene su copia de datos independiente.\n" +"* Cuando `s1` y `s2` salen del scope, cada uno liberan su propia memoria." + +#: src/ownership/double-free-modern-cpp.md:13 +msgid "Before copy-assignment:" +msgstr "Antes de la asignación-copia:" + +#: src/ownership/double-free-modern-cpp.md:16 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:30 +msgid "After copy-assignment:" +msgstr "Luego de la asignación-copia:" + +#: src/ownership/double-free-modern-cpp.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : : :\n" +": s2 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+-----+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:1 +msgid "# Moves in Function Calls" +msgstr "# Movimientos en Llamadas de Funciones" + +#: src/ownership/moves-function-calls.md:3 +msgid "" +"When you pass a value to a function, the value is assigned to the function\n" +"parameter. This transfers ownership:" +msgstr "" +"Cuando pasas un valor a una función, el valor es asignado al parámetro de la\n" +"función. Esto transfiere el ownership:" + +#: src/ownership/moves-function-calls.md:6 +msgid "" +"```rust,editable\n" +"fn say_hello(name: String) {\n" +" println!(\"Hello {name}\")\n" +"}" +msgstr "" + +#: src/ownership/moves-function-calls.md:11 +msgid "" +"fn main() {\n" +" let name = String::from(\"Alice\");\n" +" say_hello(name);\n" +" // say_hello(name);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:20 +msgid "" +"* With the first call to `say_hello`, `main` gives up ownership of `name`. Afterwards, `name` " +"cannot be used anymore within `main`.\n" +"* The heap memory allocated for `name` will be freed at the end of the `say_hello` function.\n" +"* `main` can retain ownership if it passes `name` as a reference (`&name`) and if `say_hello` " +"accepts a reference as a parameter.\n" +"* Alternatively, `main` can pass a clone of `name` in the first call (`name.clone()`).\n" +"* Rust makes it harder than C++ to inadvertently create copies by making move semantics the " +"default, and by forcing programmers to make clones explicit." +msgstr "" +"* Con la primer llamada a `say_hello`, `main` da propiedad de `name`. Después de todo, `name` no " +"puede usarse meas dentro de `main`.\n" +"* La pila de memoria se asigna para `name` y será liberada al final de la función `say_hello`.\n" +"* `main` puede mantener la propiedad si pasa `name` como referencia (`&name`) y si `say_hello` " +"acepta una referencia como un parámetro.\n" +"* Alternativamente, `main` puede pasar un clon de `name` in la primer llamada (`name.clone()`).\n" +"* Rust hace esto más duro que C++ para crear copias automáticas mediante mover semánticas por " +"defecto, y forzando a los programadores a hacer clones explícitos." + +#: src/ownership/copy-clone.md:1 +msgid "# Copying and Cloning" +msgstr "# Copiar y Clonar" + +#: src/ownership/copy-clone.md:3 +msgid "While move semantics are the default, certain types are copied by default:" +msgstr "Mientras mover semántica es por defecto, en otros casos los tipos son copiados:" + +#: src/ownership/copy-clone.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = 42;\n" +" let y = x;\n" +" println!(\"x: {x}\");\n" +" println!(\"y: {y}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:14 +msgid "These types implement the `Copy` trait." +msgstr "Esos tipos implementan el trato de `Copia`." + +#: src/ownership/copy-clone.md:16 +msgid "You can opt-in your own types to use copy semantics:" +msgstr "Puedes elegir tu propio tipo para usar copias semánticas:" + +#: src/ownership/copy-clone.md:18 +msgid "" +"```rust,editable\n" +"#[derive(Copy, Clone, Debug)]\n" +"struct Point(i32, i32);" +msgstr "" + +#: src/ownership/copy-clone.md:22 +msgid "" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = p1;\n" +" println!(\"p1: {p1:?}\");\n" +" println!(\"p2: {p2:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:30 +msgid "" +"* After the assignment, both `p1` and `p2` own their own data.\n" +"* We can also use `p1.clone()` to explicitly copy the data." +msgstr "" +"* Luego de la asignación, ambos `p1` y `p2` obtienen su propio dato.\n" +"* También podemos usar `p1.clone()` para explícitamente copiar datos." + +#: src/ownership/copy-clone.md:35 +msgid "Copying and cloning are not the same thing:" +msgstr "Copiar datos y clonar no es la misma cosa:" + +#: src/ownership/copy-clone.md:37 +msgid "" +"* Copying refers to bitwise copies of memory regions and does not work on arbitrary objects.\n" +"* Copying does not allow for custom logic (unlike copy constructors in C++).\n" +"* Cloning is a more general operation and also allows for custom behavior by implementing the " +"`Clone` trait.\n" +"* Copying does not work on types that implement the `Drop` trait." +msgstr "" +"* Copiar refiere a copias bit a bit de regiones de memoria y no funciona con objetos arbitrarios.\n" +"* Copiar no permite por lógica personalizada (como copiar constructores en C++).\n" +"* Clonar es una operación más general y también permite estados personalizados implementando el " +"trato de `Clon`.\n" +"* Copiar no funciona en tipos que implementan el trato `Drop`." + +#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 +msgid "In the above example, try the following:" +msgstr "En el ejemplo de arriba, intenta lo siguiente:" + +#: src/ownership/copy-clone.md:44 +msgid "" +"* Add a `String` field to `struct Point`. It will not compile because `String` is not a `Copy` " +"type.\n" +"* Remove `Copy` from the `derive` attribute. The compiler error is now in the `println!` for " +"`p1`.\n" +"* Show that it works if you clone `p1` instead." +msgstr "" +"* Agrega el campo `String` a `struct Point`. Esto no compilará porque `String` no es un tipo de " +"`Copia`.\n" +"* Remueve la `Copia` de el atributo `resultante`. El error del compilador es ahora `println!` para " +"`p1`.\n" +"* Muestra que en cambio funciona si clonas `p1`." + +#: src/ownership/copy-clone.md:48 +msgid "" +"If students ask about `derive`, it is sufficient to say that this is a way to generate code in " +"Rust\n" +"at compile time. In this case the default implementations of `Copy` and `Clone` traits are " +"generated.\n" +" \n" +"" +msgstr "" +"Si un estudiante pregunta sobre `derive`, es suficiente decir que esta es la forma que se genera " +"el código en Rust\n" +"en tiempo de compilación. En este caso la implementación del trato por defecto de `Copiar` y " +"`Clonar` los genera.\n" +" \n" +"" + +#: src/ownership/borrowing.md:1 +msgid "# Borrowing" +msgstr "" + +#: src/ownership/borrowing.md:3 +msgid "" +"Instead of transferring ownership when calling a function, you can let a\n" +"function _borrow_ the value:" +msgstr "" +"En vez de transferir la propiedad cuando llamamos a una función, puedes _prestar_\n" +"el valor a una función:" + +#: src/ownership/borrowing.md:6 src/ownership/lifetimes-function-calls.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);" +msgstr "" + +#: src/ownership/borrowing.md:10 +msgid "" +"fn add(p1: &Point, p2: &Point) -> Point {\n" +" Point(p1.0 + p2.0, p1.1 + p2.1)\n" +"}" +msgstr "" + +#: src/ownership/borrowing.md:14 +msgid "" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/borrowing.md:22 +msgid "" +"* The `add` function _borrows_ two points and returns a new point.\n" +"* The caller retains ownership of the inputs." +msgstr "" +"* El `add` de la función presta dos puntos y devuelve uno nuevo.\n" +"* El llamador mantiene la propiedad de sus inputs." + +#: src/ownership/borrowing.md:27 +msgid "" +"Notes on stack returns:\n" +"* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy " +"operation. Change the above code to print stack addresses and run it on the [Playground]. In the " +"\"DEBUG\" optimization level, the addresses should change, while the stay the same when changing " +"to the \"RELEASE\" setting:" +msgstr "" +"Notas acerca de la pila devuelta:\n" +"* Demuestra que el return de `add` es adecuado porque le compilador puede eliminar la operación de " +"copia. Cambia el código de arriba para imprimir una pila de direcciones y corre esto en " +"[Playground]. En nivel de optimización \"DEBUG\", las direcciones pueden cambiar, mientras que se " +"mantienen igual cuando se cambia el seteo a \"RELEASE\":" + +#: src/ownership/borrowing.md:30 +msgid "" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);" +msgstr "" + +#: src/ownership/borrowing.md:34 +msgid "" +" fn add(p1: &Point, p2: &Point) -> Point {\n" +" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" +" println!(\"&p.0: {:p}\", &p.0);\n" +" p\n" +" }" +msgstr "" + +#: src/ownership/borrowing.md:40 +msgid "" +" fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"&p3.0: {:p}\", &p3.0);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +" }\n" +" ```\n" +"* The Rust compiler can do return value optimization (RVO).\n" +"* In C++, copy elision has to be defined in the language specification because constructors can " +"have side effects. In Rust, this is not an issue at all. If RVO did not happen, Rust will always " +"performs a simple and efficient `memcpy` copy." +msgstr "" +" fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"&p3.0: {:p}\", &p3.0);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +" }\n" +" ```\n" +"* El compilador de Rust puede devolver optimización de valor (RVO).\n" +"* En C++, la copia elisión tiene que estar definida en la especificación porque los contructores " +"pueden tener efectos secundarios. En Rust, esto para nada es un issue. Si no sucede RVO, Rust " +"siempre hará que corre de forma simple y eficiente con una copia `memcpy`." + +#: src/ownership/borrowing.md:53 +msgid "[Playground]: https://play.rust-lang.org/" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:1 +msgid "# Shared and Unique Borrows" +msgstr "# Shared y Unique Borrows" + +#: src/ownership/shared-unique-borrows.md:3 +msgid "Rust puts constraints on the ways you can borrow values:" +msgstr "Rust restringe la forma que puedes estar calores:" + +#: src/ownership/shared-unique-borrows.md:5 +msgid "" +"* You can have one or more `&T` values at any given time, _or_\n" +"* You can have exactly one `&mut T` value." +msgstr "" +"* A lo largo del tiempo puedes tener diferentes valores `&T`, _o_\n" +"* Puedes tener exactamente el mismo valor `&mud T`." + +#: src/ownership/shared-unique-borrows.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let mut a: i32 = 10;\n" +" let b: &i32 = &a;" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:13 +msgid "" +" {\n" +" let c: &mut i32 = &mut a;\n" +" *c = 20;\n" +" }" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:18 src/std/rc.md:13 +msgid "" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:25 +msgid "" +"* The above code does not compile because `a` is borrowed as mutable (through `c`) and as " +"immutable (through `b`) at the same time.\n" +"* Move the `println!` statement for `b` before the scope that introduces `c` to make the code " +"compile.\n" +"* After that change, the compiler realizes that `b` is only ever used before the new mutable " +"borrow of `a` through `c`. This is a feature of the borrow checker called \"non-lexical " +"lifetimes\"." +msgstr "" +"* El código de arriba no compila porque `a` es prestado como mutable (a través de `c`) y es " +"inmutable (a través de `b`) al mismo tiempo.\n" +"* Mueve el `println!` para `b` antes del scope que dice a `c` hacer que el código compile.\n" +"* Luego de ese cambio, el compilados hace que `b` sea usado solo antes de un préstamo mutable de " +"`a` a través de `c`. Esta es una característica para chequear los préstamos llamada \"non-lexical " +"lifetimes\"." + +#: src/ownership/lifetimes.md:1 +msgid "# Lifetimes" +msgstr "# Tiempo de Vida" + +#: src/ownership/lifetimes.md:3 +msgid "A borrowed value has a _lifetime_:" +msgstr "Un valor prestado tiene un tiempo de vida:" + +#: src/ownership/lifetimes.md:5 +msgid "" +"* The lifetime can be elided: `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." +msgstr "" +"* El tiempo de vida puede ser otorgado: `add(p1: &Point, p2: &Point) -> Point`.\n" +"* El tiempo también puede ser explícito: `&’a Point`, `&’document str`.\n" +"* Leer `&’a Point` como un \"`Point` prestado\" que es válido para al menos el tiempo de `a`\".\n" +"* Los tiempos de vida siempre son inferidos por el compilador: no puedes asignar uno tú mismo.\n" +"* Las anotaciones de tiempo de vida crea dependencias; el compilador verifica que allí haya una " +"solución válida." + +#: src/ownership/lifetimes-function-calls.md:1 +msgid "# Lifetimes in Function Calls" +msgstr "# Tiempo de Vida en Llamada a Funciones" + +#: src/ownership/lifetimes-function-calls.md:3 +msgid "In addition to borrowing its arguments, a function can return a borrowed value:" +msgstr "Además, para prestar estos argumentos, una función puede devolver un valor prestado:" + +#: src/ownership/lifetimes-function-calls.md:9 +msgid "" +"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +"}" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:13 +msgid "" +"fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p2: Point = Point(20, 20);\n" +" let p3: &Point = left_most(&p1, &p2);\n" +" println!(\"left-most point: {:?}\", p3);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:21 +msgid "" +"* `'a` is a generic parameter, it is inferred by the compiler.\n" +"* Lifetimes start with `'` and `'a` is a typical default name.\n" +"* Read `&'a Point` as \"a borrowed `Point` which is valid for at least the\n" +" lifetime `a`\".\n" +" * The _at least_ part is important when parameters are in different scopes." +msgstr "" +"* `’a` es un parámetro genérico, inferido por el compilador.\n" +"* Los tiempos de vida empiezan con `’` y `’a` es el nombre típico por default.\n" +"* Lee `&’ un Point` es \"un `Point` prestado que es válido por al menos el ciclo de vida de " +"`a`\".\n" +"* El _al menos_ es importante cuando los parámetros están en diferentes scopes." + +#: src/ownership/lifetimes-function-calls.md:31 +msgid "" +"* Move the declaration of `p2` and `p3` into a a new scope (`{ ... }`), resulting in the following " +"code:\n" +" ```rust,ignore\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);" +msgstr "" +"* Mueve la declaración de `p2` y `p3` a un nuevo scope (`{ … }`), resultando en este código:\n" +" ```rust,ignore\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);" + +#: src/ownership/lifetimes-function-calls.md:36 +msgid "" +" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +" }" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:40 +msgid "" +" fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p3: &Point;\n" +" {\n" +" let p2: Point = Point(20, 20);\n" +" p3 = left_most(&p1, &p2);\n" +" }\n" +" println!(\"left-most point: {:?}\", p3);\n" +" }\n" +" ```\n" +" Note how this does not compile since `p3` outlives `p2`." +msgstr "" +" fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p3: &Point;\n" +" {\n" +" let p2: Point = Point(20, 20);\n" +" p3 = left_most(&p1, &p2);\n" +" }\n" +" println!(\"left-most point: {:?}\", p3);\n" +" }\n" +" ```\n" +" Nota como no compila desde que `p3` persiste `p2`." + +#: src/ownership/lifetimes-function-calls.md:52 +msgid "" +"* Reset the workspace and change the function signature to `fn left_most<'a, 'b>(p1: &'a Point, " +"p2: &'a Point) -> &'b Point`. This will not compile because the relationship between the lifetimes " +"`'a` and `'b` is unclear.\n" +"* Another way to explain it:\n" +" * 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" +" for longer than a variable from where the reference came from." +msgstr "" +"* Resetea el workspace y cambia el signo de la función a `fn left_most<‘a, ‘b>(p1: &’a Point, p2: " +"&’a Point) -> &’b Point`. Esto no compilará porque la relación entre los ciclos de vida `’a` y " +"`’b` no es clara.\n" +"* Otra forma de explicar esto:\n" +" *Dos referencias para dos valores son prestados por una función y la función devuelve otra " +"referencia.\n" +" * esto debe venir desde uno de esos dos inputs (o de una variable global).\n" +" * Cuál es esta? El compilador necesita saber, que la llamada para volver al sitio de referencia " +"no se usa más que como variable de donde viene la referencia." + +#: src/ownership/lifetimes-data-structures.md:1 +msgid "# Lifetimes in Data Structures" +msgstr "# Ciclos de Vida y Estructura de Datos" + +#: src/ownership/lifetimes-data-structures.md:3 +msgid "If a data type stores borrowed data, it must be annotated with a lifetime:" +msgstr "SI un tipo de datos presta data, debe ser anotado como un ciclo de vida:" + +#: src/ownership/lifetimes-data-structures.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Highlight<'doc>(&'doc str);" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:9 +msgid "" +"fn erase(text: String) {\n" +" println!(\"Bye {text}!\");\n" +"}" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:13 +msgid "" +"fn main() {\n" +" let text = String::from(\"The quick brown fox jumps over the lazy dog.\");\n" +" let fox = Highlight(&text[4..19]);\n" +" let dog = Highlight(&text[35..43]);\n" +" // erase(text);\n" +" println!(\"{fox:?}\");\n" +" println!(\"{dog:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:25 +msgid "" +"* In the above example, the annotation on `Highlight` enforces that the data underlying the " +"contained `&str` lives at least as long as any instance of `Highlight` that uses that data.\n" +"* If `text` is consumed before the end of the lifetime of `fox` (or `dog`), the borrow checker " +"throws an error.\n" +"* Types with borrowed data force users to hold on to the original data. This can be useful for " +"creating lightweight views, but it generally makes them somewhat harder to use.\n" +"* When possible, make data structures own their data directly.\n" +"* Some structs with multiple references inside can have more than one lifetime annotation. This " +"can be necessary if there is a need to describe lifetime relationships between the references " +"themselves, in addition to the lifetime of the struct itself. Those are very advanced use cases.\n" +"" +msgstr "" +"* En el ejemplo de arriba, las anotaciones `resaltadlas` fuerzan que los datos contenidos en " +"`&str` viven al menos a lo largo de todas las instancias `resaltadlas` que usan esos datos.\n" +"* Si el `texto` es usado antes del final del ciclo de vida de `fox` (o `dog`), el chequeado de " +"préstamos arrojará error.\n" +"* Los tipos que prestan datos fuerzan a los usuarios a mantener el dato original. Esto puede ser " +"útil para crear vistas ligeras, pero generalmente hace que sea difícil de usar.\n" +"* Cuando sea posible, haz estructuras de datos tengan su dato directamente.\n" +"* Algunas estructuras con múltiples referencias dentro pueden tener más de una anotación de ciclo " +"de vida. Esto puede ser necesario si allí quiere describir un a relación de ciclo de vida entre " +"las referencias, ademas del ciclo de vida de las estructuras en sí mismo. Aquellas son casos de " +"uso más avanzado.\n" +"" + +#: src/exercises/day-1/afternoon.md:1 +msgid "# Day 1: Afternoon Exercises" +msgstr "# Día 1: Ejercicios de la Tarde" + +#: src/exercises/day-1/afternoon.md:3 +msgid "We will look at two things:" +msgstr "Veremos todas estas cosas:" + +#: src/exercises/day-1/afternoon.md:5 +msgid "* A small book library," +msgstr "* Un pequeño libro de biblioteca," + +#: src/exercises/day-1/afternoon.md:7 +msgid "* Iterators and ownership (hard)." +msgstr "* Iteradores y propiedad (difícil)." + +#: src/exercises/day-1/afternoon.md:13 src/exercises/day-2/afternoon.md:9 +msgid "[solutions]: solutions-afternoon.md" +msgstr "[soluciones]: solutions-afternoon.md" + +#: src/exercises/day-1/book-library.md:1 +msgid "# Designing a Library" +msgstr "# Diseñar una Librería" + +#: src/exercises/day-1/book-library.md:3 +msgid "" +"We will learn much more about structs and the `Vec` type tomorrow. For now,\n" +"you just need to know part of its API:" +msgstr "" +"Mañana aprenderemos mucho mas acerca de estructuras y tipos `Vec`. Por ahora,\n" +"solo necesitas conocer parte de esta API:" + +#: src/exercises/day-1/book-library.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut vec = vec![10, 20];\n" +" vec.push(30);\n" +" println!(\"middle value: {}\", vec[vec.len() / 2]);\n" +" for item in vec.iter() {\n" +" println!(\"item: {item}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:17 +msgid "" +"Use this to create a library application. Copy the code below to\n" +" and update the types to make it compile:" +msgstr "" +"Usa esto para crear una librería de aplicación. Copia el código debajo a\n" +" y actualiza los tipos para hacer que compile:" + +#: src/exercises/day-1/book-library.md:24 +msgid "" +"struct Library {\n" +" books: Vec,\n" +"}" +msgstr "" + +#: src/exercises/day-1/book-library.md:28 src/exercises/day-1/solutions-afternoon.md:27 +msgid "" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}" +msgstr "" + +#: src/exercises/day-1/book-library.md:33 src/exercises/day-1/solutions-afternoon.md:32 +msgid "" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}" +msgstr "" +"impl Book {\n" +" // Este es el constructor, usado debajo.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}" + +#: src/exercises/day-1/book-library.md:43 +msgid "" +"// 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" +"}" +msgstr "" +"// Esto hace posible imprimir valores del libro con {}.\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" +"}" + +#: src/exercises/day-1/book-library.md:50 +msgid "" +"impl Library {\n" +" fn new() -> Library {\n" +" unimplemented!()\n" +" }" +msgstr "" + +#: src/exercises/day-1/book-library.md:55 +msgid "" +" //fn len(self) -> usize {\n" +" // unimplemented!()\n" +" //}" +msgstr "" + +#: src/exercises/day-1/book-library.md:59 +msgid "" +" //fn is_empty(self) -> bool {\n" +" // unimplemented!()\n" +" //}" +msgstr "" + +#: src/exercises/day-1/book-library.md:63 +msgid "" +" //fn add_book(self, book: Book) {\n" +" // unimplemented!()\n" +" //}" +msgstr "" + +#: src/exercises/day-1/book-library.md:67 +msgid "" +" //fn print_books(self) {\n" +" // unimplemented!()\n" +" //}" +msgstr "" + +#: src/exercises/day-1/book-library.md:71 +msgid "" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // unimplemented!()\n" +" //}\n" +"}" +msgstr "" + +#: src/exercises/day-1/book-library.md:76 +msgid "" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();" +msgstr "" +"// Esto muestra el estado deseado. Descomenta el código debajo e\n" +"// implementa el método que falta. Puedes necesitar actualizar el \n" +"// signo del método, incluyendo el parámetro \"self\". También\n" +"fn main() {\n" +" let library = Library::new();" + +#: src/exercises/day-1/book-library.md:83 +msgid "" +" //println!(\"Our 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" +" //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" +" //}\n" +" //\n" +" //println!(\"Our library has {} books\", library.len());\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:99 +msgid "" +"
\n" +" \n" +"[Solution](solutions-afternoon.md#designing-a-library)" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:1 +msgid "# Iterators and Ownership" +msgstr "# Iteratoradores y Propiedad" + +#: src/exercises/day-1/iterators-and-ownership.md:3 +msgid "" +"The ownership model of Rust affects many APIs. An example of this is the\n" +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and\n" +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)\n" +"traits." +msgstr "" +"El modelo de propiedad de Rust afecta muchas APIs. Un ejemplo de esto es\n" +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) y\n" +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)." + +#: src/exercises/day-1/iterators-and-ownership.md:8 +msgid "## `Iterator`" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:10 +msgid "" +"Traits are like interfaces: they describe behavior (methods) for a type. The\n" +"`Iterator` trait simply says that you can call `next` until you get `None` back:" +msgstr "" +"Estos son como interfaces: ellas describen un estado (método) para un tipo. El\n" +"`Iterador` simplemente dice que puedes llamar al `siguiente` hasta que se devuelve `ninguno`:" + +#: src/exercises/day-1/iterators-and-ownership.md:13 +msgid "" +"```rust\n" +"pub trait Iterator {\n" +" type Item;\n" +" fn next(&mut self) -> Option;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:20 +msgid "You use this trait like this:" +msgstr "Puedes usar lo siguiente:" + +#: src/exercises/day-1/iterators-and-ownership.md:22 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:27 +msgid "" +" println!(\"v[0]: {:?}\", iter.next());\n" +" println!(\"v[1]: {:?}\", iter.next());\n" +" println!(\"v[2]: {:?}\", iter.next());\n" +" println!(\"No more items: {:?}\", iter.next());\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:34 +msgid "What is the type returned by the iterator? Test your answer here:" +msgstr "Cuál es el tipo devuelto por el iterador? Testea tu respuesta aquí:" + +#: src/exercises/day-1/iterators-and-ownership.md:36 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:41 +#: src/exercises/day-1/iterators-and-ownership.md:78 +msgid "" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:46 +msgid "Why is this type used?" +msgstr "Por qué es usado este tipo?" + +#: src/exercises/day-1/iterators-and-ownership.md:48 +msgid "## `IntoIterator`" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:50 +msgid "" +"The `Iterator` trait tells you how to _iterate_ once you have created an\n" +"iterator. The related trait `IntoIterator` tells you how to create the iterator:" +msgstr "" +"El `Iterator` te dice cómo _iterarP una vez que creas un\n" +"iterado. La relación `IntoIterator` dice cómo crear un iterador:" + +#: src/exercises/day-1/iterators-and-ownership.md:53 +msgid "" +"```rust\n" +"pub trait IntoIterator {\n" +" type Item;\n" +" type IntoIter: Iterator;" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:58 +msgid "" +" fn into_iter(self) -> Self::IntoIter;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:62 +msgid "" +"The syntax here means that every implementation of `IntoIterator` must\n" +"declare two types:" +msgstr "La sintaxis aquí dice que cada implementación de `IntoIterator` debe declarar dos tipos:" + +#: src/exercises/day-1/iterators-and-ownership.md:65 +msgid "" +"* `Item`: the type we iterate over, such as `i8`,\n" +"* `IntoIter`: the `Iterator` type returned by the `into_iter` method." +msgstr "" +"* `Item`: el tipo que iteramos, como `i8`,\n" +"* `IntoIter`: el tipo `Iterator` devuelto por el método `into_iter`." + +#: src/exercises/day-1/iterators-and-ownership.md:68 +msgid "" +"Note that `IntoIter` and `Item` are linked: the iterator must have the same\n" +"`Item` type, which means that it returns `Option`" +msgstr "" +"Nota que `IntoIter` e `Item` están linkeados: el iterado debe tener el mismo\n" +"tipo `Item`, que quiere decir que retorna `Option`" + +#: src/exercises/day-1/iterators-and-ownership.md:71 +msgid "Like before, what is the type returned by the iterator?" +msgstr "Como antes, qué es el tipo devuelto por el iterador?" + +#: src/exercises/day-1/iterators-and-ownership.md:73 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];\n" +" let mut iter = v.into_iter();" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:83 +msgid "## `for` Loops" +msgstr "## Loops `for`" + +#: src/exercises/day-1/iterators-and-ownership.md:85 +msgid "" +"Now that we know both `Iterator` and `IntoIterator`, we can build `for` loops.\n" +"They call `into_iter()` on an expression and iterates over the resulting\n" +"iterator:" +msgstr "" +"Ahora que sabemos de ambos `Iterator` y `Intolterator`, podemos hacer loops `for`.\n" +"Ellos llaman `into_iter()` en una expresión e iterados sobre el iterado resultante:" + +#: src/exercises/day-1/iterators-and-ownership.md:89 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:93 +msgid "" +" for word in &v {\n" +" println!(\"word: {word}\");\n" +" }" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:97 +msgid "" +" for word in v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:103 +msgid "What is the type of `word` in each loop?" +msgstr "Qué es el tipo `word` en cada loop?" + +#: src/exercises/day-1/iterators-and-ownership.md:105 +msgid "" +"Experiment with the code above and then consult the documentation for [`impl\n" +"IntoIterator for\n" +"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-" +"%26%27a%20Vec%3CT%2C%20A%3E)\n" +"and [`impl IntoIterator for\n" +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-" +"Vec%3CT%2C%20A%3E)\n" +"to check your answers." +msgstr "" +"Experimenta con el código de arriba y luego consultas por [`impl\n" +"IntoIterator for\n" +"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-" +"%26%27a%20Vec%3CT%2C%20A%3E)\n" +"y [`impl IntoIterator for\n" +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-" +"Vec%3CT%2C%20A%3E)\n" +"para verificar tus respuestas." + +#: src/welcome-day-2.md:1 +msgid "# Welcome to Day 2" +msgstr "# Bienvenido al Día 2" + +#: src/welcome-day-2.md:3 +msgid "Now that we have seen a fair amount of Rust, we will continue with:" +msgstr "" + +#: src/welcome-day-2.md:5 +msgid "* Structs, enums, methods." +msgstr "" + +#: src/welcome-day-2.md:7 +msgid "* Pattern matching: destructuring enums, structs, and arrays." +msgstr "" + +#: src/welcome-day-2.md:9 +msgid "" +"* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and\n" +" `continue`." +msgstr "" + +#: src/welcome-day-2.md:12 +msgid "" +"* The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, `Rc`\n" +" and `Arc`." +msgstr "" + +#: src/welcome-day-2.md:15 +msgid "* Modules: visibility, paths, and filesystem hierarchy." +msgstr "" + +#: src/structs.md:1 +msgid "# Structs" +msgstr "" + +#: src/structs.md:3 +msgid "Like C and C++, Rust has support for custom structs:" +msgstr "" + +#: src/structs.md:5 +msgid "" +"```rust,editable\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}" +msgstr "" + +#: src/structs.md:11 +msgid "" +"fn main() {\n" +" let mut peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" peter.age = 28;\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" let jackie = Person {\n" +" name: String::from(\"Jackie\"),\n" +" ..peter\n" +" };\n" +" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" +"}\n" +"```" +msgstr "" + +#: src/structs.md:29 +msgid "" +"
\n" +"Key Points: " +msgstr "" + +#: src/structs.md:32 +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" +" * Unlike in C++, there is no inheritance between structs.\n" +"* Methods are defined in an `impl` block, which we will see in following slides.\n" +"* This may be a good time to let people know there are different types of structs. \n" +" * Zero-sized structs `e.g., struct Foo;` might be used when implementing a trait on some type " +"but don’t have any data that you want to store in the value itself. \n" +" * The next slide will introduce Tuple structs, used when the field names are not important.\n" +"* The syntax `..peter` allows us to copy the majority of the fields from the old struct without " +"having to explicitly type it all out. It must always be the last element." +msgstr "" + +#: src/structs/tuple-structs.md:1 +msgid "# Tuple Structs" +msgstr "" + +#: src/structs/tuple-structs.md:3 +msgid "If the field names are unimportant, you can use a tuple struct:" +msgstr "" + +#: src/structs/tuple-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Point(i32, i32);" +msgstr "" + +#: src/structs/tuple-structs.md:8 +msgid "" +"fn main() {\n" +" let p = Point(17, 23);\n" +" println!(\"({}, {})\", p.0, p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:14 +msgid "This is often used for single-field wrappers (called newtypes):" +msgstr "" + +#: src/structs/tuple-structs.md:16 +msgid "" +"```rust,editable,compile_fail\n" +"struct PoundOfForce(f64);\n" +"struct Newtons(f64);" +msgstr "" + +#: src/structs/tuple-structs.md:20 +msgid "" +"fn compute_thruster_force() -> PoundOfForce {\n" +" todo!(\"Ask a rocket scientist at NASA\")\n" +"}" +msgstr "" + +#: src/structs/tuple-structs.md:24 +msgid "" +"fn set_thruster_force(force: Newtons) {\n" +" // ...\n" +"}" +msgstr "" + +#: src/structs/tuple-structs.md:28 +msgid "" +"fn main() {\n" +" let force = compute_thruster_force();\n" +" set_thruster_force(force);\n" +"}" +msgstr "" + +#: src/structs/tuple-structs.md:33 src/traits/default.md:36 src/generics/trait-objects.md:86 +msgid "```" +msgstr "" + +#: src/structs/tuple-structs.md:37 +msgid "" +"* Newtypes are a great way to encode additional information about the value in a primitive type, " +"for example:\n" +" * The number is measured in some units: `Newtons` in the example above.\n" +" * The value passed some validation when it was created, so you no longer have to validate it " +"again at every use: 'PhoneNumber(String)` or `OddNumber(u32)`.\n" +"* Demonstrate how to add a `f64` value to a `Newtons` type by accessing the single field in the " +"newtype.\n" +" * Rust generally doesn’t like inexplicit things, like automatic unwrapping or for instance " +"using booleans as integers.\n" +" * Operator overloading is discussed on Day 3 (generics). \n" +"
" +msgstr "" + +#: src/structs/field-shorthand.md:1 +msgid "# Field Shorthand Syntax" +msgstr "" + +#: src/structs/field-shorthand.md:3 +msgid "" +"If you already have variables with the right names, then you can create the\n" +"struct using a shorthand:" +msgstr "" + +#: src/structs/field-shorthand.md:6 src/methods.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}" +msgstr "" + +#: src/structs/field-shorthand.md:13 +msgid "" +"impl Person {\n" +" fn new(name: String, age: u8) -> Person {\n" +" Person { name, age }\n" +" }\n" +"}" +msgstr "" + +#: src/structs/field-shorthand.md:19 +msgid "" +"fn main() {\n" +" let peter = Person::new(String::from(\"Peter\"), 27);\n" +" println!(\"{peter:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/structs/field-shorthand.md:27 +msgid "" +"The `new` function could be written using `Self` as a type, as it is interchangeable with the " +"struct type name" +msgstr "" + +#: src/structs/field-shorthand.md:29 +msgid "" +"```rust,ignore\n" +"impl Person {\n" +" fn new(name: String, age: u8) -> Self {\n" +" Self { name, age }\n" +" }\n" +"}\n" +"```\n" +" \n" +"
" +msgstr "" + +#: src/enums.md:1 +msgid "# Enums" +msgstr "" + +#: src/enums.md:3 +msgid "" +"The `enum` keyword allows the creation of a type which has a few\n" +"different variants:" +msgstr "" + +#: src/enums.md:6 +msgid "" +"```rust,editable\n" +"fn generate_random_number() -> i32 {\n" +" 4 // Chosen by fair dice roll. Guaranteed to be random.\n" +"}" +msgstr "" + +#: src/enums.md:11 +msgid "" +"#[derive(Debug)]\n" +"enum CoinFlip {\n" +" Heads,\n" +" Tails,\n" +"}" +msgstr "" + +#: src/enums.md:17 +msgid "" +"fn flip_coin() -> CoinFlip {\n" +" let random_number = generate_random_number();\n" +" if random_number % 2 == 0 {\n" +" return CoinFlip::Heads;\n" +" } else {\n" +" return CoinFlip::Tails;\n" +" }\n" +"}" +msgstr "" + +#: src/enums.md:26 +msgid "" +"fn main() {\n" +" println!(\"You got: {:?}\", flip_coin());\n" +"}\n" +"```" +msgstr "" + +#: src/enums.md:31 +msgid "" +"
\n" +" \n" +"Key Points:" +msgstr "" + +#: src/enums.md:35 +msgid "" +"* Enumerations allow you to collect a set of values under one type\n" +"* This page offers an enum type `CoinFlip` with two variants `Heads` and `Tail`. You might note " +"the namespace when using variants.\n" +"* This might be a good time to compare Structs and Enums:\n" +" * In both, you can have a simple version without fields (unit struct) or one with different " +"types of fields (variant payloads). \n" +" * In both, associated functions are defined within an `impl` block.\n" +" * You could even implement the different variants of an enum with separate structs but then they " +"wouldn’t be the same type as they would if they were all defined in an enum. \n" +"
" +msgstr "" + +#: src/enums/variant-payloads.md:1 +msgid "# Variant Payloads" +msgstr "" + +#: src/enums/variant-payloads.md:3 +msgid "" +"You can define richer enums where the variants carry data. You can then use the\n" +"`match` statement to extract the data from each variant:" +msgstr "" + +#: src/enums/variant-payloads.md:6 +msgid "" +"```rust,editable\n" +"enum WebEvent {\n" +" PageLoad, // Variant without payload\n" +" KeyPress(char), // Tuple struct variant\n" +" Click { x: i64, y: i64 }, // Full struct variant\n" +"}" +msgstr "" + +#: src/enums/variant-payloads.md:13 +msgid "" +"#[rustfmt::skip]\n" +"fn inspect(event: WebEvent) {\n" +" match event {\n" +" WebEvent::PageLoad => println!(\"page loaded\"),\n" +" WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" +" WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" +" }\n" +"}" +msgstr "" + +#: src/enums/variant-payloads.md:22 +msgid "" +"fn main() {\n" +" let load = WebEvent::PageLoad;\n" +" let press = WebEvent::KeyPress('x');\n" +" let click = WebEvent::Click { x: 20, y: 80 };" +msgstr "" + +#: src/enums/variant-payloads.md:27 +msgid "" +" inspect(load);\n" +" inspect(press);\n" +" inspect(click);\n" +"}\n" +"```" +msgstr "" + +#: src/enums/variant-payloads.md:35 +msgid "" +"* In the above example, accessing the `char` in `KeyPress`, or `x` and `y` in `Click` only works " +"within a `match` or an `if let` statement.\n" +"* `match` and `if let` inspect a hidden discriminant field in the `enum`.\n" +"* It is possible to retrieve the discriminant by calling `std::mem::discriminant()`\n" +" * This is useful, for example, if implementing `PartialEq` for structs where comparing field " +"values doesn't affect equality.\n" +"* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::Click(Click)` with a top level " +"`struct Click { ... }`. The inlined version cannot implement traits, for example." +msgstr "" + +#: src/enums/sizes.md:1 +msgid "# Enum Sizes" +msgstr "" + +#: src/enums/sizes.md:3 +msgid "Rust enums are packed tightly, taking constraints due to alignment into account:" +msgstr "" + +#: src/enums/sizes.md:5 +msgid "" +"```rust,editable\n" +"use std::mem::{align_of, size_of};" +msgstr "" + +#: src/enums/sizes.md:8 +msgid "" +"macro_rules! dbg_size {\n" +" ($t:ty) => {\n" +" println!(\"{}: size {} bytes, align: {} bytes\",\n" +" stringify!($t), size_of::<$t>(), align_of::<$t>());\n" +" };\n" +"}" +msgstr "" + +#: src/enums/sizes.md:15 +msgid "" +"enum Foo {\n" +" A,\n" +" B,\n" +"}" +msgstr "" + +#: src/enums/sizes.md:20 +msgid "" +"#[repr(u32)]\n" +"enum Bar {\n" +" A, // 0\n" +" B = 10000,\n" +" C, // 10001\n" +"}" +msgstr "" + +#: src/enums/sizes.md:27 +msgid "" +"fn main() {\n" +" dbg_size!(Foo);\n" +" dbg_size!(Bar);\n" +" dbg_size!(bool);\n" +" dbg_size!(Option);\n" +" dbg_size!(&i32);\n" +" dbg_size!(Option<&i32>);\n" +"}\n" +"```" +msgstr "" + +#: src/enums/sizes.md:37 +msgid "* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout.html)." +msgstr "" + +#: src/enums/sizes.md:39 +msgid "" +"
\n" +" \n" +"Key Points: \n" +" * Internally Rust is using a field (discriminant) to keep track of the enum variant.\n" +" * `Bar` enum demonstrates that there is a way to control the discriminant value and type. If " +"`repr` is removed, the discriminant type takes 2 bytes, becuase 10001 fits 2 bytes.\n" +" * As a niche optimization an enum discriminant is merged with the pointer so that `Option<&Foo>` " +"is the same size as `&Foo`.\n" +" * `Option` is another example of tight packing.\n" +" * For [some types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees that " +"`size_of::()` equals `size_of::>()`.\n" +" * Zero-sized types allow for efficient implementation of `HashSet` using `HashMap` with `()` as " +"the value." +msgstr "" + +#: src/enums/sizes.md:49 +msgid "" +"Example code if you want to show how the bitwise representation *may* look like in practice.\n" +"It's important to note that the compiler provides no guarantees regarding this representation, " +"therefore this is totally unsafe." +msgstr "" + +#: src/enums/sizes.md:52 +msgid "" +"```rust,editable\n" +"use std::mem::transmute;" +msgstr "" + +#: src/enums/sizes.md:55 src/enums/sizes.md:94 +msgid "" +"macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" +" };\n" +"}" +msgstr "" + +#: src/enums/sizes.md:61 +msgid "" +"fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" println!(\"Bitwise representation of bool\");\n" +" dbg_bits!(false, u8);\n" +" dbg_bits!(true, u8);" +msgstr "" + +#: src/enums/sizes.md:69 +msgid "" +" println!(\"Bitwise representation of Option\");\n" +" dbg_bits!(None::, u8);\n" +" dbg_bits!(Some(false), u8);\n" +" dbg_bits!(Some(true), u8);" +msgstr "" + +#: src/enums/sizes.md:74 +msgid "" +" println!(\"Bitwise representation of Option>\");\n" +" dbg_bits!(Some(Some(false)), u8);\n" +" dbg_bits!(Some(Some(true)), u8);\n" +" dbg_bits!(Some(None::), u8);\n" +" dbg_bits!(None::>, u8);" +msgstr "" + +#: src/enums/sizes.md:80 +msgid "" +" println!(\"Bitwise representation of Option<&i32>\");\n" +" dbg_bits!(None::<&i32>, usize);\n" +" dbg_bits!(Some(&0i32), usize);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/enums/sizes.md:87 +msgid "" +"More complex example if you want to discuss what happens when we chain more than 256 `Option`s " +"together." +msgstr "" + +#: src/enums/sizes.md:89 +msgid "" +"```rust,editable\n" +"#![recursion_limit = \"1000\"]" +msgstr "" + +#: src/enums/sizes.md:92 +msgid "use std::mem::transmute;" +msgstr "" + +#: src/enums/sizes.md:100 +msgid "" +"// Macro to wrap a value in 2^n Some() where n is the number of \"@\" signs.\n" +"// Increasing the recursion limit is required to evaluate this macro.\n" +"macro_rules! many_options {\n" +" ($value:expr) => { Some($value) };\n" +" ($value:expr, @) => {\n" +" Some(Some($value))\n" +" };\n" +" ($value:expr, @ $($more:tt)+) => {\n" +" many_options!(many_options!($value, $($more)+), $($more)+)\n" +" };\n" +"}" +msgstr "" + +#: src/enums/sizes.md:112 +msgid "" +"fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" assert_eq!(many_options!(false), Some(false));\n" +" assert_eq!(many_options!(false, @), Some(Some(false)));\n" +" assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));" +msgstr "" + +#: src/enums/sizes.md:120 +msgid "" +" println!(\"Bitwise representation of a chain of 128 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" +" dbg_bits!(many_options!(true, @@@@@@@), u8);" +msgstr "" + +#: src/enums/sizes.md:124 +msgid "" +" println!(\"Bitwise representation of a chain of 256 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(true, @@@@@@@@), u16);" +msgstr "" + +#: src/enums/sizes.md:128 +msgid "" +" println!(\"Bitwise representation of a chain of 257 Option's.\");\n" +" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/methods.md:3 +msgid "" +"Rust allows you to associate functions with your new types. You do this with an\n" +"`impl` block:" +msgstr "" + +#: src/methods.md:13 +msgid "" +"impl Person {\n" +" fn say_hello(&self) {\n" +" println!(\"Hello, my name is {}\", self.name);\n" +" }\n" +"}" +msgstr "" +"impl Person {\n" +" fn say_hello(&self) {\n" +" println!(\"Hola, mi nombre es {}\", self.name);\n" +" }\n" +"}" + +#: src/methods.md:19 +msgid "" +"fn main() {\n" +" let peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" peter.say_hello();\n" +"}\n" +"```" +msgstr "" + +#: src/methods.md:30 +msgid "" +"Key Points:\n" +"* It can be helpful to introduce methods by comparing them to functions.\n" +" * Methods are called on an instance of a type (such as a struct or enum), the first parameter " +"represents the instance as `self`.\n" +" * Developers may choose to use methods to take advantage of method receiver syntax and to help " +"keep them more organized. By using methods we can keep all the implementation code in one " +"predictable place.\n" +"* Point out the use of the keyword `self`, a method receiver. \n" +" * Show that it is an abbreviated term for `self:&Self` and perhaps show how the struct name " +"could also be used. \n" +" * Explain that `Self` is a type alias for the type the `impl` block is in and can be used " +"elsewhere in the block.\n" +" * Note how `self` is used like other structs and dot notation can be used to refer to individual " +"fields.\n" +" * This might be a good time to demonstrate how the `&self` differs from `self` by modifying the " +"code and trying to run say_hello twice. \n" +"* We describe the distinction between method receivers next.\n" +" \n" +"
" +msgstr "" + +#: src/methods/receiver.md:1 +msgid "# Method Receiver" +msgstr "" + +#: src/methods/receiver.md:3 +msgid "" +"The `&self` above indicates that the method borrows the object immutably. There\n" +"are other possible receivers for a method:" +msgstr "" + +#: src/methods/receiver.md:6 +msgid "" +"* `&self`: borrows the object from the caller using a shared and immutable\n" +" reference. The object can be used again afterwards.\n" +"* `&mut self`: borrows the object from the caller using a unique and mutable\n" +" reference. The object can be used again afterwards.\n" +"* `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" +"* No receiver: this becomes a static method on the struct. Typically used to\n" +" create constructors which are called `new` by convention." +msgstr "" + +#: src/methods/receiver.md:19 +msgid "" +"Beyond variants on `self`, there are also\n" +"[special wrapper types](https://doc.rust-lang.org/reference/special-types-and-traits.html)\n" +"allowed to be receiver types, such as `Box`." +msgstr "" + +#: src/methods/receiver.md:23 +msgid "" +"
\n" +" \n" +"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". These constraints always " +"come\n" +"together in Rust due to borrow checker rules, and `self` is no exception. It isn't possible to\n" +"reference a struct from multiple locations and call a mutating (`&mut self`) method on it.\n" +" \n" +"
" +msgstr "" + +#: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 +msgid "# Example" +msgstr "" + +#: src/methods/example.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Race {\n" +" name: String,\n" +" laps: Vec,\n" +"}" +msgstr "" + +#: src/methods/example.md:10 +msgid "" +"impl Race {\n" +" fn new(name: &str) -> Race { // No receiver, a static method\n" +" Race { name: String::from(name), laps: Vec::new() }\n" +" }" +msgstr "" + +#: src/methods/example.md:15 +msgid "" +" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write access to self\n" +" self.laps.push(lap);\n" +" }" +msgstr "" + +#: src/methods/example.md:19 +msgid "" +" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" +" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" +" for (idx, lap) in self.laps.iter().enumerate() {\n" +" println!(\"Lap {idx}: {lap} sec\");\n" +" }\n" +" }" +msgstr "" + +#: src/methods/example.md:26 +msgid "" +" fn finish(self) { // Exclusive ownership of self\n" +" let total = self.laps.iter().sum::();\n" +" println!(\"Race {} is finished, total lap time: {}\", self.name, total);\n" +" }\n" +"}" +msgstr "" + +#: src/methods/example.md:32 +msgid "" +"fn main() {\n" +" let mut race = Race::new(\"Monaco Grand Prix\");\n" +" race.add_lap(70);\n" +" race.add_lap(68);\n" +" race.print_laps();\n" +" race.add_lap(71);\n" +" race.print_laps();\n" +" race.finish();\n" +" // race.add_lap(42);\n" +"}\n" +"```" +msgstr "" + +#: src/methods/example.md:44 +msgid "" +"
\n" +" \n" +"Key Points:\n" +"* All four methods here use a different method receiver.\n" +" * You can point out how that changes what the function can do with the variable values and if/" +"how it can be used again in `main`.\n" +" * You can showcase the error that appears when trying to call `finish` twice.\n" +"* Note that although the method receivers are different, the non-static functions are called the " +"same way in the main body. Rust enables automatic referencing and dereferencing when calling " +"methods. Rust automatically adds in the `&`, `*`, `muts` so that that object matches the method " +"signature.\n" +"* You might point out that `print_laps` is using a vector that is iterated over. We describe " +"vectors in more detail in the afternoon. " +msgstr "" + +#: src/pattern-matching.md:1 +msgid "# Pattern Matching" +msgstr "" + +#: src/pattern-matching.md:3 +msgid "" +"The `match` keyword let you match a value against one or more _patterns_. The\n" +"comparisons are done from top to bottom and the first match wins." +msgstr "" + +#: src/pattern-matching.md:6 +msgid "The patterns can be simple values, similarly to `switch` in C and C++:" +msgstr "" + +#: src/pattern-matching.md:8 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let input = 'x';" +msgstr "" + +#: src/pattern-matching.md:12 +msgid "" +" match input {\n" +" 'q' => println!(\"Quitting\"),\n" +" 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" +" '0'..='9' => println!(\"Number input\"),\n" +" _ => println!(\"Something else\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching.md:21 +msgid "The `_` pattern is a wildcard pattern which matches any value." +msgstr "" + +#: src/pattern-matching.md:23 +msgid "" +"
\n" +" \n" +"Key Points:\n" +"* You might point out how some specific characters are being used when in a pattern\n" +" * `|` as an `or`\n" +" * `..` can expand as much as it needs to be\n" +" * `1..=5` represents an inclusive range\n" +" * `_` is a wild card\n" +"* It can be useful to show how binding works, by for instance replacing a wildcard character with " +"a variable, or removing the quotes around `q`.\n" +"* You can demonstrate matching on a reference.\n" +"* This might be a good time to bring up the concept of irrefutable patterns, as the term can show " +"up in error messages.\n" +" \n" +"
" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:1 +msgid "# Destructuring Enums" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:3 +msgid "" +"Patterns can also be used to bind variables to parts of your values. This is how\n" +"you inspect the structure of your types. Let us start with a simple `enum` type:" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:6 +msgid "" +"```rust,editable\n" +"enum Result {\n" +" Ok(i32),\n" +" Err(String),\n" +"}" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:12 +msgid "" +"fn divide_in_two(n: i32) -> Result {\n" +" if n % 2 == 0 {\n" +" Result::Ok(n / 2)\n" +" } else {\n" +" Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" +" }\n" +"}" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:20 +msgid "" +"fn main() {\n" +" let n = 100;\n" +" match divide_in_two(n) {\n" +" Result::Ok(half) => println!(\"{n} divided in two is {half}\"),\n" +" Result::Err(msg) => println!(\"sorry, an error happened: {msg}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:29 +msgid "" +"Here we have used the arms to _destructure_ the `Result` value. In the first\n" +"arm, `half` is bound to the value inside the `Ok` variant. In the second arm,\n" +"`msg` is bound to the error message." +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:35 +msgid "" +"Key points:\n" +"* The `if`/`else` expression is returning an enum that is later unpacked with a `match`.\n" +"* You can try adding a third variant to the enum definition and displaying the errors when running " +"the code. Point out the places where your code is now inexhaustive and how the compiler tries to " +"give you hints." +msgstr "" + +#: src/pattern-matching/destructuring-structs.md:1 +msgid "# Destructuring Structs" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md:3 +msgid "You can also destructure `structs`:" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Foo {\n" +" x: (u32, u32),\n" +" y: u32,\n" +"}" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md:11 +msgid "" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let foo = Foo { x: (1, 2), y: 3 };\n" +" match foo {\n" +" Foo { x: (1, b), y } => println!(\"x.0 = 1, b = {b}, y = {y}\"),\n" +" Foo { y: 2, x: i } => println!(\"y = 2, x = {i:?}\"),\n" +" Foo { y, .. } => println!(\"y = {y}, other fields were ignored\"),\n" +" }\n" +"}\n" +"```\n" +"
" +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.\n" +"
" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:1 +msgid "# Destructuring Arrays" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:3 +msgid "You can destructure arrays, tuples, and slices by matching on their elements:" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:5 +msgid "" +"```rust,editable\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let triple = [0, -2, 3];\n" +" println!(\"Tell me about {triple:?}\");\n" +" match triple {\n" +" [0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" [1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:21 +msgid "* Destructuring of slices of unknown length also works with patterns of fixed length." +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:24 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" inspect(&[0, -2, 3]);\n" +" inspect(&[0, -2, 3, 4]);\n" +"}" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:30 +msgid "" +"#[rustfmt::skip]\n" +"fn inspect(slice: &[i32]) {\n" +" println!(\"Tell me about {slice:?}\");\n" +" match slice {\n" +" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +"}\n" +"```\n" +" \n" +"* Create a new pattern using `_` to represent an element. \n" +"* Add more values to the array.\n" +"* Point out that how `..` will expand to account for different number of elements.\n" +"* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`" +msgstr "" + +#: src/pattern-matching/match-guards.md:1 +msgid "# Match Guards" +msgstr "" + +#: src/pattern-matching/match-guards.md:3 +msgid "" +"When matching, you can add a _guard_ to a pattern. This is an arbitrary Boolean\n" +"expression which will be executed if the pattern matches:" +msgstr "" + +#: src/pattern-matching/match-guards.md:6 +msgid "" +"```rust,editable\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let pair = (2, -2);\n" +" println!(\"Tell me about {pair:?}\");\n" +" match pair {\n" +" (x, y) if x == y => println!(\"These are twins\"),\n" +" (x, y) if x + y == 0 => println!(\"Antimatter, kaboom!\"),\n" +" (x, _) if x % 2 == 1 => println!(\"The first one is odd\"),\n" +" _ => println!(\"No correlation...\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/match-guards.md:22 +msgid "" +"Key Points:\n" +"* Match guards as a separate syntax feature are important and necessary when we wish to concisely " +"express more complex ideas than patterns alone would allow.\n" +"* They are not the same as separate `if` expression inside of the match arm. An `if` expression " +"inside of the branch block (after `=>`) happens after the match arm is selected. Failing the `if` " +"condition inside of that block won't result in other arms\n" +"of the original `match` expression being considered. \n" +"* You can use the variables defined in the pattern in your if expression.\n" +"* The condition defined in the guard applies to every expression in a pattern with an `|`.\n" +"
" +msgstr "" + +#: src/exercises/day-2/morning.md:1 +msgid "# Day 2: Morning Exercises" +msgstr "" + +#: src/exercises/day-2/morning.md:3 +msgid "We will look at implementing methods in two contexts:" +msgstr "" + +#: src/exercises/day-2/morning.md:5 +msgid "* Simple struct which tracks health statistics." +msgstr "" + +#: src/exercises/day-2/morning.md:7 +msgid "* Multiple structs and enums for a drawing library." +msgstr "" + +#: src/exercises/day-2/health-statistics.md:1 +msgid "# Health Statistics" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:3 +msgid "" +"You're working on implementing a health-monitoring system. As part of that, you\n" +"need to keep track of users' health statistics." +msgstr "" + +#: src/exercises/day-2/health-statistics.md:6 +msgid "" +"You'll start with some stubbed functions in an `impl` block as well as a `User`\n" +"struct definition. Your goal is to implement the stubbed out methods on the\n" +"`User` `struct` defined in the `impl` block." +msgstr "" + +#: src/exercises/day-2/health-statistics.md:10 +msgid "" +"Copy the code below to and fill in the missing\n" +"methods:" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:17 +msgid "" +"struct User {\n" +" name: String,\n" +" age: u32,\n" +" weight: f32,\n" +"}" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:23 +msgid "" +"impl User {\n" +" pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +" unimplemented!()\n" +" }" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:28 +msgid "" +" pub fn name(&self) -> &str {\n" +" unimplemented!()\n" +" }" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:32 +msgid "" +" pub fn age(&self) -> u32 {\n" +" unimplemented!()\n" +" }" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:36 +msgid "" +" pub fn weight(&self) -> f32 {\n" +" unimplemented!()\n" +" }" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:40 +msgid "" +" pub fn set_age(&mut self, new_age: u32) {\n" +" unimplemented!()\n" +" }" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:44 +msgid "" +" pub fn set_weight(&mut self, new_weight: f32) {\n" +" unimplemented!()\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:49 +msgid "" +"fn main() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" +"}" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:54 +msgid "" +"#[test]\n" +"fn test_weight() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.weight(), 155.2);\n" +"}" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:60 +msgid "" +"#[test]\n" +"fn test_set_age() {\n" +" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.age(), 32);\n" +" bob.set_age(33);\n" +" assert_eq!(bob.age(), 33);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:1 +msgid "# Polygon Struct" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:3 +msgid "" +"We will create a `Polygon` struct which contain some points. Copy the code below\n" +"to and fill in the missing methods to make the\n" +"tests pass:" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:7 src/exercises/day-2/luhn.md:23 +#: src/exercises/day-2/strings-iterators.md:12 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:11 +msgid "" +"pub struct Point {\n" +" // add fields\n" +"}" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:15 +msgid "" +"impl Point {\n" +" // add methods\n" +"}" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:19 +msgid "" +"pub struct Polygon {\n" +" // add fields\n" +"}" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:23 +msgid "" +"impl Polygon {\n" +" // add methods\n" +"}" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:27 +msgid "" +"pub struct Circle {\n" +" // add fields\n" +"}" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:31 +msgid "" +"impl Circle {\n" +" // add methods\n" +"}" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:35 +msgid "" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:40 src/testing/test-modules.md:15 +msgid "" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:44 src/exercises/day-2/solutions-morning.md:165 +msgid "" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:48 src/exercises/day-2/solutions-morning.md:169 +msgid "" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:54 src/exercises/day-2/solutions-morning.md:175 +msgid "" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:61 src/exercises/day-2/solutions-morning.md:182 +msgid "" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:68 src/exercises/day-2/solutions-morning.md:189 +msgid "" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:73 src/exercises/day-2/solutions-morning.md:194 +msgid "" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:79 src/exercises/day-2/solutions-morning.md:200 +msgid "" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:84 src/exercises/day-2/solutions-morning.md:205 +msgid "" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:88 src/exercises/day-2/solutions-morning.md:209 +msgid "" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:92 +msgid "" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:111 src/exercises/day-2/luhn.md:68 +msgid "" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:117 +msgid "" +"Since the method signatures are missing from the problem statements, the key part\n" +"of the exercise is to specify those correctly. You don't have to modify the tests." +msgstr "" + +#: src/exercises/day-2/points-polygons.md:120 +msgid "" +"Other interesting parts of the exercise:\n" +" \n" +"* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their " +"arguments.\n" +"* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". Note that " +"we do not discuss generics until Day 3." +msgstr "" + +#: src/control-flow.md:1 +msgid "# Control Flow" +msgstr "" + +#: src/control-flow.md:3 +msgid "" +"As we have seen, `if` is an expression in Rust. It is used to conditionally\n" +"evaluate one of two blocks, but the blocks can have a value which then becomes\n" +"the value of the `if` expression. Other control flow expressions work similarly\n" +"in Rust." +msgstr "" + +#: src/control-flow/blocks.md:1 +msgid "# Blocks" +msgstr "" + +#: src/control-flow/blocks.md:3 +msgid "" +"A block in Rust has a value and a type: the value is the last expression of the\n" +"block:" +msgstr "" + +#: src/control-flow/blocks.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = {\n" +" let y = 10;\n" +" println!(\"y: {y}\");\n" +" let z = {\n" +" let w = {\n" +" 3 + 4\n" +" };\n" +" println!(\"w: {w}\");\n" +" y * w\n" +" };\n" +" println!(\"z: {z}\");\n" +" z - y\n" +" };\n" +" println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:25 +msgid "" +"The same rule is used for functions: the value of the function body is the\n" +"return value:" +msgstr "" + +#: src/control-flow/blocks.md:28 +msgid "" +"```rust,editable\n" +"fn double(x: i32) -> i32 {\n" +" x + x\n" +"}" +msgstr "" + +#: src/control-flow/blocks.md:33 +msgid "" +"fn main() {\n" +" println!(\"doubled: {}\", double(7));\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:38 +msgid "However if the last expression ends with `;`, then the resulting value and type is `()`." +msgstr "" + +#: src/control-flow/blocks.md:42 +msgid "" +"Key Points:\n" +"* The point of this slide is to show that blocks have a type and value in Rust. \n" +"* You can show how the value of the block changes by changing the last line in the block. For " +"instance, adding/removing a semicolon or using a `return`.\n" +" \n" +"" +msgstr "" + +#: src/control-flow/if-expressions.md:1 +msgid "# `if` expressions" +msgstr "" + +#: src/control-flow/if-expressions.md:3 +msgid "You use `if` very similarly to how you would in other languages:" +msgstr "" + +#: src/control-flow/if-expressions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" if x % 2 == 0 {\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:16 +msgid "In addition, you can use it as an expression. This does the same as above:" +msgstr "" + +#: src/control-flow/if-expressions.md:18 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:31 +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.\n" +" \n" +"" +msgstr "" + +#: src/control-flow/if-let-expressions.md:1 +msgid "# `if let` expressions" +msgstr "" + +#: src/control-flow/if-let-expressions.md:3 +msgid "If you want to match a value against a pattern, you can use `if let`:" +msgstr "" + +#: src/control-flow/if-let-expressions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let arg = std::env::args().next();\n" +" if let Some(value) = arg {\n" +" println!(\"Program name: {value}\");\n" +" } else {\n" +" println!(\"Missing name?\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-let-expressions.md:16 src/control-flow/while-let-expressions.md:21 +#: src/control-flow/match-expressions.md:22 +msgid "" +"See [pattern matching](../pattern-matching.md) for more details on patterns in\n" +"Rust." +msgstr "" + +#: src/control-flow/if-let-expressions.md:21 +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" +" * For the similar use case consider demonstrating a newly stabilized [`let else`](https://" +"github.com/rust-lang/rust/pull/93628) feature.\n" +"* A common usage is handling `Some` values when working with `Option`.\n" +"* Unlike `match`, `if let` does not support guard clauses for pattern matching." +msgstr "" + +#: src/control-flow/while-expressions.md:1 +msgid "# `while` expressions" +msgstr "" + +#: src/control-flow/while-expressions.md:3 +msgid "The `while` keyword works very similar to other languages:" +msgstr "" + +#: src/control-flow/while-expressions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" while x != 1 {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/while-let-expressions.md:1 +msgid "# `while let` expressions" +msgstr "" + +#: src/control-flow/while-let-expressions.md:3 +msgid "" +"Like with `if`, there is a `while let` variant which repeatedly tests a value\n" +"against a pattern:" +msgstr "" + +#: src/control-flow/while-let-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();" +msgstr "" + +#: src/control-flow/while-let-expressions.md:11 +msgid "" +" while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/while-let-expressions.md:17 +msgid "" +"Here the iterator returned by `v.iter()` will return a `Option` on every\n" +"call to `next()`. It returns `Some(x)` until it is done, after which it will\n" +"return `None`. The `while let` lets us keep iterating through all items." +msgstr "" + +#: src/control-flow/while-let-expressions.md:27 +msgid "" +"* Point out that the `while let` loop will keep going as long as the value matches the pattern.\n" +"* You could rewrite the `while let` loop as an infinite loop with an if statement that breaks when " +"there is no value to unwrap for `iter.next()`. The `while let` provides syntactic sugar for the " +"above scenario.\n" +" \n" +"" +msgstr "" + +#: src/control-flow/for-expressions.md:1 +msgid "# `for` expressions" +msgstr "" + +#: src/control-flow/for-expressions.md:3 +msgid "" +"The `for` expression is closely related to the `while let` expression. It will\n" +"automatically call `into_iter()` on the expression and then iterate over it:" +msgstr "" + +#: src/control-flow/for-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];" +msgstr "" + +#: src/control-flow/for-expressions.md:10 +msgid "" +" for x in v {\n" +" println!(\"x: {x}\");\n" +" }\n" +" \n" +" for i in (0..10).step_by(2) {\n" +" println!(\"i: {i}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/for-expressions.md:20 +msgid "You can use `break` and `continue` here as usual." +msgstr "" + +#: src/control-flow/for-expressions.md:22 +msgid "" +"
\n" +" \n" +"* Index iteration is not a special syntax in Rust for just that case.\n" +"* `(0..10)` is a range that implements an `Iterator` trait. \n" +"* `step_by` is a method that returns another `Iterator` that skips every other element. \n" +"* Modify the elements in the vector and explain the compiler errors. Change vector `v` to be " +"mutable and the for loop to `for x in v.iter_mut()`." +msgstr "" + +#: src/control-flow/loop-expressions.md:1 +msgid "# `loop` expressions" +msgstr "" + +#: src/control-flow/loop-expressions.md:3 +msgid "" +"Finally, there is a `loop` keyword which creates an endless loop. Here you must\n" +"either `break` or `return` to stop the loop:" +msgstr "" + +#: src/control-flow/loop-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" loop {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" if x == 1 {\n" +" break;\n" +" }\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/loop-expressions.md:23 +msgid "" +"
\n" +" \n" +"* Break the `loop` with a value (e.g. `break 8`) and print it out." +msgstr "" + +#: src/control-flow/match-expressions.md:1 +msgid "# `match` expressions" +msgstr "" + +#: src/control-flow/match-expressions.md:3 +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:" +msgstr "" + +#: src/control-flow/match-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" match std::env::args().next().as_deref() {\n" +" Some(\"cat\") => println!(\"Will do cat things\"),\n" +" Some(\"ls\") => println!(\"Will ls some files\"),\n" +" Some(\"mv\") => println!(\"Let's move some files\"),\n" +" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" +" None => println!(\"Hmm, no program name?\"),\n" +" _ => println!(\"Unknown program name!\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/match-expressions.md:19 +msgid "" +"Like `if let`, each match arm must have the same type. The type is the last\n" +"expression of the block, if any. In the example above, the type is `()`." +msgstr "" + +#: src/control-flow/match-expressions.md:27 +msgid "" +"* Save the match expression to a variable and print it out.\n" +"* Remove `.as_deref()` and explain the error.\n" +" * `std::env::args().next()` returns an `Option`, but we cannot match against " +"`String`.\n" +" * `as_deref()` transforms an `Option` to `Option<&T::Target>`. In our case, this turns " +"`Option` into `Option<&str>`.\n" +" * We can now use pattern matching to match against the `&str` inside `Option`.\n" +"
" +msgstr "" + +#: src/control-flow/break-continue.md:1 +msgid "# `break` and `continue`" +msgstr "" + +#: src/control-flow/break-continue.md:3 +msgid "" +"If you want to exit a loop early, use `break`, 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:" +msgstr "" + +#: src/control-flow/break-continue.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +" 'outer: while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" let mut i = 0;\n" +" while i < x {\n" +" println!(\"x: {x}, i: {i}\");\n" +" i += 1;\n" +" if i == 3 {\n" +" break 'outer;\n" +" }\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/break-continue.md:25 +msgid "In this case we break the outer loop after 3 iterations of the inner loop." +msgstr "" + +#: src/std.md:1 +msgid "# Standard Library" +msgstr "" + +#: src/std.md:3 +msgid "" +"Rust comes with a standard library which helps establish a set of common types\n" +"used by Rust library and programs. This way, two libraries can work together\n" +"smoothly because they both use the same `String` type." +msgstr "" + +#: src/std.md:7 +msgid "The common vocabulary types include:" +msgstr "" + +#: src/std.md:9 +msgid "" +"* [`Option` and `Result`](std/option-result.md) types: used for optional values\n" +" and [error handling](error-handling.md)." +msgstr "" + +#: src/std.md:12 +msgid "* [`String`](std/string.md): the default string type used for owned data." +msgstr "" + +#: src/std.md:14 +msgid "* [`Vec`](std/vec.md): a standard extensible vector." +msgstr "" + +#: src/std.md:16 +msgid "" +"* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" +" algorithm." +msgstr "" + +#: src/std.md:19 +msgid "* [`Box`](std/box.md): an owned pointer for heap-allocated data." +msgstr "" + +#: src/std.md:21 +msgid "* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated data." +msgstr "" + +#: src/std.md:23 +msgid "" +"
\n" +" \n" +" * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. \n" +" * `core` includes the most basic types and functions that don't depend on `libc`, allocator or\n" +" even the presence of an operating system. \n" +" * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`.\n" +" * Embedded Rust applications often only use `core`, and sometimes `alloc`." +msgstr "" + +#: src/std/option-result.md:1 +msgid "# `Option` and `Result`" +msgstr "" + +#: src/std/option-result.md:3 +msgid "The types represent optional data:" +msgstr "" + +#: src/std/option-result.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let numbers = vec![10, 20, 30];\n" +" let first: Option<&i8> = numbers.first();\n" +" println!(\"first: {first:?}\");" +msgstr "" + +#: src/std/option-result.md:11 +msgid "" +" let idx: Result = numbers.binary_search(&10);\n" +" println!(\"idx: {idx:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/option-result.md:18 +msgid "" +"* `Option` and `Result` are widely used not just in the standard library.\n" +"* `Option<&T>` has zero space overhead compared to `&T`.\n" +"* `Result` is the standard type to implement error handling as we will see on Day 3.\n" +"* `binary_search` returns `Result`.\n" +" * If found, `Result::Ok` holds the index where the element is found.\n" +" * Otherwise, `Result::Err` contains the index where such an element should be inserted." +msgstr "" + +#: src/std/string.md:1 +msgid "# String" +msgstr "" + +#: src/std/string.md:3 +msgid "[`String`][1] is the standard heap-allocated growable UTF-8 string buffer:" +msgstr "" + +#: src/std/string.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut s1 = String::new();\n" +" s1.push_str(\"Hello\");\n" +" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());" +msgstr "" + +#: src/std/string.md:11 +msgid "" +" let mut s2 = String::with_capacity(s1.len() + 1);\n" +" s2.push_str(&s1);\n" +" s2.push('!');\n" +" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());" +msgstr "" + +#: src/std/string.md:16 +msgid "" +" let s3 = String::from(\"🇨🇭\");\n" +" println!(\"s3: len = {}, number of chars = {}\", s3.len(),\n" +" s3.chars().count());\n" +"}\n" +"```" +msgstr "" + +#: src/std/string.md:22 +msgid "" +"`String` implements [`Deref`][2], which means that you can call all\n" +"`str` methods on a `String`." +msgstr "" + +#: src/std/string.md:25 +msgid "" +"[1]: https://doc.rust-lang.org/std/string/struct.String.html\n" +"[2]: https://doc.rust-lang.org/std/string/struct.String.html#deref-methods-str" +msgstr "" + +#: src/std/string.md:30 +msgid "" +"* `len()` returns the size of the `String` in bytes, not its length in characters.\n" +"* `chars()` returns an iterator over the actual characters." +msgstr "" + +#: src/std/vec.md:1 +msgid "# `Vec`" +msgstr "" + +#: src/std/vec.md:3 +msgid "[`Vec`][1] is the standard resizable heap-allocated buffer:" +msgstr "" + +#: src/std/vec.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut v1 = Vec::new();\n" +" v1.push(42);\n" +" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());" +msgstr "" + +#: src/std/vec.md:11 +msgid "" +" let mut v2 = Vec::with_capacity(v1.len() + 1);\n" +" v2.extend(v1.iter());\n" +" v2.push(9999);\n" +" println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());" +msgstr "" + +#: src/std/vec.md:16 +msgid "" +" // Canonical macro to initialize a vector with elements.\n" +" let mut v3 = vec![0, 0, 1, 2, 3, 4];" +msgstr "" + +#: src/std/vec.md:19 +msgid "" +" // Retain only the even elements.\n" +" v3.retain(|x| x % 2 == 0);\n" +" println!(\"{v3:?}\");" +msgstr "" + +#: src/std/vec.md:23 +msgid "" +" // Remove consecutive duplicates.\n" +" v3.dedup();\n" +" println!(\"{v3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/vec.md:29 +msgid "" +"`Vec` implements [`Deref`][2], which means that you can call slice\n" +"methods on a `Vec`." +msgstr "" + +#: src/std/vec.md:32 +msgid "" +"[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" +"[2]: https://doc.rust-lang.org/std/vec/struct.Vec.html#deref-methods-[T]" +msgstr "" + +#: src/std/vec.md:37 +msgid "" +"* `Vec` is a type of collection, along with `String` and `HashMap`. The data it contains is " +"stored\n" +" on the heap. This means the amount of data doesn't need to be known at compile time. It can " +"grow\n" +" or shrink at runtime.\n" +"* Notice how `Vec` is a generic type too, but you don't have to specify `T` explicitly. As " +"always\n" +" with Rust type inference, the `T` was established during the first `push` call.\n" +"* `vec![...]` is a canonical macro to use instead of `Vec::new()` and it supports adding initial\n" +" elements to the vector.\n" +"* To index the vector you use `[` `]`, but they will panic if out of bounds. Alternatively, using\n" +" `get` will return an `Option`. The `pop` function will remove the last element.\n" +"* Show iterating over a vector and mutating the value:\n" +" `for e in &mut v { *e += 50; }`" +msgstr "" + +#: src/std/hashmap.md:1 +msgid "# `HashMap`" +msgstr "" + +#: src/std/hashmap.md:3 +msgid "Standard hash map with protection against HashDoS attacks:" +msgstr "" + +#: src/std/hashmap.md:5 +msgid "" +"```rust,editable\n" +"use std::collections::HashMap;" +msgstr "" + +#: src/std/hashmap.md:8 +msgid "" +"fn main() {\n" +" let mut page_counts = HashMap::new();\n" +" page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), 207);\n" +" page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" +" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);" +msgstr "" + +#: src/std/hashmap.md:14 +msgid "" +" if !page_counts.contains_key(\"Les Misérables\") {\n" +" println!(\"We know about {} books, but not Les Misérables.\",\n" +" page_counts.len());\n" +" }" +msgstr "" + +#: src/std/hashmap.md:19 +msgid "" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" +" match page_counts.get(book) {\n" +" Some(count) => println!(\"{book}: {count} pages\"),\n" +" None => println!(\"{book} is unknown.\")\n" +" }\n" +" }" +msgstr "" + +#: src/std/hashmap.md:26 +msgid "" +" // Use the .entry() method to insert a value if nothing is found.\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" +" let page_count: &mut i32 = page_counts.entry(book.to_string()).or_insert(0);\n" +" *page_count += 1;\n" +" }" +msgstr "" + +#: src/std/hashmap.md:32 +msgid "" +" println!(\"{page_counts:#?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/hashmap.md:38 +msgid "" +"* `HashMap` is not defined in the prelude and needs to be brought into scope.\n" +"* Try the following lines of code. The first line will see if a book is in the hashmap and if not " +"return an alternative value. The second line will insert the alternative value in the hashmap if " +"the book is not found." +msgstr "" + +#: src/std/hashmap.md:41 +msgid "" +" ```rust,ignore\n" +" let pc1 = page_counts\n" +" .get(\"Harry Potter and the Sorcerer's Stone \")\n" +" .unwrap_or(&336);\n" +" let pc2 = page_counts\n" +" .entry(\"The Hunger Games\".to_string())\n" +" .or_insert(374);\n" +" ```\n" +"* Unlike `vec!`, there is unfortunately no standard `hashmap!` macro.\n" +" * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], which allows us to " +"easily initialize a hash map from a literal array:" +msgstr "" + +#: src/std/hashmap.md:52 +msgid "" +" ```rust,ignore\n" +" let page_counts = HashMap::from([\n" +" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" +" (\"The Hunger Games\".to_string(), 374),\n" +" ]);\n" +" ```" +msgstr "" + +#: src/std/hashmap.md:59 +msgid "" +" * Alternatively HashMap can be built from any `Iterator` which yields key-value tuples.\n" +"* We are showing `HashMap`, and avoid using `&str` as key to make examples easier. " +"Using references in collections can, of course, be done,\n" +" but it can lead into complications with the borrow checker.\n" +" * Try removing `to_string()` from the example above and see if it still compiles. Where do you " +"think we might run into issues?" +msgstr "" + +#: src/std/hashmap.md:64 +msgid "" +"[1]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#impl-" +"From%3C%5B(K%2C%20V)%3B%20N%5D%3E-for-HashMap%3CK%2C%20V%2C%20RandomState%3E" +msgstr "" + +#: src/std/box.md:1 +msgid "# `Box`" +msgstr "" + +#: src/std/box.md:3 +msgid "[`Box`][1] is an owned pointer to data on the heap:" +msgstr "" + +#: src/std/box.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let five = Box::new(5);\n" +" println!(\"five: {}\", *five);\n" +"}\n" +"```" +msgstr "" + +#: src/std/box.md:13 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - -. .- - - - - - -.\n" +": : : :\n" +": five : : :\n" +": +-----+ : : +-----+ :\n" +": | o---|---+-----+-->| 5 | :\n" +": +-----+ : : +-----+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - -' `- - - - - - -'\n" +"```" +msgstr "" + +#: src/std/box.md:26 +msgid "" +"`Box` implements `Deref`, which means that you can [call methods\n" +"from `T` directly on a `Box`][2]." +msgstr "" + +#: src/std/box.md:29 +msgid "" +"[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" +"[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion" +msgstr "" + +#: src/std/box.md:34 +msgid "" +"* `Box` is like `std::unique_ptr` in C++. \n" +"* In the above example, you can even leave out the `*` in the `println!` statement thanks to " +"`Deref`. \n" +"* A `Box` can be useful when you:\n" +" * have a type whose size that can't be known at compile time, but the Rust compiler wants to " +"know an exact size.\n" +" * want to transfer ownership of a large amount of data. To avoid copying large amounts of data " +"on the stack, instead store the data on the heap in a `Box` so only the pointer is moved.\n" +"
" +msgstr "" + +#: src/std/box-recursive.md:1 +msgid "# Box with Recursive Data Structures" +msgstr "" + +#: src/std/box-recursive.md:3 +msgid "Recursive data types or data types with dynamic sizes need to use a `Box`:" +msgstr "" + +#: src/std/box-recursive.md:5 src/std/box-niche.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"enum List {\n" +" Cons(T, Box>),\n" +" Nil,\n" +"}" +msgstr "" + +#: src/std/box-recursive.md:12 src/std/box-niche.md:10 +msgid "" +"fn main() {\n" +" let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));\n" +" println!(\"{list:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/box-recursive.md:18 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": list : : :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----+ :\n" +": | Cons | 1 | o--+----+-----+--->| Cons | 2 | o--+--->| Nil | // | // | :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----+ :\n" +": : : :\n" +": : : :\n" +"'- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/std/box-recursive.md:33 +msgid "" +"* If the `Box` was not used here and we attempted to embed a `List` directly into the `List`,\n" +"the compiler would not compute a fixed size of the struct in memory, it would look infinite." +msgstr "" + +#: src/std/box-recursive.md:36 +msgid "" +"* `Box` solves this problem as it has the same size as a regular pointer and just points at the " +"next\n" +"element of the `List` in the heap." +msgstr "" + +#: src/std/box-recursive.md:39 +msgid "" +"* Remove the `Box` in the List definition and show the compiler error. \"Recursive with " +"indirection\" is a hint you might want to use a Box or reference of some kind, instead of storing " +"a value directly. \n" +" \n" +"
" +msgstr "" + +#: src/std/box-niche.md:1 +msgid "# Niche Optimization" +msgstr "" + +#: src/std/box-niche.md:16 +msgid "" +"A `Box` cannot be empty, so the pointer is always valid and non-`null`. This\n" +"allows the compiler to optimize the memory layout:" +msgstr "" + +#: src/std/box-niche.md:19 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": list : : :\n" +": +----+----+ : : +----+----+ +----+------+ :\n" +": | 1 | o--+-----------+-----+--->| 2 | o--+--->| // | null | :\n" +": +----+----+ : : +----+----+ +----+------+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/std/rc.md:1 +msgid "# `Rc`" +msgstr "" + +#: src/std/rc.md:3 +msgid "" +"[`Rc`][1] is a reference-counted shared pointer. Use this when you need to refer\n" +"to the same data from multiple places:" +msgstr "" + +#: src/std/rc.md:6 +msgid "" +"```rust,editable\n" +"use std::rc::Rc;" +msgstr "" + +#: src/std/rc.md:9 +msgid "" +"fn main() {\n" +" let mut a = Rc::new(10);\n" +" let mut b = a.clone();" +msgstr "" + +#: src/std/rc.md:18 +msgid "" +"* If you need to mutate the data inside an `Rc`, you will need to wrap the data in\n" +" a type such as [`Cell` or `RefCell`][2].\n" +"* See [`Arc`][3] if you are in a multi-threaded context.\n" +"* You can *downgrade* a shared pointer into a [`Weak`][4] pointer to create cycles\n" +" that will get dropped." +msgstr "" + +#: src/std/rc.md:24 +msgid "" +"[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" +"[2]: https://doc.rust-lang.org/std/cell/index.html\n" +"[3]: ../concurrency/shared_state/arc.md\n" +"[4]: https://doc.rust-lang.org/std/rc/struct.Weak.html" +msgstr "" + +#: src/std/rc.md:31 +msgid "" +"* Like C++'s `std::shared_ptr`.\n" +"* `clone` is cheap: creates a pointer to the same allocation and increases the reference count.\n" +"* `make_mut` actually clones the inner value if necessary (\"clone-on-write\") and returns a " +"mutable reference.\n" +"* You can `downgrade()` a `Rc` into a *weakly reference-counted* object to\n" +" create cycles that will be dropped properly (likely in combination with\n" +" `RefCell`)." +msgstr "" + +#: src/std/rc.md:38 +msgid "" +"```rust,editable\n" +"use std::rc::{Rc, Weak};\n" +"use std::cell::RefCell;" +msgstr "" + +#: src/std/rc.md:42 +msgid "" +"#[derive(Debug)]\n" +"struct Node {\n" +" value: i64,\n" +" parent: Option>>,\n" +" children: Vec>>,\n" +"}" +msgstr "" + +#: src/std/rc.md:49 +msgid "" +"fn main() {\n" +" let mut root = Rc::new(RefCell::new(Node {\n" +" value: 42,\n" +" parent: None,\n" +" children: vec![],\n" +" }));\n" +" let child = Rc::new(RefCell::new(Node {\n" +" value: 43,\n" +" children: vec![],\n" +" parent: Some(Rc::downgrade(&root))\n" +" }));\n" +" root.borrow_mut().children.push(child);" +msgstr "" + +#: src/std/rc.md:62 +msgid "" +" println!(\"graph: {root:#?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/modules.md:1 +msgid "# Modules" +msgstr "" + +#: src/modules.md:3 +msgid "We have seen how `impl` blocks let us namespace functions to a type." +msgstr "" + +#: src/modules.md:5 +msgid "Similarly, `mod` lets us namespace types and functions:" +msgstr "" + +#: src/modules.md:7 +msgid "" +"```rust,editable\n" +"mod foo {\n" +" pub fn do_something() {\n" +" println!(\"In the foo module\");\n" +" }\n" +"}" +msgstr "" + +#: src/modules.md:14 +msgid "" +"mod bar {\n" +" pub fn do_something() {\n" +" println!(\"In the bar module\");\n" +" }\n" +"}" +msgstr "" + +#: src/modules.md:20 +msgid "" +"fn main() {\n" +" foo::do_something();\n" +" bar::do_something();\n" +"}\n" +"```" +msgstr "" + +#: src/modules.md:28 +msgid "" +"* Packages provide functionality and include a `Cargo.toml` file that describes how to build a " +"bundle of 1+ crates.\n" +"* Crates are a tree of modules, where a binary crate creates an executable and a library crate " +"compiles to a library.\n" +"* Modules define organization, scope, and are the focus of this section." +msgstr "" + +#: src/modules/visibility.md:1 +msgid "# Visibility" +msgstr "" + +#: src/modules/visibility.md:3 +msgid "Modules are a privacy boundary:" +msgstr "" + +#: src/modules/visibility.md:5 +msgid "" +"* Module items are private by default (hides implementation details).\n" +"* Parent and sibling items are always visible.\n" +"* In other words, if an item is visible in module `foo`, it's visible in all the\n" +" descendants of `foo`." +msgstr "" + +#: src/modules/visibility.md:10 +msgid "" +"```rust,editable\n" +"mod outer {\n" +" fn private() {\n" +" println!(\"outer::private\");\n" +" }" +msgstr "" + +#: src/modules/visibility.md:16 +msgid "" +" pub fn public() {\n" +" println!(\"outer::public\");\n" +" }" +msgstr "" + +#: src/modules/visibility.md:20 +msgid "" +" mod inner {\n" +" fn private() {\n" +" println!(\"outer::inner::private\");\n" +" }" +msgstr "" + +#: src/modules/visibility.md:25 +msgid "" +" pub fn public() {\n" +" println!(\"outer::inner::public\");\n" +" super::private();\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/modules/visibility.md:32 +msgid "" +"fn main() {\n" +" outer::public();\n" +"}\n" +"```" +msgstr "" + +#: src/modules/visibility.md:39 +msgid "* Use the `pub` keyword to make modules public." +msgstr "" + +#: src/modules/visibility.md:41 +msgid "" +"Additionally, there are advanced `pub(...)` specifiers to restrict the scope of public visibility." +msgstr "" + +#: src/modules/visibility.md:43 +msgid "" +"* See the [Rust Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-" +"path-pubcrate-pubsuper-and-pubself)).\n" +"* Configuring `pub(crate)` visibility is a common pattern.\n" +"* Less commonly, you can give visibility to a specific path.\n" +"* In any case, visibility must be granted to an ancestor module (and all of its descendants)." +msgstr "" + +#: src/modules/paths.md:1 +msgid "# Paths" +msgstr "" + +#: src/modules/paths.md:3 +msgid "Paths are resolved as follows:" +msgstr "" + +#: src/modules/paths.md:5 +msgid "" +"1. As a relative path:\n" +" * `foo` or `self::foo` refers to `foo` in the current module,\n" +" * `super::foo` refers to `foo` in the parent module." +msgstr "" + +#: src/modules/paths.md:9 +msgid "" +"2. As an absolute path:\n" +" * `crate::foo` refers to `foo` in the root of the current crate,\n" +" * `bar::foo` refers to `foo` in the `bar` crate." +msgstr "" + +#: src/modules/filesystem.md:1 +msgid "# Filesystem Hierarchy" +msgstr "" + +#: src/modules/filesystem.md:3 +msgid "The module content can be omitted:" +msgstr "" + +#: src/modules/filesystem.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"mod garden;\n" +"```" +msgstr "" + +#: src/modules/filesystem.md:9 +msgid "The `garden` module content is found at:" +msgstr "" + +#: src/modules/filesystem.md:11 +msgid "" +"* `src/garden.rs` (modern Rust 2018 style)\n" +"* `src/garden/mod.rs` (older Rust 2015 style)" +msgstr "" + +#: src/modules/filesystem.md:14 +msgid "Similarly, a `garden::vegetables` module can be found at:" +msgstr "" + +#: src/modules/filesystem.md:16 +msgid "" +"* `src/garden/vegetables.rs` (modern Rust 2018 style)\n" +"* `src/garden/vegetables/mod.rs` (older Rust 2015 style)" +msgstr "" + +#: src/modules/filesystem.md:19 +msgid "The `crate` root is in:" +msgstr "" + +#: src/modules/filesystem.md:21 +msgid "" +"* `src/lib.rs` (for a library crate)\n" +"* `src/main.rs` (for a binary crate)" +msgstr "" + +#: src/modules/filesystem.md:26 +msgid "" +"* The change from `module/mod.rs` to `module.rs` doesn't preclude the use of submodules in Rust " +"2018.\n" +" (It was mandatory in Rust 2015.)" +msgstr "" + +#: src/modules/filesystem.md:29 +msgid " The following is valid:" +msgstr "" + +#: src/modules/filesystem.md:31 +msgid "" +" ```ignore\n" +" src/\n" +" ├── main.rs\n" +" ├── top_module.rs\n" +" └── top_module/\n" +" └── sub_module.rs\n" +" ```" +msgstr "" + +#: src/modules/filesystem.md:39 +msgid "" +"* The main reason for the change is to prevent many files named `mod.rs`, which can be hard\n" +" to distinguish in IDEs." +msgstr "" + +#: src/modules/filesystem.md:42 +msgid "" +"* Rust will look for modules in `modulename/mod.rs` and `modulename.rs`, but this can be changed\n" +" with a compiler directive:" +msgstr "" + +#: src/modules/filesystem.md:45 +msgid "" +" ```rust,ignore\n" +" #[path = \"some/path.rs\"]\n" +" mod some_module { }\n" +" ```" +msgstr "" + +#: src/modules/filesystem.md:50 +msgid "" +" This is useful, for example, if you would like to place tests for a module in a file named\n" +" `some_module_test.rs`, similar to the convention in Go." +msgstr "" + +#: src/exercises/day-2/afternoon.md:1 +msgid "# Day 2: Afternoon Exercises" +msgstr "" + +#: src/exercises/day-2/afternoon.md:3 +msgid "The exercises for this afternoon will focus on strings and iterators." +msgstr "" + +#: src/exercises/day-2/luhn.md:1 +msgid "# Luhn Algorithm" +msgstr "" + +#: src/exercises/day-2/luhn.md:3 +msgid "" +"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used to\n" +"validate credit card numbers. The algorithm takes a string as input and does the\n" +"following to validate the credit card number:" +msgstr "" + +#: src/exercises/day-2/luhn.md:7 +msgid "* Ignore all spaces. Reject number with less than two digits." +msgstr "" + +#: src/exercises/day-2/luhn.md:9 +msgid "" +"* Moving from right to left, double every second digit: for the number `1234`,\n" +" we double `3` and `1`." +msgstr "" + +#: src/exercises/day-2/luhn.md:12 +msgid "" +"* After doubling a digit, sum the digits. So doubling `7` becomes `14` which\n" +" becomes `5`." +msgstr "" + +#: src/exercises/day-2/luhn.md:15 +msgid "* Sum all the undoubled and doubled digits." +msgstr "" + +#: src/exercises/day-2/luhn.md:17 +msgid "* The credit card number is valid if the sum ends with `0`." +msgstr "" + +#: src/exercises/day-2/luhn.md:19 +msgid "" +"Copy the following code to and implement the\n" +"function:" +msgstr "" + +#: src/exercises/day-2/luhn.md:27 +msgid "" +"pub fn luhn(cc_number: &str) -> bool {\n" +" unimplemented!()\n" +"}" +msgstr "" + +#: src/exercises/day-2/luhn.md:31 +msgid "" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}" +msgstr "" + +#: src/exercises/day-2/luhn.md:36 src/exercises/day-2/solutions-afternoon.md:64 +msgid "" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}" +msgstr "" + +#: src/exercises/day-2/luhn.md:44 src/exercises/day-2/solutions-afternoon.md:72 +msgid "" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}" +msgstr "" + +#: src/exercises/day-2/luhn.md:49 src/exercises/day-2/solutions-afternoon.md:77 +msgid "" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}" +msgstr "" + +#: src/exercises/day-2/luhn.md:54 src/exercises/day-2/solutions-afternoon.md:82 +msgid "" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}" +msgstr "" + +#: src/exercises/day-2/luhn.md:61 +msgid "" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:1 +msgid "# Strings and Iterators" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:3 +msgid "" +"In this exercise, you are implementing a routing component of a web server. The\n" +"server is configured with a number of _path prefixes_ which are matched against\n" +"_request paths_. The path prefixes can contain a wildcard character which\n" +"matches a full segment. See the unit tests below." +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:8 +msgid "" +"Copy the following code to and make the tests\n" +"pass. Try avoiding allocating a `Vec` for your intermediate results:" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:16 +msgid "" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" unimplemented!()\n" +"}" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:20 +msgid "" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:26 src/exercises/day-2/solutions-afternoon.md:146 +msgid "" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" +"}" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:31 src/exercises/day-2/solutions-afternoon.md:151 +msgid "" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:46 +msgid "" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"```" +msgstr "" + +#: src/welcome-day-3.md:1 +msgid "# Welcome to Day 3" +msgstr "# Bienvenido al Día 3" + +#: src/welcome-day-3.md:3 +msgid "Today, we will cover some more advanced topics of Rust:" +msgstr "" + +#: src/welcome-day-3.md:5 +msgid "" +"* Traits: deriving traits, default methods, and important standard library\n" +" traits." +msgstr "" + +#: src/welcome-day-3.md:8 +msgid "" +"* Generics: generic data types, generic methods, monomorphization, and trait\n" +" objects." +msgstr "" + +#: src/welcome-day-3.md:11 +msgid "* Error handling: panics, `Result`, and the try operator `?`." +msgstr "" + +#: src/welcome-day-3.md:13 +msgid "* Testing: unit tests, documentation tests, and integration tests." +msgstr "" + +#: src/welcome-day-3.md:15 +msgid "" +"* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" +" functions." +msgstr "" + +#: src/traits.md:1 +msgid "# Traits" +msgstr "" + +#: src/traits.md:3 +msgid "Rust lets you abstract over types with traits. They're similar to interfaces:" +msgstr "" + +#: src/traits.md:5 +msgid "" +"```rust,editable\n" +"trait Greet {\n" +" fn say_hello(&self);\n" +"}" +msgstr "" + +#: src/traits.md:10 +msgid "" +"struct Dog {\n" +" name: String,\n" +"}" +msgstr "" + +#: src/traits.md:14 +msgid "struct Cat; // No name, cats won't respond to it anyway." +msgstr "" + +#: src/traits.md:16 +msgid "" +"impl Greet for Dog {\n" +" fn say_hello(&self) {\n" +" println!(\"Wuf, my name is {}!\", self.name);\n" +" }\n" +"}" +msgstr "" + +#: src/traits.md:22 +msgid "" +"impl Greet for Cat {\n" +" fn say_hello(&self) {\n" +" println!(\"Miau!\");\n" +" }\n" +"}" +msgstr "" + +#: src/traits.md:28 +msgid "" +"fn main() {\n" +" let pets: Vec> = vec![\n" +" Box::new(Dog { name: String::from(\"Fido\") }),\n" +" Box::new(Cat),\n" +" ];\n" +" for pet in pets {\n" +" pet.say_hello();\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/traits.md:41 +msgid "" +"* Traits may specify pre-implemented (default) methods and methods that users are required to " +"implement themselves. Methods with default implementations can rely on required methods.\n" +"* Types that implement a given trait may be of different sizes. This makes it impossible to have " +"things like `Vec` in the example above.\n" +"* `dyn Greet` is a way to tell the compiler about a dynamically sized type that implements " +"`Greet`.\n" +"* In the example, `pets` holds Fat Pointers to objects that implement `Greet`. The Fat Pointer " +"consists of two components, a pointer to the actual object and a pointer to the virtual method " +"table for the `Greet` implementation of that particular object." +msgstr "" + +#: src/traits.md:46 +msgid "" +"Compare these outputs in the above example:\n" +"```rust,ignore\n" +" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::());\n" +" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n" +" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n" +" println!(\"{}\", std::mem::size_of::>());\n" +"```" +msgstr "" + +#: src/traits/deriving-traits.md:1 +msgid "# Deriving Traits" +msgstr "" + +#: src/traits/deriving-traits.md:3 +msgid "You can let the compiler derive a number of traits:" +msgstr "" + +#: src/traits/deriving-traits.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Clone, PartialEq, Eq, Default)]\n" +"struct Player {\n" +" name: String,\n" +" strength: u8,\n" +" hit_points: u8,\n" +"}" +msgstr "" + +#: src/traits/deriving-traits.md:13 +msgid "" +"fn main() {\n" +" let p1 = Player::default();\n" +" let p2 = p1.clone();\n" +" println!(\"Is {:?}\\nequal to {:?}?\\nThe answer is {}!\", &p1, &p2,\n" +" if p1 == p2 { \"yes\" } else { \"no\" });\n" +"}\n" +"```" +msgstr "" + +#: src/traits/default-methods.md:1 +msgid "# Default Methods" +msgstr "" + +#: src/traits/default-methods.md:3 +msgid "Traits can implement behavior in terms of other trait methods:" +msgstr "" + +#: src/traits/default-methods.md:5 +msgid "" +"```rust,editable\n" +"trait Equals {\n" +" fn equal(&self, other: &Self) -> bool;\n" +" fn not_equal(&self, other: &Self) -> bool {\n" +" !self.equal(other)\n" +" }\n" +"}" +msgstr "" + +#: src/traits/default-methods.md:13 +msgid "" +"#[derive(Debug)]\n" +"struct Centimeter(i16);" +msgstr "" + +#: src/traits/default-methods.md:16 +msgid "" +"impl Equals for Centimeter {\n" +" fn equal(&self, other: &Centimeter) -> bool {\n" +" self.0 == other.0\n" +" }\n" +"}" +msgstr "" + +#: src/traits/default-methods.md:22 +msgid "" +"fn main() {\n" +" let a = Centimeter(10);\n" +" let b = Centimeter(20);\n" +" println!(\"{a:?} equals {b:?}: {}\", a.equal(&b));\n" +" println!(\"{a:?} not_equals {b:?}: {}\", a.not_equal(&b));\n" +"}\n" +"```" +msgstr "" + +#: src/traits/important-traits.md:1 +msgid "# Important Traits" +msgstr "" + +#: src/traits/important-traits.md:3 +msgid "We will now look at some of the most common traits of the Rust standard library:" +msgstr "" + +#: src/traits/important-traits.md:5 +msgid "" +"* [`Iterator`][1] and [`IntoIterator`][2] used in `for` loops,\n" +"* [`From`][3] and [`Into`][4] used to convert values,\n" +"* [`Read`][5] and [`Write`][6] used for IO,\n" +"* [`Add`][7], [`Mul`][8], ... used for operator overloading, and\n" +"* [`Drop`][9] used for defining destructors.\n" +"* [`Default`][10] used to construct a default instance of a type." +msgstr "" + +#: src/traits/important-traits.md:12 +msgid "" +"[1]: https://doc.rust-lang.org/std/iter/trait.Iterator.html\n" +"[2]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html\n" +"[3]: https://doc.rust-lang.org/std/convert/trait.From.html\n" +"[4]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" +"[5]: https://doc.rust-lang.org/std/io/trait.Read.html\n" +"[6]: https://doc.rust-lang.org/std/io/trait.Write.html\n" +"[7]: https://doc.rust-lang.org/std/ops/trait.Add.html\n" +"[8]: https://doc.rust-lang.org/std/ops/trait.Mul.html\n" +"[9]: https://doc.rust-lang.org/std/ops/trait.Drop.html\n" +"[10]: https://doc.rust-lang.org/std/default/trait.Default.html" +msgstr "" + +#: src/traits/iterator.md:1 +msgid "# Iterators" +msgstr "" + +#: src/traits/iterator.md:3 +msgid "You can implement the [`Iterator`][1] trait on your own types:" +msgstr "" + +#: src/traits/iterator.md:5 +msgid "" +"```rust,editable\n" +"struct Fibonacci {\n" +" curr: u32,\n" +" next: u32,\n" +"}" +msgstr "" + +#: src/traits/iterator.md:11 +msgid "" +"impl Iterator for Fibonacci {\n" +" type Item = u32;" +msgstr "" + +#: src/traits/iterator.md:14 +msgid "" +" fn next(&mut self) -> Option {\n" +" let new_next = self.curr + self.next;\n" +" self.curr = self.next;\n" +" self.next = new_next;\n" +" Some(self.curr)\n" +" }\n" +"}" +msgstr "" + +#: src/traits/iterator.md:22 +msgid "" +"fn main() {\n" +" let fib = Fibonacci { curr: 0, next: 1 };\n" +" for (i, n) in fib.enumerate().take(5) {\n" +" println!(\"fib({i}): {n}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/traits/iterator.md:32 +msgid "" +"* `IntoIterator` is the trait that makes for loops work. It is implemented by collection types " +"such as\n" +" `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also implement it.\n" +"* The `Iterator` trait implements many common functional programming operations over collections \n" +" (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can find all the " +"documentation\n" +" about them. In Rust these functions should produce the code as efficient as equivalent " +"imperative\n" +" implementations.\n" +" \n" +"" +msgstr "" + +#: src/traits/iterator.md:41 +msgid "[1]: https://doc.rust-lang.org/std/iter/trait.Iterator.html" +msgstr "" + +#: src/traits/from-iterator.md:1 +msgid "# FromIterator" +msgstr "" + +#: src/traits/from-iterator.md:3 +msgid "[`FromIterator`][1] lets you build a collection from an [`Iterator`][2]." +msgstr "" + +#: src/traits/from-iterator.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let primes = vec![2, 3, 5, 7];\n" +" let prime_squares = primes\n" +" .into_iter()\n" +" .map(|prime| prime * prime)\n" +" .collect::>();\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-iterator.md:17 +msgid "" +"`Iterator` implements\n" +"`fn collect(self) -> B\n" +"where\n" +" B: FromIterator,\n" +" Self: Sized`" +msgstr "" + +#: src/traits/from-iterator.md:23 +msgid "" +"There are also implementations which let you do cool things like convert an\n" +"`Iterator>` into a `Result, E>`." +msgstr "" + +#: src/traits/from-iterator.md:28 +msgid "" +"[1]: https://doc.rust-lang.org/std/iter/trait.FromIterator.html\n" +"[2]: https://doc.rust-lang.org/std/iter/trait.Iterator.html" +msgstr "" + +#: src/traits/from-into.md:1 +msgid "# `From` and `Into`" +msgstr "" + +#: src/traits/from-into.md:3 +msgid "Types implement [`From`][1] and [`Into`][2] to facilitate type conversions:" +msgstr "" + +#: src/traits/from-into.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s = String::from(\"hello\");\n" +" let addr = std::net::Ipv4Addr::from([127, 0, 0, 1]);\n" +" let one = i16::from(true);\n" +" let bigger = i32::from(123i16);\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-into.md:15 +msgid "[`Into`][2] is automatically implemented when [`From`][1] is implemented:" +msgstr "" + +#: src/traits/from-into.md:17 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s: String = \"hello\".into();\n" +" let addr: std::net::Ipv4Addr = [127, 0, 0, 1].into();\n" +" let one: i16 = true.into();\n" +" let bigger: i32 = 123i16.into();\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-into.md:27 +msgid "" +"
\n" +" \n" +"* That's why it is common to only implement `From`, as your type will get `Into` implementation " +"too.\n" +"* When declaring a function argument input type like \"anything that can be converted into a " +"`String`\", the rule is opposite, you should use `Into`.\n" +" Your function will accept types that implement `From` and those that _only_ implement `Into`.\n" +" \n" +"
" +msgstr "" + +#: src/traits/from-into.md:35 +msgid "" +"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" +"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html" +msgstr "" + +#: src/traits/read-write.md:1 +msgid "# `Read` and `Write`" +msgstr "" + +#: src/traits/read-write.md:3 +msgid "Using [`Read`][1] and [`BufRead`][2], you can abstract over `u8` sources:" +msgstr "" + +#: src/traits/read-write.md:5 +msgid "" +"```rust,editable\n" +"use std::io::{BufRead, BufReader, Read, Result};" +msgstr "" + +#: src/traits/read-write.md:8 +msgid "" +"fn count_lines(reader: R) -> usize {\n" +" let buf_reader = BufReader::new(reader);\n" +" buf_reader.lines().count()\n" +"}" +msgstr "" + +#: src/traits/read-write.md:13 +msgid "" +"fn main() -> Result<()> {\n" +" let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" +" println!(\"lines in slice: {}\", count_lines(slice));" +msgstr "" + +#: src/traits/read-write.md:17 +msgid "" +" let file = std::fs::File::open(std::env::current_exe()?)?;\n" +" println!(\"lines in file: {}\", count_lines(file));\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/read-write.md:23 +msgid "Similarly, [`Write`][3] lets you abstract over `u8` sinks:" +msgstr "" + +#: src/traits/read-write.md:25 +msgid "" +"```rust,editable\n" +"use std::io::{Result, Write};" +msgstr "" + +#: src/traits/read-write.md:28 +msgid "" +"fn log(writer: &mut W, msg: &str) -> Result<()> {\n" +" writer.write_all(msg.as_bytes())?;\n" +" writer.write_all(\"\\n\".as_bytes())\n" +"}" +msgstr "" + +#: src/traits/read-write.md:33 +msgid "" +"fn main() -> Result<()> {\n" +" let mut buffer = Vec::new();\n" +" log(&mut buffer, \"Hello\")?;\n" +" log(&mut buffer, \"World\")?;\n" +" println!(\"Logged: {:?}\", buffer);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/read-write.md:42 +msgid "" +"[1]: https://doc.rust-lang.org/std/io/trait.Read.html\n" +"[2]: https://doc.rust-lang.org/std/io/trait.BufRead.html\n" +"[3]: https://doc.rust-lang.org/std/io/trait.Write.html" +msgstr "" + +#: src/traits/operators.md:1 +msgid "# `Add`, `Mul`, ..." +msgstr "" + +#: src/traits/operators.md:3 +msgid "Operator overloading is implemented via traits in [`std::ops`][1]:" +msgstr "" + +#: src/traits/operators.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Copy, Clone)]\n" +"struct Point { x: i32, y: i32 }" +msgstr "" + +#: src/traits/operators.md:9 src/exercises/day-2/solutions-morning.md:46 +msgid "" +"impl std::ops::Add for Point {\n" +" type Output = Self;" +msgstr "" + +#: src/traits/operators.md:12 +msgid "" +" fn add(self, other: Self) -> Self {\n" +" Self {x: self.x + other.x, y: self.y + other.y}\n" +" }\n" +"}" +msgstr "" + +#: src/traits/operators.md:17 +msgid "" +"fn main() {\n" +" let p1 = Point { x: 10, y: 20 };\n" +" let p2 = Point { x: 100, y: 200 };\n" +" println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" +"}\n" +"```" +msgstr "" + +#: src/traits/operators.md:26 src/traits/drop.md:34 +msgid "Discussion points:" +msgstr "" + +#: src/traits/operators.md:28 +msgid "" +"* You could implement `Add` for `&Point`. In which situations is that useful? \n" +" * Answer: `Add:add` consumes `self`. If type `T` for which you are\n" +" 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" +" associated types (like `Output`) are controlled by the implementor of a\n" +" trait." +msgstr "" + +#: src/traits/operators.md:40 +msgid "[1]: https://doc.rust-lang.org/std/ops/index.html" +msgstr "" + +#: src/traits/drop.md:1 +msgid "# The `Drop` Trait" +msgstr "" + +#: src/traits/drop.md:3 +msgid "Values which implement [`Drop`][1] can specify code to run when they go out of scope:" +msgstr "" + +#: src/traits/drop.md:5 +msgid "" +"```rust,editable\n" +"struct Droppable {\n" +" name: &'static str,\n" +"}" +msgstr "" + +#: src/traits/drop.md:10 +msgid "" +"impl Drop for Droppable {\n" +" fn drop(&mut self) {\n" +" println!(\"Dropping {}\", self.name);\n" +" }\n" +"}" +msgstr "" + +#: src/traits/drop.md:16 +msgid "" +"fn main() {\n" +" let a = Droppable { name: \"a\" };\n" +" {\n" +" let b = Droppable { name: \"b\" };\n" +" {\n" +" let c = Droppable { name: \"c\" };\n" +" let d = Droppable { name: \"d\" };\n" +" println!(\"Exiting block B\");\n" +" }\n" +" println!(\"Exiting block A\");\n" +" }\n" +" drop(a);\n" +" println!(\"Exiting main\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/drop.md:36 +msgid "" +"* Why does not `Drop::drop` take `self`?\n" +" * Short-answer: If it did, `std::mem::drop` would be called at the end of\n" +" the block, resulting in another call to `Drop::drop`, and a stack\n" +" overflow!\n" +"* Try replacing `drop(a)` with `a.drop()`." +msgstr "" + +#: src/traits/drop.md:44 +msgid "[1]: https://doc.rust-lang.org/std/ops/trait.Drop.html" +msgstr "" + +#: src/traits/default.md:1 +msgid "# The `Default` Trait" +msgstr "" + +#: src/traits/default.md:3 +msgid "[`Default`][1] trait provides a default implementation of a trait." +msgstr "" + +#: src/traits/default.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Default)]\n" +"struct Derived {\n" +" x: u32,\n" +" y: String,\n" +" z: Implemented,\n" +"}" +msgstr "" + +#: src/traits/default.md:13 +msgid "" +"#[derive(Debug)]\n" +"struct Implemented(String);" +msgstr "" + +#: src/traits/default.md:16 +msgid "" +"impl Default for Implemented {\n" +" fn default() -> Self {\n" +" Self(\"John Smith\".into())\n" +" }\n" +"}" +msgstr "" + +#: src/traits/default.md:22 +msgid "" +"fn main() {\n" +" let default_struct: Derived = Default::default();\n" +" println!(\"{default_struct:#?}\");" +msgstr "" + +#: src/traits/default.md:26 +msgid "" +" let almost_default_struct = Derived {\n" +" y: \"Y is set!\".into(),\n" +" ..Default::default()\n" +" };\n" +" println!(\"{almost_default_struct:#?}\");" +msgstr "" + +#: src/traits/default.md:32 +msgid "" +" let nothing: Option = None;\n" +" println!(\"{:#?}\", nothing.unwrap_or_default());\n" +"}" +msgstr "" + +#: src/traits/default.md:40 +msgid "" +" * It can be implemented directly or it can be derived via `#[derive(Default)]`.\n" +" * Derived implementation will produce an instance where all fields are set to their default " +"values.\n" +" * This means all types in the struct must implement `Default` too.\n" +" * Standard Rust types often implement `Default` with reasonable values (e.g. `0`, `\"\"`, etc).\n" +" * The partial struct copy works nicely with default.\n" +" * Rust standard library is aware that types can implement `Default` and provides convenience " +"methods that use it." +msgstr "" + +#: src/traits/default.md:49 +msgid "[1]: https://doc.rust-lang.org/std/default/trait.Default.html" +msgstr "" + +#: src/generics.md:1 +msgid "# Generics" +msgstr "" + +#: src/generics.md:3 +msgid "" +"Rust support generics, which lets you abstract an algorithm (such as sorting)\n" +"over the types used in the algorithm." +msgstr "" + +#: src/generics/data-types.md:1 +msgid "# Generic Data Types" +msgstr "" + +#: src/generics/data-types.md:3 +msgid "You can use generics to abstract over the concrete field type:" +msgstr "" + +#: src/generics/data-types.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point {\n" +" x: T,\n" +" y: T,\n" +"}" +msgstr "" + +#: src/generics/data-types.md:12 +msgid "" +"fn main() {\n" +" let integer = Point { x: 5, y: 10 };\n" +" let float = Point { x: 1.0, y: 4.0 };\n" +" println!(\"{integer:?} and {float:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/methods.md:1 +msgid "# Generic Methods" +msgstr "" + +#: src/generics/methods.md:3 +msgid "You can declare a generic type on your `impl` block:" +msgstr "" + +#: src/generics/methods.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(T, T);" +msgstr "" + +#: src/generics/methods.md:9 +msgid "" +"impl Point {\n" +" fn x(&self) -> &T {\n" +" &self.0 // + 10\n" +" }" +msgstr "" + +#: src/generics/methods.md:14 +msgid "" +" // fn set_x(&mut self, x: T)\n" +"}" +msgstr "" + +#: src/generics/methods.md:17 +msgid "" +"fn main() {\n" +" let p = Point(5, 10);\n" +" println!(\"p.x = {}\", p.x());\n" +"}\n" +"```" +msgstr "" + +#: src/generics/methods.md:25 +msgid "" +"* *Q:* Why `T` is specified twice in `impl Point {}`? Isn't that redundant?\n" +" * This is because it is a generic implementation section for generic type. They are " +"independently generic.\n" +" * It means these methods are defined for any `T`.\n" +" * It is possible to write `impl Point { .. }`. \n" +" * `Point` is still generic and you can use `Point`, but methods in this block will only " +"be available for `Point`." +msgstr "" + +#: src/generics/trait-bounds.md:1 +msgid "# Trait Bounds" +msgstr "" + +#: src/generics/trait-bounds.md:3 +msgid "" +"When working with generics, you often want to require the types to implement\n" +"some trait, so that you can call this trait's methods." +msgstr "" + +#: src/generics/trait-bounds.md:6 +msgid "You can do this with `T: Trait` or `impl Trait`:" +msgstr "" + +#: src/generics/trait-bounds.md:8 +msgid "" +"```rust,editable\n" +"fn duplicate(a: T) -> (T, T) {\n" +" (a.clone(), a.clone())\n" +"}" +msgstr "" + +#: src/generics/trait-bounds.md:13 +msgid "" +"// Syntactic sugar for:\n" +"// fn add_42_millions>(x: T) -> i32 {\n" +"fn add_42_millions(x: impl Into) -> i32 {\n" +" x.into() + 42_000_000\n" +"}" +msgstr "" + +#: src/generics/trait-bounds.md:19 +msgid "// struct NotClonable;" +msgstr "" + +#: src/generics/trait-bounds.md:21 +msgid "" +"fn main() {\n" +" let foo = String::from(\"foo\");\n" +" let pair = duplicate(foo);\n" +" println!(\"{pair:?}\");" +msgstr "" + +#: src/generics/trait-bounds.md:26 +msgid "" +" let many = add_42_millions(42_i8);\n" +" println!(\"{many}\");\n" +" let many_more = add_42_millions(10_000_000);\n" +" println!(\"{many_more}\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-bounds.md:35 +msgid "" +"Show a `where` clause, students will encounter it when reading code.\n" +" \n" +"```rust,ignore\n" +"fn duplicate(a: T) -> (T, T)\n" +"where\n" +" T: Clone,\n" +"{\n" +" (a.clone(), a.clone())\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-bounds.md:46 +msgid "" +"* It declutters the function signature if you have many parameters.\n" +"* It has additional features making it more powerful.\n" +" * If someone asks, the extra feature is that the type on the left of \":\" can be arbitrary, " +"like `Option`.\n" +" \n" +"" +msgstr "" + +#: src/generics/impl-trait.md:1 +msgid "# `impl Trait`" +msgstr "" + +#: src/generics/impl-trait.md:3 +msgid "" +"Similar to trait bounds, an `impl Trait` syntax can be used in function\n" +"arguments and return values:" +msgstr "" + +#: src/generics/impl-trait.md:6 src/generics/trait-objects.md:5 src/generics/trait-objects.md:28 +msgid "" +"```rust,editable\n" +"use std::fmt::Display;" +msgstr "" + +#: src/generics/impl-trait.md:9 +msgid "" +"fn get_x(name: impl Display) -> impl Display {\n" +" format!(\"Hello {name}\")\n" +"}" +msgstr "" + +#: src/generics/impl-trait.md:13 +msgid "" +"fn main() {\n" +" let x = get_x(\"foo\");\n" +" println!(\"{x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/impl-trait.md:19 +msgid "" +"* `impl Trait` cannot be used with the `::<>` turbo fish syntax.\n" +"* `impl Trait` allows you to work with types which you cannot name." +msgstr "" + +#: src/generics/impl-trait.md:24 +msgid "The meaning of `impl Trait` is a bit different in the different positions." +msgstr "" + +#: src/generics/impl-trait.md:26 +msgid "" +"* For a parameter, `impl Trait` is like an anonymous generic parameter with a trait bound.\n" +"* For a return type, it means that the return type is some concrete type that implements the " +"trait,\n" +" without naming the type. This can be useful when you don't want to expose the concrete type in " +"a\n" +" public API." +msgstr "" + +#: src/generics/impl-trait.md:31 +msgid "" +"This example is great, because it uses `impl Display` twice. It helps to explain that\n" +"nothing here enforces that it is _the same_ `impl Display` type. If we used a single \n" +"`T: Display`, it would enforce the constraint that input `T` and return `T` type are the same " +"type.\n" +"It would not work for this particular function, as the type we expect as input is likely not\n" +"what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two\n" +"independent generic parameters.\n" +" \n" +"" +msgstr "" + +#: src/generics/closures.md:1 +msgid "# Closures" +msgstr "" + +#: src/generics/closures.md:3 +msgid "" +"Closures or lambda expressions have types which cannot be named. However, they\n" +"implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:" +msgstr "" + +#: src/generics/closures.md:8 +msgid "" +"```rust,editable\n" +"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" +" println!(\"Calling function on {input}\");\n" +" func(input)\n" +"}" +msgstr "" + +#: src/generics/closures.md:14 +msgid "" +"fn main() {\n" +" let add_3 = |x| x + 3;\n" +" let mul_5 = |x| x * 5;" +msgstr "" + +#: src/generics/closures.md:18 +msgid "" +" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" +" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" +"}\n" +"```" +msgstr "" + +#: src/generics/closures.md:25 +msgid "If you have an `FnOnce`, you may only call it once. It might consume captured values." +msgstr "" + +#: src/generics/closures.md:27 +msgid "" +"An `FnMut` might mutate captured values, so you can call it multiple times but not concurrently." +msgstr "" + +#: src/generics/closures.md:29 +msgid "" +"An `Fn` neither consumes nor mutates captured values, or perhaps captures nothing at all, so it " +"can\n" +"be called multiple times concurrently." +msgstr "" + +#: src/generics/closures.md:32 +msgid "" +"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. I.e. you can use an\n" +"`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever an `FnMut` or " +"`FnOnce`\n" +"is called for." +msgstr "" + +#: src/generics/closures.md:36 +msgid "`move` closures only implement `FnOnce`." +msgstr "" + +#: src/generics/monomorphization.md:1 +msgid "# Monomorphization" +msgstr "" + +#: src/generics/monomorphization.md:3 +msgid "Generic code is turned into non-generic code based on the call sites:" +msgstr "" + +#: src/generics/monomorphization.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let integer = Some(5);\n" +" let float = Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:12 +msgid "behaves as if you wrote" +msgstr "" + +#: src/generics/monomorphization.md:14 +msgid "" +"```rust,editable\n" +"enum Option_i32 {\n" +" Some(i32),\n" +" None,\n" +"}" +msgstr "" + +#: src/generics/monomorphization.md:20 +msgid "" +"enum Option_f64 {\n" +" Some(f64),\n" +" None,\n" +"}" +msgstr "" + +#: src/generics/monomorphization.md:25 +msgid "" +"fn main() {\n" +" let integer = Option_i32::Some(5);\n" +" let float = Option_f64::Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:31 +msgid "" +"This is a zero-cost abstraction: you get exactly the same result as if you had\n" +"hand-coded the data structures without the abstraction." +msgstr "" + +#: src/generics/trait-objects.md:1 +msgid "# Trait Objects" +msgstr "" + +#: src/generics/trait-objects.md:3 +msgid "We've seen how a function can take arguments which implement a trait:" +msgstr "" + +#: src/generics/trait-objects.md:8 +msgid "" +"fn print(x: T) {\n" +" println!(\"Your value: {x}\");\n" +"}" +msgstr "" + +#: src/generics/trait-objects.md:12 +msgid "" +"fn main() {\n" +" print(123);\n" +" print(\"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-objects.md:18 +msgid "However, how can we store a collection of mixed types which implement `Display`?" +msgstr "" + +#: src/generics/trait-objects.md:20 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let xs = vec![123, \"Hello\"];\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-objects.md:26 +msgid "For this, we need _trait objects_:" +msgstr "" + +#: src/generics/trait-objects.md:31 +msgid "" +"fn main() {\n" +" let xs: Vec> = vec![Box::new(123), Box::new(\"Hello\")];\n" +" for x in xs {\n" +" println!(\"x: {x}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/generics/trait-objects.md:39 +msgid "Memory layout after allocating `xs`:" +msgstr "" + +#: src/generics/trait-objects.md:41 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": xs : : :\n" +": +-----------+-------+ : : +-----+-----+ :\n" +": | ptr | o---+---+-----+-->| o o | o o | :\n" +": | len | 2 | : : +-|-|-+-|-|-+ :\n" +": | capacity | 2 | : : | | | | +----+----+----+----+----+ :\n" +": +-----------+-------+ : : | | | '-->| H | e | l | l | o | :\n" +": : : | | | +----+----+----+----+----+ :\n" +"`- - - - - - - - - - - - - -' : | | | :\n" +" : | | | +-------------------------+ :\n" +" : | | '---->| \"::fmt\" | :\n" +" : | | +-------------------------+ :\n" +" : | | :\n" +" : | | +----+----+----+----+ :\n" +" : | '-->| 7b | 00 | 00 | 00 | :\n" +" : | +----+----+----+----+ :\n" +" : | :\n" +" : | +-------------------------+ :\n" +" : '---->| \"::fmt\" | :\n" +" : +-------------------------+ :\n" +" : :\n" +" : :\n" +" '- - - - - - - - - - - - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/generics/trait-objects.md:69 +msgid "" +"Similarly, you need a trait object if you want to return different types\n" +"implementing a trait:" +msgstr "" + +#: src/generics/trait-objects.md:72 +msgid "" +"```rust,editable\n" +"fn numbers(n: i32) -> Box> {\n" +" if n > 0 {\n" +" Box::new(0..n)\n" +" } else {\n" +" Box::new((n..0).rev())\n" +" }\n" +"}" +msgstr "" + +#: src/generics/trait-objects.md:81 +msgid "" +"fn main() {\n" +" println!(\"{:?}\", numbers(-5).collect::>());\n" +" println!(\"{:?}\", numbers(5).collect::>());\n" +"}" +msgstr "" + +#: src/exercises/day-3/morning.md:1 +msgid "# Day 3: Morning Exercises" +msgstr "" + +#: src/exercises/day-3/morning.md:3 +msgid "We will design a classical GUI library traits and trait objects." +msgstr "" + +#: src/exercises/day-3/simple-gui.md:1 +msgid "# A Simple GUI Library" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:3 +msgid "" +"Let us design a classical GUI library using our new knowledge of traits and\n" +"trait objects." +msgstr "" + +#: src/exercises/day-3/simple-gui.md:6 +msgid "We will have a number of widgets in our library:" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:8 +msgid "" +"* `Window`: has a `title` and contains other widgets.\n" +"* `Button`: has a `label` and a callback function which is invoked when the\n" +" button is pressed.\n" +"* `Label`: has a `label`." +msgstr "" + +#: src/exercises/day-3/simple-gui.md:13 +msgid "The widgets will implement a `Widget` trait, see below." +msgstr "" + +#: src/exercises/day-3/simple-gui.md:15 +msgid "" +"Copy the code below to , fill in the missing\n" +"`draw_into` methods so that you implement the `Widget` trait:" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:18 src/exercises/day-3/safe-ffi-wrapper.md:25 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:22 +msgid "" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:26 src/exercises/day-3/solutions-morning.md:27 +msgid "" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:29 src/exercises/day-3/solutions-morning.md:30 +msgid "" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:37 src/exercises/day-3/solutions-morning.md:38 +msgid "" +"pub struct Label {\n" +" label: String,\n" +"}" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:41 src/exercises/day-3/solutions-morning.md:42 +msgid "" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:49 src/exercises/day-3/solutions-morning.md:50 +msgid "" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:54 src/exercises/day-3/solutions-morning.md:55 +msgid "" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:63 src/exercises/day-3/solutions-morning.md:64 +msgid "" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:68 src/exercises/day-3/solutions-morning.md:69 +msgid "" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:76 src/exercises/day-3/solutions-morning.md:77 +msgid "" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:82 +msgid "" +"impl Widget for Label {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:87 src/exercises/day-3/simple-gui.md:97 +#: src/exercises/day-3/simple-gui.md:107 +msgid "" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:92 +msgid "" +"impl Widget for Button {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:102 +msgid "" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:112 +msgid "" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:123 +msgid "The output of the above program can be something simple like this:" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:125 +msgid "" +"```text\n" +"========\n" +"Rust GUI Demo 1.23\n" +"========" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:130 +msgid "This is a small text GUI demo." +msgstr "" + +#: src/exercises/day-3/simple-gui.md:132 +msgid "" +"| Click me! |\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:135 +msgid "" +"If you want to draw aligned text, you can use the\n" +"[fill/alignment](https://doc.rust-lang.org/std/fmt/index.html#fillalignment)\n" +"formatting operators. In particular, notice how you can pad with different\n" +"characters (here a `'/'`) and how you can control alignment:" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:140 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let width = 10;\n" +" println!(\"left aligned: |{:/width$}|\", \"foo\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:149 +msgid "Using such alignment tricks, you can for example produce output like this:" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:151 +msgid "" +"```text\n" +"+--------------------------------+\n" +"| Rust GUI Demo 1.23 |\n" +"+================================+\n" +"| This is a small text GUI demo. |\n" +"| +-----------+ |\n" +"| | Click me! | |\n" +"| +-----------+ |\n" +"+--------------------------------+\n" +"```" +msgstr "" + +#: src/error-handling.md:1 +msgid "# Error Handling" +msgstr "" + +#: src/error-handling.md:3 +msgid "Error handling in Rust is done using explicit control flow:" +msgstr "" + +#: src/error-handling.md:5 +msgid "" +"* Functions that can have errors list this in their return type,\n" +"* There are no exceptions." +msgstr "" + +#: src/error-handling/panics.md:1 +msgid "# Panics" +msgstr "" + +#: src/error-handling/panics.md:3 +msgid "Rust will trigger a panic if a fatal error happens at runtime:" +msgstr "" + +#: src/error-handling/panics.md:5 +msgid "" +"```rust,editable,should_panic\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" println!(\"v[100]: {}\", v[100]);\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/panics.md:12 +msgid "" +"* Panics are for unrecoverable and unexpected errors.\n" +" * Panics are symptoms of bugs in the program.\n" +"* Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." +msgstr "" + +#: src/error-handling/panic-unwind.md:1 +msgid "# Catching the Stack Unwinding" +msgstr "" + +#: src/error-handling/panic-unwind.md:3 +msgid "By default, a panic will cause the stack to unwind. The unwinding can be caught:" +msgstr "" + +#: src/error-handling/panic-unwind.md:5 +msgid "" +"```rust\n" +"use std::panic;" +msgstr "" + +#: src/error-handling/panic-unwind.md:8 +msgid "" +"let result = panic::catch_unwind(|| {\n" +" println!(\"hello!\");\n" +"});\n" +"assert!(result.is_ok());" +msgstr "" + +#: src/error-handling/panic-unwind.md:13 +msgid "" +"let result = panic::catch_unwind(|| {\n" +" panic!(\"oh no!\");\n" +"});\n" +"assert!(result.is_err());\n" +"```" +msgstr "" + +#: src/error-handling/panic-unwind.md:19 +msgid "" +"* This can be useful in servers which should keep running even if a single\n" +" request crashes.\n" +"* This does not work if `panic = 'abort'` is set in your `Cargo.toml`." +msgstr "" + +#: src/error-handling/result.md:1 +msgid "# Structured Error Handling with `Result`" +msgstr "" + +#: src/error-handling/result.md:3 +msgid "" +"We have already seen the `Result` enum. This is used pervasively when errors are\n" +"expected as part of normal operation:" +msgstr "" + +#: src/error-handling/result.md:6 +msgid "" +"```rust\n" +"use std::fs::File;\n" +"use std::io::Read;" +msgstr "" + +#: src/error-handling/result.md:10 +msgid "" +"fn main() {\n" +" let file = File::open(\"diary.txt\");\n" +" match file {\n" +" Ok(mut file) => {\n" +" let mut contents = String::new();\n" +" file.read_to_string(&mut contents);\n" +" println!(\"Dear diary: {contents}\");\n" +" },\n" +" Err(err) => {\n" +" println!(\"The diary could not be opened: {err}\");\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/result.md:27 +msgid "" +" * As with `Option`, the successful value sits inside of `Result`, forcing the developer to\n" +" explicitly extract it. This encourages error checking. In the case where an error should never " +"happen,\n" +" `unwrap()` or `expect()` can be called, and this is a signal of the developer intent too. \n" +" * `Result` documentation is a recommended read. Not during the course, but it is worth " +"mentioning. \n" +" It contains a lot of convenience methods and functions that help functional-style " +"programming. \n" +" \n" +"" +msgstr "" + +#: src/error-handling/try-operator.md:1 +msgid "# Propagating Errors with `?`" +msgstr "" + +#: src/error-handling/try-operator.md:3 +msgid "" +"The try-operator `?` is used to return errors to the caller. It lets you turn\n" +"the common" +msgstr "" + +#: src/error-handling/try-operator.md:6 +msgid "" +"```rust,ignore\n" +"match some_expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(err),\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:13 +msgid "into the much simpler" +msgstr "" + +#: src/error-handling/try-operator.md:15 +msgid "" +"```rust,ignore\n" +"some_expression?\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:19 +msgid "We can use this to simplify our error handing code:" +msgstr "" + +#: src/error-handling/try-operator.md:21 +msgid "" +"```rust,editable\n" +"use std::fs;\n" +"use std::io::{self, Read};" +msgstr "" + +#: src/error-handling/try-operator.md:25 +msgid "" +"fn read_username(path: &str) -> Result {\n" +" let username_file_result = fs::File::open(path);" +msgstr "" + +#: src/error-handling/try-operator.md:28 +msgid "" +" let mut username_file = match username_file_result {\n" +" Ok(file) => file,\n" +" Err(e) => return Err(e),\n" +" };" +msgstr "" + +#: src/error-handling/try-operator.md:33 +msgid " let mut username = String::new();" +msgstr "" + +#: src/error-handling/try-operator.md:35 +msgid "" +" match username_file.read_to_string(&mut username) {\n" +" Ok(_) => Ok(username),\n" +" Err(e) => Err(e),\n" +" }\n" +"}" +msgstr "" + +#: src/error-handling/try-operator.md:41 +msgid "" +"fn main() {\n" +" //fs::write(\"config.dat\", \"alice\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:52 src/error-handling/converting-error-types-example.md:52 +msgid "" +"* The `username` variable can be either `Ok(string)` or `Err(error)`.\n" +"* Use the `fs::write` call to test out the different scenarios: no file, empty file, file with " +"username." +msgstr "" + +#: src/error-handling/converting-error-types.md:1 +#: src/error-handling/converting-error-types-example.md:1 +msgid "# Converting Error Types" +msgstr "" + +#: src/error-handling/converting-error-types.md:3 +msgid "The effective expansion of `?` is a little more complicated than previously indicated:" +msgstr "" + +#: src/error-handling/converting-error-types.md:5 +msgid "" +"```rust,ignore\n" +"expression?\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types.md:9 +msgid "works the same as" +msgstr "" + +#: src/error-handling/converting-error-types.md:11 +msgid "" +"```rust,ignore\n" +"match expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(From::from(err)),\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types.md:18 +msgid "" +"The `From::from` call here means we attempt to convert the error type to the\n" +"type returned by the function:" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:3 +msgid "" +"```rust,editable\n" +"use std::error::Error;\n" +"use std::fmt::{self, Display, Formatter};\n" +"use std::fs::{self, File};\n" +"use std::io::{self, Read};" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:9 +msgid "" +"#[derive(Debug)]\n" +"enum ReadUsernameError {\n" +" IoError(io::Error),\n" +" EmptyUsername(String),\n" +"}" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:15 +msgid "impl Error for ReadUsernameError {}" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:17 +msgid "" +"impl Display for ReadUsernameError {\n" +" fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" +" match self {\n" +" Self::IoError(e) => write!(f, \"IO error: {}\", e),\n" +" Self::EmptyUsername(filename) => write!(f, \"Found no username in {}\", filename),\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:26 +msgid "" +"impl From for ReadUsernameError {\n" +" fn from(err: io::Error) -> ReadUsernameError {\n" +" ReadUsernameError::IoError(err)\n" +" }\n" +"}" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:32 +msgid "" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:41 +msgid "" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:55 +msgid "" +"It is good practice for all error types to implement `std::error::Error`, which requires `Debug` " +"and\n" +"`Display`. It's generally helpful for them to implement `Clone` and `Eq` too where possible, to " +"make\n" +"life easier for tests and consumers of your library. In this case we can't easily do so, because\n" +"`io::Error` doesn't implement them." +msgstr "" + +#: src/error-handling/deriving-error-enums.md:1 +msgid "# Deriving Error Enums" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:3 +msgid "" +"The [thiserror](https://docs.rs/thiserror/) crate is a popular way to create an\n" +"error enum like we did on the previous page:" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use thiserror::Error;" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:11 +msgid "" +"#[derive(Debug, Error)]\n" +"enum ReadUsernameError {\n" +" #[error(\"Could not read: {0}\")]\n" +" IoError(#[from] io::Error),\n" +" #[error(\"Found no username in {0}\")]\n" +" EmptyUsername(String),\n" +"}" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:19 +msgid "" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:28 src/error-handling/dynamic-errors.md:25 +msgid "" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:39 +msgid "" +"`thiserror`'s derive macro automatically implements `std::error::Error`, and optionally `Display`\n" +"(if the `#[error(...)]` attributes are provided) and `From` (if the `#[from]` attribute is " +"added).\n" +"It also works for structs." +msgstr "" + +#: src/error-handling/deriving-error-enums.md:43 +msgid "It doesn't affect your public API, which makes it good for libraries." +msgstr "" + +#: src/error-handling/dynamic-errors.md:1 +msgid "# Dynamic Error Types" +msgstr "" + +#: src/error-handling/dynamic-errors.md:3 +msgid "" +"Sometimes we want to allow any type of error to be returned without writing our own enum covering\n" +"all the different possibilities. `std::error::Error` makes this easy." +msgstr "" + +#: src/error-handling/dynamic-errors.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use std::fs::{self, File};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"use std::error::Error;" +msgstr "" + +#: src/error-handling/dynamic-errors.md:12 +msgid "" +"#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" +"#[error(\"Found no username in {0}\")]\n" +"struct EmptyUsernameError(String);" +msgstr "" + +#: src/error-handling/dynamic-errors.md:16 +msgid "" +"fn read_username(path: &str) -> Result> {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(EmptyUsernameError(String::from(path)).into());\n" +" }\n" +" Ok(username)\n" +"}" +msgstr "" + +#: src/error-handling/dynamic-errors.md:36 +msgid "" +"This saves on code, but gives up the ability to cleanly handle different error cases differently " +"in\n" +"the program. As such it's generally not a good idea to use `Box` in the public API of " +"a\n" +"library, but it can be a good option in a program where you just want to display the error " +"message\n" +"somewhere." +msgstr "" + +#: src/error-handling/error-contexts.md:1 +msgid "# Adding Context to Errors" +msgstr "" + +#: src/error-handling/error-contexts.md:3 +msgid "" +"The widely used [anyhow](https://docs.rs/anyhow/) crate can help you add\n" +"contextual information to your errors and allows you to have fewer\n" +"custom error types:" +msgstr "" + +#: src/error-handling/error-contexts.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use anyhow::{Context, Result, bail};" +msgstr "" + +#: src/error-handling/error-contexts.md:12 +msgid "" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)\n" +" .context(format!(\"Failed to open {path}\"))?\n" +" .read_to_string(&mut username)\n" +" .context(\"Failed to read\")?;\n" +" if username.is_empty() {\n" +" bail!(\"Found no username in {path}\");\n" +" }\n" +" Ok(username)\n" +"}" +msgstr "" + +#: src/error-handling/error-contexts.md:24 +msgid "" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err:?}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/error-contexts.md:35 +msgid "" +"* `anyhow::Result` is a type alias for `Result`.\n" +"* `anyhow::Error` is essentially a wrapper around `Box`. As such it's again generally " +"not\n" +" a good choice for the public API of a library, but is widely used in applications.\n" +"* Actual error type inside of it can be extracted for examination if necessary.\n" +"* Functionality provided by `anyhow::Result` may be familiar to Go developers, as it provides\n" +" similar usage patterns and ergonomics to `(T, error)` from Go." +msgstr "" + +#: src/testing.md:1 +msgid "# Testing" +msgstr "" + +#: src/testing.md:3 +msgid "Rust and Cargo come with a simple unit test framework:" +msgstr "" + +#: src/testing.md:5 +msgid "* Unit tests are supported throughout your code." +msgstr "" + +#: src/testing.md:7 +msgid "* Integration tests are supported via the `tests/` directory." +msgstr "" + +#: src/testing/unit-tests.md:1 +msgid "# Unit Tests" +msgstr "" + +#: src/testing/unit-tests.md:3 +msgid "Mark unit tests with `#[test]`:" +msgstr "" + +#: src/testing/unit-tests.md:5 +msgid "" +"```rust,editable\n" +"fn first_word(text: &str) -> &str {\n" +" match text.find(' ') {\n" +" Some(idx) => &text[..idx],\n" +" None => &text,\n" +" }\n" +"}" +msgstr "" + +#: src/testing/unit-tests.md:13 +msgid "" +"#[test]\n" +"fn test_empty() {\n" +" assert_eq!(first_word(\"\"), \"\");\n" +"}" +msgstr "" + +#: src/testing/unit-tests.md:18 +msgid "" +"#[test]\n" +"fn test_single_word() {\n" +" assert_eq!(first_word(\"Hello\"), \"Hello\");\n" +"}" +msgstr "" + +#: src/testing/unit-tests.md:23 +msgid "" +"#[test]\n" +"fn test_multiple_words() {\n" +" assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/testing/unit-tests.md:29 +msgid "Use `cargo test` to find and run the unit tests." +msgstr "" + +#: src/testing/test-modules.md:1 +msgid "# Test Modules" +msgstr "" + +#: src/testing/test-modules.md:3 +msgid "" +"Unit tests are often put in a nested module (run tests on the\n" +"[Playground](https://play.rust-lang.org/)):" +msgstr "" + +#: src/testing/test-modules.md:6 +msgid "" +"```rust,editable\n" +"fn helper(a: &str, b: &str) -> String {\n" +" format!(\"{a} {b}\")\n" +"}" +msgstr "" + +#: src/testing/test-modules.md:11 +msgid "" +"pub fn main() {\n" +" println!(\"{}\", helper(\"Hello\", \"World\"));\n" +"}" +msgstr "" + +#: src/testing/test-modules.md:19 +msgid "" +" #[test]\n" +" fn test_helper() {\n" +" assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/testing/test-modules.md:26 +msgid "" +"* This lets you unit test private helpers.\n" +"* The `#[cfg(test)]` attribute is only active when you run `cargo test`." +msgstr "" + +#: src/testing/doc-tests.md:1 +msgid "# Documentation Tests" +msgstr "" + +#: src/testing/doc-tests.md:3 +msgid "Rust has built-in support for documentation tests:" +msgstr "" + +#: src/testing/doc-tests.md:5 +msgid "" +"```rust\n" +"/// Shortens a string to the given length.\n" +"///\n" +"/// ```\n" +"/// use playground::shorten_string;\n" +"/// assert_eq!(shorten_string(\"Hello World\", 5), \"Hello\");\n" +"/// assert_eq!(shorten_string(\"Hello World\", 20), \"Hello World\");\n" +"/// ```\n" +"pub fn shorten_string(s: &str, length: usize) -> &str {\n" +" &s[..std::cmp::min(length, s.len())]\n" +"}\n" +"```" +msgstr "" + +#: src/testing/doc-tests.md:18 +msgid "" +"* Code blocks in `///` comments are automatically seen as Rust code.\n" +"* The code will be compiled and executed as part of `cargo test`.\n" +"* Test the above code on the [Rust Playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." +msgstr "" + +#: src/testing/integration-tests.md:1 +msgid "# Integration Tests" +msgstr "" + +#: src/testing/integration-tests.md:3 +msgid "If you want to test your library as a client, use an integration test." +msgstr "" + +#: src/testing/integration-tests.md:5 +msgid "Create a `.rs` file under `tests/`:" +msgstr "" + +#: src/testing/integration-tests.md:7 +msgid "" +"```rust,ignore\n" +"use my_library::init;" +msgstr "" + +#: src/testing/integration-tests.md:10 +msgid "" +"#[test]\n" +"fn test_init() {\n" +" assert!(init().is_ok());\n" +"}\n" +"```" +msgstr "" + +#: src/testing/integration-tests.md:16 +msgid "These tests only have access to the public API of your crate." +msgstr "" + +#: src/unsafe.md:1 +msgid "# Unsafe Rust" +msgstr "" + +#: src/unsafe.md:3 +msgid "The Rust language has two parts:" +msgstr "" + +#: src/unsafe.md:5 +msgid "" +"* **Safe Rust:** memory safe, no undefined behavior possible.\n" +"* **Unsafe Rust:** can trigger undefined behavior if preconditions are violated." +msgstr "" + +#: src/unsafe.md:8 +msgid "" +"We will be seeing mostly safe Rust in this course, but it's important to know\n" +"what Unsafe Rust is." +msgstr "" + +#: src/unsafe.md:11 +msgid "" +"Unsafe code is usually small and isolated, and its correctness should be carefully\n" +"documented. It is usually wrapped in a safe abstraction layer." +msgstr "" + +#: src/unsafe.md:14 +msgid "Unsafe Rust gives you access to five new capabilities:" +msgstr "" + +#: src/unsafe.md:16 +msgid "" +"* Dereference raw pointers.\n" +"* Access or modify mutable static variables.\n" +"* Access `union` fields.\n" +"* Call `unsafe` functions, including `extern` functions.\n" +"* Implement `unsafe` traits." +msgstr "" + +#: src/unsafe.md:22 +msgid "" +"We will briefly cover unsafe capabilities next. For full details, please see\n" +"[Chapter 19.1 in the Rust Book](https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html)\n" +"and the [Rustonomicon](https://doc.rust-lang.org/nomicon/)." +msgstr "" + +#: src/unsafe.md:28 +msgid "" +"Unsafe Rust does not mean the code is incorrect. It means that developers have\n" +"turned off the compiler safety features and have to write correct code by\n" +"themselves. It means the compiler no longer enforces Rust's memory-safety rules." +msgstr "" + +#: src/unsafe/raw-pointers.md:1 +msgid "# Dereferencing Raw Pointers" +msgstr "" + +#: src/unsafe/raw-pointers.md:3 +msgid "Creating pointers is safe, but dereferencing them requires `unsafe`:" +msgstr "" + +#: src/unsafe/raw-pointers.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut num = 5;" +msgstr "" + +#: src/unsafe/raw-pointers.md:9 +msgid "" +" let r1 = &mut num as *mut i32;\n" +" let r2 = &num as *const i32;" +msgstr "" + +#: src/unsafe/raw-pointers.md:12 +msgid "" +" // 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" +" // references or concurrently through any other pointers.\n" +" unsafe {\n" +" println!(\"r1 is: {}\", *r1);\n" +" *r1 = 10;\n" +" println!(\"r2 is: {}\", *r2);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/raw-pointers.md:26 +msgid "" +"It is good practice (and required by the Android Rust style guide) to write a comment for each\n" +"`unsafe` block explaining how the code inside it satisfies the safety requirements of the unsafe\n" +"operations it is doing." +msgstr "" + +#: src/unsafe/raw-pointers.md:30 +msgid "" +"In the case of pointer dereferences, this means that the pointers must be\n" +"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), i.e.:" +msgstr "" + +#: src/unsafe/raw-pointers.md:33 +msgid "" +" * The pointer must be non-null.\n" +" * The pointer must be _dereferenceable_ (within the bounds of a single allocated object).\n" +" * The object must not have been deallocated.\n" +" * There must not be concurrent accesses to the same location.\n" +" * If the pointer was obtained by casting a reference, the underlying object must be live and no\n" +" reference may be used to access the memory." +msgstr "" + +#: src/unsafe/raw-pointers.md:40 +msgid "In most cases the pointer must also be properly aligned." +msgstr "" + +#: src/unsafe/mutable-static-variables.md:1 +msgid "# Mutable Static Variables" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:3 +msgid "It is safe to read an immutable static variable:" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:5 +msgid "" +"```rust,editable\n" +"static HELLO_WORLD: &str = \"Hello, world!\";" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:8 +msgid "" +"fn main() {\n" +" println!(\"HELLO_WORLD: {HELLO_WORLD}\");\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:13 +msgid "" +"However, since data races can occur, it is unsafe to read and write mutable\n" +"static variables:" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:16 +msgid "" +"```rust,editable\n" +"static mut COUNTER: u32 = 0;" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:19 +msgid "" +"fn add_to_counter(inc: u32) {\n" +" unsafe { COUNTER += inc; } // Potential data race!\n" +"}" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:23 +msgid "" +"fn main() {\n" +" add_to_counter(42);" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:26 +msgid "" +" unsafe { println!(\"COUNTER: {COUNTER}\"); } // Potential data race!\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:32 +msgid "" +"Using a mutable static is generally a bad idea, but there are some cases where it might make " +"sense\n" +"in low-level `no_std` code, such as implementing a heap allocator or working with some C APIs." +msgstr "" + +#: src/unsafe/unions.md:1 +msgid "# Unions" +msgstr "" + +#: src/unsafe/unions.md:3 +msgid "Unions are like enums, but you need to track the active field yourself:" +msgstr "" + +#: src/unsafe/unions.md:5 +msgid "" +"```rust,editable\n" +"#[repr(C)]\n" +"union MyUnion {\n" +" i: u8,\n" +" b: bool,\n" +"}" +msgstr "" + +#: src/unsafe/unions.md:12 +msgid "" +"fn main() {\n" +" let u = MyUnion { i: 42 };\n" +" println!(\"int: {}\", unsafe { u.i });\n" +" println!(\"bool: {}\", unsafe { u.b }); // Undefined behavior!\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/unions.md:21 +msgid "" +"Unions are very rarely needed in Rust as you can usually use an enum. They are occasionally " +"needed\n" +"for interacting with C library APIs." +msgstr "" + +#: src/unsafe/unions.md:24 +msgid "" +"If you just want to reinterpret bytes as a different type, you probably want\n" +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn.transmute.html) or a safe\n" +"wrapper such as the [`zerocopy`](https://crates.io/crates/zerocopy) crate." +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:1 +msgid "# Calling Unsafe Functions" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:3 +msgid "" +"A function or method can be marked `unsafe` if it has extra preconditions you\n" +"must uphold to avoid undefined behaviour:" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let emojis = \"🗻∈🌏\";" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:10 +msgid "" +" // Safe because the indices are in the correct order, within the bounds of\n" +" // the string slice, and lie on UTF-8 sequence boundaries.\n" +" unsafe {\n" +" println!(\"emoji: {}\", emojis.get_unchecked(0..4));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(4..7));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(7..11));\n" +" }" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:18 +msgid " println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..7) }));" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:20 +msgid "" +" // Not upholding the UTF-8 encoding requirement breaks memory safety!\n" +" // println!(\"emoji: {}\", unsafe { emojis.get_unchecked(0..3) });\n" +" // println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..3) }));\n" +"}" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:25 +msgid "" +"fn count_chars(s: &str) -> usize {\n" +" s.chars().map(|_| 1).sum()\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:1 +msgid "# Writing Unsafe Functions" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:3 +msgid "" +"You can mark your own functions as `unsafe` if they require particular conditions to avoid " +"undefined\n" +"behaviour." +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:6 +msgid "" +"```rust,editable\n" +"/// Swaps the values pointed to by the given pointers.\n" +"///\n" +"/// # Safety\n" +"///\n" +"/// The pointers must be valid and properly aligned.\n" +"unsafe fn swap(a: *mut u8, b: *mut u8) {\n" +" let temp = *a;\n" +" *a = *b;\n" +" *b = temp;\n" +"}" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:18 +msgid "" +"fn main() {\n" +" let mut a = 42;\n" +" let mut b = 66;" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:22 +msgid "" +" // Safe because ...\n" +" unsafe {\n" +" swap(&mut a, &mut b);\n" +" }" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:27 +msgid "" +" println!(\"a = {}, b = {}\", a, b);\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:33 +msgid "We wouldn't actually use pointers for this because it can be done safely with references." +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:35 +msgid "" +"Note that unsafe code is allowed within an unsafe function without an `unsafe` block. We can\n" +"prohibit this with `#[deny(unsafe_op_in_unsafe_fn)]`. Try adding it and see what happens." +msgstr "" + +#: src/unsafe/extern-functions.md:1 +msgid "# Calling External Code" +msgstr "" + +#: src/unsafe/extern-functions.md:3 +msgid "" +"Functions from other languages might violate the guarantees of Rust. Calling\n" +"them is thus unsafe:" +msgstr "" + +#: src/unsafe/extern-functions.md:6 +msgid "" +"```rust,editable\n" +"extern \"C\" {\n" +" fn abs(input: i32) -> i32;\n" +"}" +msgstr "" + +#: src/unsafe/extern-functions.md:11 +msgid "" +"fn main() {\n" +" unsafe {\n" +" // Undefined behavior if abs misbehaves.\n" +" println!(\"Absolute value of -3 according to C: {}\", abs(-3));\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/extern-functions.md:21 +msgid "" +"This is usually only a problem for extern functions which do things with pointers which might\n" +"violate Rust's memory model, but in general any C function might have undefined behaviour under " +"any\n" +"arbitrary circumstances." +msgstr "" + +#: src/unsafe/extern-functions.md:25 +msgid "" +"The `\"C\"` in this example is the ABI;\n" +"[other ABIs are available too](https://doc.rust-lang.org/reference/items/external-blocks.html)." +msgstr "" + +#: src/unsafe/unsafe-traits.md:1 +msgid "# Implementing Unsafe Traits" +msgstr "" + +#: src/unsafe/unsafe-traits.md:3 +msgid "" +"Like with functions, you can mark a trait as `unsafe` if the implementation must guarantee\n" +"particular conditions to avoid undefined behaviour." +msgstr "" + +#: src/unsafe/unsafe-traits.md:6 +msgid "" +"For example, the `zerocopy` crate has an unsafe trait that looks\n" +"[something like this](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" +msgstr "" + +#: src/unsafe/unsafe-traits.md:9 +msgid "" +"```rust,editable\n" +"use std::mem::size_of_val;\n" +"use std::slice;" +msgstr "" + +#: src/unsafe/unsafe-traits.md:13 +msgid "" +"/// ...\n" +"/// # Safety\n" +"/// The type must have a defined representation and no padding.\n" +"pub unsafe trait AsBytes {\n" +" fn as_bytes(&self) -> &[u8] {\n" +" unsafe {\n" +" slice::from_raw_parts(self as *const Self as *const u8, size_of_val(self))\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/unsafe/unsafe-traits.md:24 +msgid "" +"// Safe because u32 has a defined representation and no padding.\n" +"unsafe impl AsBytes for u32 {}\n" +"```" +msgstr "" + +#: src/unsafe/unsafe-traits.md:30 +msgid "" +"There should be a `# Safety` section on the Rustdoc for the trait explaining the requirements for\n" +"the trait to be safely implemented." +msgstr "" + +#: src/unsafe/unsafe-traits.md:33 +msgid "The actual safety section for `AsBytes` is rather longer and more complicated." +msgstr "" + +#: src/unsafe/unsafe-traits.md:35 +msgid "The built-in `Send` and `Sync` traits are unsafe." +msgstr "" + +#: src/exercises/day-3/afternoon.md:1 +msgid "# Day 3: Afternoon Exercises" +msgstr "" + +#: src/exercises/day-3/afternoon.md:3 +msgid "Let us build a safe wrapper for reading directory content!" +msgstr "" + +#: src/exercises/day-3/afternoon.md:7 +msgid "After looking at the exercise, you can look at the [solution] provided." +msgstr "" + +#: src/exercises/day-3/afternoon.md:9 +msgid "[solution]: solutions-afternoon.md" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:1 +msgid "# Safe FFI Wrapper" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:3 +msgid "" +"Rust has great support for calling functions through a _foreign function\n" +"interface_ (FFI). We will use this to build a safe wrapper for the `libc`\n" +"functions you would use from C to read the filenames of a directory." +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:7 +msgid "You will want to consult the manual pages:" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:9 +msgid "" +"* [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)\n" +"* [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)\n" +"* [`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:13 +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 "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:17 +msgid "" +"[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" +"[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" +"[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" +"[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:22 +msgid "" +"Copy the code below to and fill in the missing\n" +"functions and methods:" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:29 +msgid "" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:32 src/exercises/day-3/solutions-afternoon.md:26 +msgid "" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" +" }" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:39 src/exercises/day-3/solutions-afternoon.md:33 +msgid "" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:49 src/exercises/day-3/solutions-afternoon.md:43 +msgid "" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:56 src/exercises/day-3/solutions-afternoon.md:50 +msgid "" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:59 +msgid "" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:65 +msgid "" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" unimplemented!()\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:73 +msgid "" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" unimplemented!()\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:81 +msgid "" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" unimplemented!()\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:88 +msgid "" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/welcome-day-4.md:1 +msgid "# Welcome to Day 4" +msgstr "# Bienvenido al Día 4" + +#: src/welcome-day-4.md:3 +msgid "Today we will look at two main topics:" +msgstr "" + +#: src/welcome-day-4.md:5 +msgid "* Concurrency: threads, channels, shared state, `Send` and `Sync`." +msgstr "" + +#: src/welcome-day-4.md:7 +msgid "" +"* Android: building binaries and libraries, using AIDL, logging, and\n" +" interoperability with C, C++, and Java." +msgstr "" + +#: src/welcome-day-4.md:10 +msgid "" +"> We will attempt to call Rust from one of your own projects today. So try to\n" +"> find a little corner of your code base where we can move some lines of code to\n" +"> Rust. The fewer dependencies and \"exotic\" types the better. Something that\n" +"> parses some raw bytes would be ideal." +msgstr "" + +#: src/concurrency.md:1 +msgid "# Fearless Concurrency" +msgstr "" + +#: src/concurrency.md:3 +msgid "" +"Rust has full support for concurrency using OS threads with mutexes and\n" +"channels." +msgstr "" + +#: src/concurrency.md:6 +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 "" + +#: src/concurrency/threads.md:1 +msgid "# Threads" +msgstr "" + +#: src/concurrency/threads.md:3 +msgid "Rust threads work similarly to threads in other languages:" +msgstr "" + +#: src/concurrency/threads.md:5 +msgid "" +"```rust,editable\n" +"use std::thread;\n" +"use std::time::Duration;" +msgstr "" + +#: src/concurrency/threads.md:9 +msgid "" +"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" +" });" +msgstr "" + +#: src/concurrency/threads.md:17 +msgid "" +" 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 +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 "" + +#: src/concurrency/threads.md:32 +msgid "" +"* Notice that the thread is stopped before it reaches 10 — the main thread is\n" +" not waiting." +msgstr "" + +#: src/concurrency/threads.md:35 +msgid "" +"* Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for\n" +" the thread to finish." +msgstr "" + +#: src/concurrency/threads.md:38 +msgid "* Trigger a panic in the thread, notice how this doesn't affect `main`." +msgstr "" + +#: src/concurrency/threads.md:40 +msgid "" +"* 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/threads.md:43 +msgid "[`Any`]: https://doc.rust-lang.org/std/any/index.html" +msgstr "" + +#: src/concurrency/scoped-threads.md:1 +msgid "# Scoped Threads" +msgstr "" + +#: src/concurrency/scoped-threads.md:3 +msgid "Normal threads cannot borrow from their environment:" +msgstr "" + +#: src/concurrency/scoped-threads.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use std::thread;" +msgstr "" + +#: src/concurrency/scoped-threads.md:8 src/concurrency/scoped-threads.md:22 +msgid "" +"fn main() {\n" +" let s = String::from(\"Hello\");" +msgstr "" + +#: src/concurrency/scoped-threads.md:11 +msgid "" +" thread::spawn(|| {\n" +" println!(\"Length: {}\", s.len());\n" +" });\n" +"}\n" +"```" +msgstr "" + +#: src/concurrency/scoped-threads.md:17 +msgid "However, you can use a [scoped thread][1] for this:" +msgstr "" + +#: src/concurrency/scoped-threads.md:19 +msgid "" +"```rust,editable\n" +"use std::thread;" +msgstr "" + +#: src/concurrency/scoped-threads.md:25 +msgid "" +" thread::scope(|scope| {\n" +" scope.spawn(|| {\n" +" println!(\"Length: {}\", s.len());\n" +" });\n" +" });\n" +"}\n" +"```" +msgstr "" + +#: src/concurrency/scoped-threads.md:33 +msgid "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html" +msgstr "" + +#: src/concurrency/scoped-threads.md:35 +msgid "" +"
\n" +" \n" +"* 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" +" \n" +"
" +msgstr "" + +#: src/concurrency/channels.md:1 +msgid "# Channels" +msgstr "" + +#: src/concurrency/channels.md:3 +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 "" + +#: src/concurrency/channels.md:6 +msgid "" +"```rust,editable\n" +"use std::sync::mpsc;\n" +"use std::thread;" +msgstr "" + +#: src/concurrency/channels.md:10 src/concurrency/channels/unbounded.md:10 +msgid "" +"fn main() {\n" +" let (tx, rx) = mpsc::channel();" +msgstr "" + +#: src/concurrency/channels.md:13 +msgid "" +" tx.send(10).unwrap();\n" +" tx.send(20).unwrap();" +msgstr "" + +#: src/concurrency/channels.md:16 +msgid "" +" println!(\"Received: {:?}\", rx.recv());\n" +" println!(\"Received: {:?}\", rx.recv());" +msgstr "" + +#: src/concurrency/channels.md:19 +msgid "" +" let tx2 = tx.clone();\n" +" tx2.send(30).unwrap();\n" +" println!(\"Received: {:?}\", rx.recv());\n" +"}\n" +"```" +msgstr "" + +#: src/concurrency/channels.md:27 +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 "" + +#: src/concurrency/channels/unbounded.md:1 +msgid "# Unbounded Channels" +msgstr "" + +#: src/concurrency/channels/unbounded.md:3 +msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" +msgstr "" + +#: src/concurrency/channels/unbounded.md:5 src/concurrency/channels/bounded.md:5 +msgid "" +"```rust,editable\n" +"use std::sync::mpsc;\n" +"use std::thread;\n" +"use std::time::Duration;" +msgstr "" + +#: src/concurrency/channels/unbounded.md:13 src/concurrency/channels/bounded.md:13 +msgid "" +" 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));" +msgstr "" + +#: src/concurrency/channels/unbounded.md:23 +msgid "" +" for msg in rx.iter() {\n" +" println!(\"Main: got {}\", msg);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/concurrency/channels/bounded.md:1 +msgid "# Bounded Channels" +msgstr "" + +#: src/concurrency/channels/bounded.md:3 +msgid "Bounded and synchronous channels make `send` block the current thread:" +msgstr "" + +#: src/concurrency/channels/bounded.md:10 +msgid "" +"fn main() {\n" +" let (tx, rx) = mpsc::sync_channel(3);" +msgstr "" + +#: src/concurrency/channels/bounded.md:23 +msgid "" +" for msg in rx.iter() {\n" +" println!(\"Main: got {msg}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/concurrency/shared_state.md:1 +msgid "# Shared State" +msgstr "" + +#: src/concurrency/shared_state.md:3 +msgid "" +"Rust uses the type system to enforce synchronization of shared data. This is\n" +"primarily done via two types:" +msgstr "" + +#: src/concurrency/shared_state.md:6 +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 "" + +#: src/concurrency/shared_state.md:10 +msgid "" +"[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" +"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" +msgstr "" + +#: src/concurrency/shared_state/arc.md:1 +msgid "# `Arc`" +msgstr "" + +#: src/concurrency/shared_state/arc.md:3 +msgid "[`Arc`][1] allows shared read-only access via its `clone` method:" +msgstr "" + +#: src/concurrency/shared_state/arc.md:5 +msgid "" +"```rust,editable\n" +"use std::thread;\n" +"use std::sync::Arc;" +msgstr "" + +#: src/concurrency/shared_state/arc.md:9 +msgid "" +"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" +" }" +msgstr "" + +#: src/concurrency/shared_state/arc.md:20 +msgid "" +" handles.into_iter().for_each(|h| h.join().unwrap());\n" +" println!(\"v: {v:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/concurrency/shared_state/arc.md:25 +msgid "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" +msgstr "" + +#: src/concurrency/shared_state/arc.md:29 +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 "" + +#: src/concurrency/shared_state/mutex.md:1 +msgid "# `Mutex`" +msgstr "" + +#: src/concurrency/shared_state/mutex.md:3 +msgid "" +"[`Mutex`][1] ensures mutual exclusion _and_ allows mutable access to `T`\n" +"behind a read-only interface:" +msgstr "" + +#: src/concurrency/shared_state/mutex.md:6 +msgid "" +"```rust,editable\n" +"use std::sync::Mutex;" +msgstr "" + +#: src/concurrency/shared_state/mutex.md:9 +msgid "" +"fn main() {\n" +" let v = Mutex::new(vec![10, 20, 30]);\n" +" println!(\"v: {:?}\", v.lock().unwrap());" +msgstr "" + +#: src/concurrency/shared_state/mutex.md:13 +msgid "" +" {\n" +" let mut guard = v.lock().unwrap();\n" +" guard.push(40);\n" +" }" +msgstr "" + +#: src/concurrency/shared_state/mutex.md:18 +msgid "" +" println!(\"v: {:?}\", v.lock().unwrap());\n" +"}\n" +"```" +msgstr "" + +#: src/concurrency/shared_state/mutex.md:22 +msgid "" +"Notice how we have a [`impl Sync for Mutex`][2] blanket\n" +"implementation." +msgstr "" + +#: src/concurrency/shared_state/mutex.md:25 +msgid "" +"[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" +"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-Mutex%3CT%3E\n" +"[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" +msgstr "" + +#: src/concurrency/shared_state/mutex.md:29 +msgid "" +"
\n" +" \n" +"* `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 "" + +#: src/concurrency/shared_state/mutex.md:43 +msgid "" +"[`PoisonError`]: https://doc.rust-lang.org/std/sync/struct.PoisonError.html \n" +" \n" +"
" +msgstr "" + +#: src/concurrency/shared_state/example.md:3 +msgid "Let us see `Arc` and `Mutex` in action:" +msgstr "" + +#: src/concurrency/shared_state/example.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use std::thread;\n" +"// use std::sync::{Arc, Mutex};" +msgstr "" + +#: src/concurrency/shared_state/example.md:9 +msgid "" +"fn main() {\n" +" let mut v = vec![10, 20, 30];\n" +" let handle = thread::spawn(|| {\n" +" v.push(10);\n" +" });\n" +" v.push(1000);" +msgstr "" + +#: src/concurrency/shared_state/example.md:16 +msgid "" +" handle.join().unwrap();\n" +" println!(\"v: {v:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/concurrency/shared_state/example.md:23 +msgid "" +"Possible solution:\n" +" \n" +"```rust,editable\n" +"use std::sync::{Arc, Mutex};\n" +"use std::thread;" +msgstr "" + +#: src/concurrency/shared_state/example.md:29 +msgid "" +"fn main() {\n" +" let v = Arc::new(Mutex::new(vec![10, 20, 30]));" +msgstr "" + +#: src/concurrency/shared_state/example.md:32 +msgid "" +" let v2 = v.clone();\n" +" let handle = thread::spawn(move || {\n" +" let mut v2 = v2.lock().unwrap();\n" +" v2.push(10);\n" +" });" +msgstr "" + +#: src/concurrency/shared_state/example.md:38 +msgid "" +" {\n" +" let mut v = v.lock().unwrap();\n" +" v.push(1000);\n" +" }" +msgstr "" + +#: src/concurrency/shared_state/example.md:43 +msgid " handle.join().unwrap();" +msgstr "" + +#: src/concurrency/shared_state/example.md:45 +msgid "" +" {\n" +" let v = v.lock().unwrap();\n" +" println!(\"v: {v:?}\");\n" +" }\n" +"}\n" +"```\n" +" \n" +"Notable parts:" +msgstr "" + +#: src/concurrency/shared_state/example.md:54 +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.\n" +"* We still need to acquire the `Mutex` to print our `Vec`." +msgstr "" + +#: src/concurrency/send-sync.md:1 +msgid "# `Send` and `Sync`" +msgstr "" + +#: src/concurrency/send-sync.md:3 +msgid "How does Rust know to forbid shared access across thread? The answer is in two traits:" +msgstr "" + +#: src/concurrency/send-sync.md:5 +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 "" + +#: src/concurrency/send-sync.md:10 +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 "" + +#: src/concurrency/send-sync.md:14 +msgid "" +"[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" +"[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html\n" +"[3]: ../unsafe/unsafe-traits.md" +msgstr "" + +#: src/concurrency/send-sync.md:20 +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" +" \n" +"" +msgstr "" + +#: src/concurrency/send-sync/send.md:1 +msgid "# `Send`" +msgstr "" + +#: src/concurrency/send-sync/send.md:3 +msgid "> A type `T` is [`Send`][1] if it is safe to move a `T` value to another thread." +msgstr "" + +#: src/concurrency/send-sync/send.md:5 +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 "" + +#: src/concurrency/send-sync/send.md:9 +msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" +msgstr "" + +#: src/concurrency/send-sync/sync.md:1 +msgid "# `Sync`" +msgstr "" + +#: src/concurrency/send-sync/sync.md:3 +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 "" + +#: src/concurrency/send-sync/sync.md:6 +msgid "More precisely, the definition is:" +msgstr "" + +#: src/concurrency/send-sync/sync.md:8 +msgid "> `T` is `Sync` if and only if `&T` is `Send`" +msgstr "" + +#: src/concurrency/send-sync/sync.md:10 +msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Sync.html" +msgstr "" + +#: src/concurrency/send-sync/sync.md:14 +msgid "" +"This statement is essentially a shorthand way of saying that if a type is thread-safe for shared " +"use, it is also thread-safe to pass references of it across threads." +msgstr "" + +#: src/concurrency/send-sync/sync.md:16 +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 "" + +#: src/concurrency/send-sync/examples.md:1 +msgid "# Examples" +msgstr "" + +#: src/concurrency/send-sync/examples.md:3 +msgid "## `Send + Sync`" +msgstr "" + +#: src/concurrency/send-sync/examples.md:5 +msgid "Most types you come across are `Send + Sync`:" +msgstr "" + +#: 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 +msgid "" +"The generic types are typically `Send + Sync` when the type parameters are\n" +"`Send + Sync`." +msgstr "" + +#: src/concurrency/send-sync/examples.md:17 +msgid "## `Send + !Sync`" +msgstr "" + +#: src/concurrency/send-sync/examples.md:19 +msgid "" +"These types can be moved to other threads, but they're not thread-safe.\n" +"Typically because of interior mutability:" +msgstr "" + +#: src/concurrency/send-sync/examples.md:22 +msgid "" +"* `mpsc::Sender`\n" +"* `mpsc::Receiver`\n" +"* `Cell`\n" +"* `RefCell`" +msgstr "" + +#: src/concurrency/send-sync/examples.md:27 +msgid "## `!Send + Sync`" +msgstr "" + +#: src/concurrency/send-sync/examples.md:29 +msgid "These types are thread-safe, but they cannot be moved to another thread:" +msgstr "" + +#: src/concurrency/send-sync/examples.md:31 +msgid "" +"* `MutexGuard`: Uses OS level primitives which must be deallocated on the\n" +" thread which created them." +msgstr "" + +#: src/concurrency/send-sync/examples.md:34 +msgid "## `!Send + !Sync`" +msgstr "" + +#: src/concurrency/send-sync/examples.md:36 +msgid "These types are not thread-safe and cannot be moved to other threads:" +msgstr "" + +#: src/concurrency/send-sync/examples.md:38 +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 "" + +#: src/exercises/day-4/morning.md:1 src/exercises/day-4/afternoon.md:1 +msgid "# Exercises" +msgstr "" + +#: src/exercises/day-4/morning.md:3 +msgid "Let us practice our new concurrency skills with" +msgstr "" + +#: src/exercises/day-4/morning.md:5 +msgid "* Dining philosophers: a classic problem in concurrency." +msgstr "" + +#: src/exercises/day-4/morning.md:7 +msgid "" +"* Multi-threaded link checker: a larger project where you'll use Cargo to\n" +" download dependencies and then check links in parallel." +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:1 +msgid "# Dining Philosophers" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:3 +msgid "The dining philosophers problem is a classic problem in concurrency:" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:5 +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 "" + +#: src/exercises/day-4/dining-philosophers.md:13 +msgid "" +"You will need a local [Cargo installation](../../cargo/running-locally.md) for\n" +"this exercise. Copy the code below to `src/main.rs` file, fill out the blanks,\n" +"and test that `cargo run` does not deadlock:" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:17 +msgid "" +"```rust,compile_fail\n" +"use std::sync::mpsc;\n" +"use std::sync::{Arc, Mutex};\n" +"use std::thread;\n" +"use std::time::Duration;" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:23 src/exercises/day-4/solutions-morning.md:28 +msgid "struct Fork;" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:25 +msgid "" +"struct Philosopher {\n" +" name: String,\n" +" // left_fork: ...\n" +" // right_fork: ...\n" +" // thoughts: ...\n" +"}" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:32 +msgid "" +"impl Philosopher {\n" +" fn think(&self) {\n" +" self.thoughts\n" +" .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" +" .unwrap();\n" +" }" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:39 +msgid "" +" fn eat(&self) {\n" +" // Pick up forks...\n" +" println!(\"{} is eating...\", &self.name);\n" +" thread::sleep(Duration::from_millis(10));\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:46 src/exercises/day-4/solutions-morning.md:60 +msgid "" +"static PHILOSOPHERS: &[&str] =\n" +" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:49 +msgid "" +"fn main() {\n" +" // Create forks" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:52 +msgid " // Create philosophers" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:54 +msgid " // Make them think and eat" +msgstr "" + +#: src/exercises/day-4/dining-philosophers.md:56 +msgid "" +" // Output their thoughts\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-4/link-checker.md:1 +msgid "# Multi-threaded Link Checker" +msgstr "" + +#: src/exercises/day-4/link-checker.md:3 +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 "" + +#: src/exercises/day-4/link-checker.md:8 +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 "" + +#: 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 +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 "" + +#: src/exercises/day-4/link-checker.md:20 +msgid "You will also need a way to find links. We can use [`scraper`][2] for that:" +msgstr "" + +#: src/exercises/day-4/link-checker.md:22 +msgid "" +"```shell\n" +"$ cargo add scraper\n" +"```" +msgstr "" + +#: src/exercises/day-4/link-checker.md:26 +msgid "" +"Finally, we'll need some way of handling errors. We use [`thiserror`][3] for\n" +"that:" +msgstr "" + +#: src/exercises/day-4/link-checker.md:29 +msgid "" +"```shell\n" +"$ cargo add thiserror\n" +"```" +msgstr "" + +#: src/exercises/day-4/link-checker.md:33 +msgid "The `cargo add` calls will update the `Cargo.toml` file to look like this:" +msgstr "" + +#: src/exercises/day-4/link-checker.md:35 +msgid "" +"```toml\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:42 +msgid "" +"You can now download the start page. Try with a small site such as\n" +"`https://www.google.org/`." +msgstr "" + +#: src/exercises/day-4/link-checker.md:45 +msgid "Your `src/main.rs` file should look something like this:" +msgstr "" + +#: src/exercises/day-4/link-checker.md:47 +msgid "" +"```rust,compile_fail\n" +"use reqwest::blocking::{get, Response};\n" +"use reqwest::Url;\n" +"use scraper::{Html, Selector};\n" +"use thiserror::Error;" +msgstr "" + +#: src/exercises/day-4/link-checker.md:53 +msgid "" +"#[derive(Error, Debug)]\n" +"enum Error {\n" +" #[error(\"request error: {0}\")]\n" +" ReqwestError(#[from] reqwest::Error),\n" +"}" +msgstr "" + +#: src/exercises/day-4/link-checker.md:59 +msgid "" +"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();" +msgstr "" + +#: src/exercises/day-4/link-checker.md:65 +msgid "" +" 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" +" }" +msgstr "" + +#: src/exercises/day-4/link-checker.md:77 +msgid "" +" Ok(valid_urls)\n" +"}" +msgstr "" + +#: src/exercises/day-4/link-checker.md:80 +msgid "" +"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:90 +msgid "Run the code in `src/main.rs` with" +msgstr "" + +#: src/exercises/day-4/link-checker.md:92 +msgid "" +"```shell\n" +"$ cargo run\n" +"```" +msgstr "" + +#: src/exercises/day-4/link-checker.md:96 +msgid "## Tasks" +msgstr "" + +#: src/exercises/day-4/link-checker.md:98 +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 "" + +#: src/exercises/day-4/link-checker.md:104 +msgid "" +"[1]: https://docs.rs/reqwest/\n" +"[2]: https://docs.rs/scraper/\n" +"[3]: https://docs.rs/thiserror/" +msgstr "" + +#: src/android.md:1 +msgid "# Android" +msgstr "" + +#: src/android.md:3 +msgid "" +"Rust is supported for native platform development on Android. This means that\n" +"you can write new operating system services in Rust, as well as extending\n" +"existing services." +msgstr "" + +#: src/android/setup.md:1 +msgid "# Setup" +msgstr "" + +#: src/android/setup.md:3 +msgid "" +"We will be using an Android Virtual Device to test our code. Make sure you have\n" +"access to one or create a new one with:" +msgstr "" + +#: src/android/setup.md:6 +msgid "" +"```shell\n" +"$ source build/envsetup.sh\n" +"$ lunch aosp_cf_x86_64_phone-userdebug\n" +"$ acloud create\n" +"```" +msgstr "" + +#: src/android/setup.md:12 +msgid "" +"Please see the [Android Developer\n" +"Codelab](https://source.android.com/docs/setup/start) for details." +msgstr "" + +#: src/android/build-rules.md:1 +msgid "# Build Rules" +msgstr "" + +#: src/android/build-rules.md:3 +msgid "The Android build system (Soong) supports Rust via a number of modules:" +msgstr "" + +#: src/android/build-rules.md:5 +msgid "" +"| Module Type | " +"Description " +"|\n" +"|-------------------|----------------------------------------------------------------------------------------------------|\n" +"| `rust_binary` | Produces a Rust " +"binary. |\n" +"| `rust_library` | Produces a Rust library, and provides both `rlib` and `dylib` " +"variants. |\n" +"| `rust_ffi` | Produces a Rust C library usable by `cc` modules, and provides both static " +"and shared variants. |\n" +"| `rust_proc_macro` | Produces a `proc-macro` Rust library. These are analogous to compiler " +"plugins. |\n" +"| `rust_test` | Produces a Rust test binary that uses the standard Rust test " +"harness. |\n" +"| `rust_fuzz` | Produces a Rust fuzz binary leveraging " +"`libfuzzer`. |\n" +"| `rust_protobuf` | Generates source and produces a Rust library that provides an interface for " +"a particular protobuf. |\n" +"| `rust_bindgen` | Generates source and produces a Rust library containing Rust bindings to C " +"libraries. |" +msgstr "" + +#: src/android/build-rules.md:16 +msgid "We will look at `rust_binary` and `rust_library` next." +msgstr "" + +#: src/android/build-rules/binary.md:1 +msgid "# Rust Binaries" +msgstr "" + +#: src/android/build-rules/binary.md:3 +msgid "" +"Let us start with a simple application. At the root of an AOSP checkout, create\n" +"the following files:" +msgstr "" + +#: src/android/build-rules/binary.md:6 src/android/build-rules/library.md:13 +msgid "_hello_rust/Android.bp_:" +msgstr "" + +#: src/android/build-rules/binary.md:8 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust\",\n" +" crate_name: \"hello_rust\",\n" +" srcs: [\"src/main.rs\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md:16 src/android/build-rules/library.md:34 +msgid "_hello_rust/src/main.rs_:" +msgstr "" + +#: src/android/build-rules/binary.md:18 +msgid "" +"```rust\n" +"//! Rust demo." +msgstr "" + +#: src/android/build-rules/binary.md:21 +msgid "" +"/// Prints a greeting to standard output.\n" +"fn main() {\n" +" println!(\"Hello from Rust!\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md:27 +msgid "You can now build, push, and run the binary:" +msgstr "" + +#: src/android/build-rules/binary.md:29 +msgid "" +"```shell\n" +"$ m hello_rust\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust\n" +"Hello from Rust!\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:1 +msgid "# Rust Libraries" +msgstr "" + +#: src/android/build-rules/library.md:3 +msgid "You use `rust_library` to create a new Rust library for Android." +msgstr "" + +#: src/android/build-rules/library.md:5 +msgid "Here we declare a dependency on two libraries:" +msgstr "" + +#: src/android/build-rules/library.md:7 +msgid "" +"* `libgreeting`, which we define below,\n" +"* `libtextwrap`, which is a crate already vendored in\n" +" [`external/rust/crates/`][crates]." +msgstr "" + +#: src/android/build-rules/library.md:11 +msgid "[crates]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/" +msgstr "" + +#: src/android/build-rules/library.md:15 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_with_dep\",\n" +" crate_name: \"hello_rust_with_dep\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libgreetings\",\n" +" \"libtextwrap\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}" +msgstr "" + +#: src/android/build-rules/library.md:27 +msgid "" +"rust_library {\n" +" name: \"libgreetings\",\n" +" crate_name: \"greetings\",\n" +" srcs: [\"src/lib.rs\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:36 +msgid "" +"```rust,ignore\n" +"//! Rust demo." +msgstr "" + +#: src/android/build-rules/library.md:39 +msgid "" +"use greetings::greeting;\n" +"use textwrap::fill;" +msgstr "" + +#: src/android/build-rules/library.md:42 +msgid "" +"/// Prints a greeting to standard output.\n" +"fn main() {\n" +" println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:48 +msgid "_hello_rust/src/lib.rs_:" +msgstr "" + +#: src/android/build-rules/library.md:50 +msgid "" +"```rust,ignore\n" +"//! Greeting library." +msgstr "" + +#: src/android/build-rules/library.md:53 +msgid "" +"/// Greet `name`.\n" +"pub fn greeting(name: &str) -> String {\n" +" format!(\"Hello {name}, it is very nice to meet you!\")\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:59 +msgid "You build, push, and run the binary like before:" +msgstr "" + +#: src/android/build-rules/library.md:61 +msgid "" +"```shell\n" +"$ m hello_rust_with_dep\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust_with_dep\n" +"Hello Bob, it is very\n" +"nice to meet you!\n" +"```" +msgstr "" + +#: src/android/aidl.md:1 +msgid "# AIDL" +msgstr "" + +#: src/android/aidl.md:3 +msgid "" +"The [Android Interface Definition Language\n" +"(AIDL)](https://developer.android.com/guide/components/aidl) is supported in Rust:" +msgstr "" + +#: src/android/aidl.md:6 +msgid "" +"* Rust code can call existing AIDL servers,\n" +"* You can create new AIDL servers in Rust." +msgstr "" + +#: src/android/aidl/interface.md:1 +msgid "# AIDL Interfaces" +msgstr "" + +#: src/android/aidl/interface.md:3 +msgid "You declare the API of your service using an AIDL interface:" +msgstr "" + +#: src/android/aidl/interface.md:5 +msgid "*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" +msgstr "" + +#: src/android/aidl/interface.md:7 src/android/aidl/changing.md:6 +msgid "" +"```java\n" +"package com.example.birthdayservice;" +msgstr "" + +#: src/android/aidl/interface.md:10 +msgid "" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years);\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/interface.md:17 +msgid "*birthday_service/aidl/Android.bp*:" +msgstr "" + +#: src/android/aidl/interface.md:19 +msgid "" +"```javascript\n" +"aidl_interface {\n" +" name: \"com.example.birthdayservice\",\n" +" srcs: [\"com/example/birthdayservice/*.aidl\"],\n" +" unstable: true,\n" +" backend: {\n" +" rust: { // Rust is not enabled by default\n" +" enabled: true,\n" +" },\n" +" },\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/interface.md:32 +msgid "" +"Add `vendor_available: true` if your AIDL file is used by a binary in the vendor\n" +"partition." +msgstr "" + +#: src/android/aidl/implementation.md:1 +msgid "# Service Implementation" +msgstr "" + +#: src/android/aidl/implementation.md:3 +msgid "We can now implement the AIDL service:" +msgstr "" + +#: src/android/aidl/implementation.md:5 +msgid "*birthday_service/src/lib.rs*:" +msgstr "" + +#: src/android/aidl/implementation.md:7 +msgid "" +"```rust,ignore\n" +"//! Implementation of the `IBirthdayService` AIDL interface.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::" +"IBirthdayService;\n" +"use com_example_birthdayservice::binder;" +msgstr "" + +#: src/android/aidl/implementation.md:12 +msgid "" +"/// The `IBirthdayService` implementation.\n" +"pub struct BirthdayService;" +msgstr "" + +#: src/android/aidl/implementation.md:15 +msgid "impl binder::Interface for BirthdayService {}" +msgstr "" + +#: src/android/aidl/implementation.md:17 +msgid "" +"impl IBirthdayService for BirthdayService {\n" +" fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result {\n" +" Ok(format!(\n" +" \"Happy Birthday {name}, congratulations with the {years} years!\"\n" +" ))\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/implementation.md:26 src/android/aidl/server.md:28 src/android/aidl/client.md:37 +msgid "*birthday_service/Android.bp*:" +msgstr "" + +#: src/android/aidl/implementation.md:28 +msgid "" +"```javascript\n" +"rust_library {\n" +" name: \"libbirthdayservice\",\n" +" srcs: [\"src/lib.rs\"],\n" +" crate_name: \"birthdayservice\",\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/server.md:1 +msgid "# AIDL Server" +msgstr "" + +#: src/android/aidl/server.md:3 +msgid "Finally, we can create a server which exposes the service:" +msgstr "" + +#: src/android/aidl/server.md:5 +msgid "*birthday_service/src/server.rs*:" +msgstr "" + +#: src/android/aidl/server.md:7 +msgid "" +"```rust,ignore\n" +"//! Birthday service.\n" +"use birthdayservice::BirthdayService;\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::" +"BnBirthdayService;\n" +"use com_example_birthdayservice::binder;" +msgstr "" + +#: src/android/aidl/server.md:13 src/android/aidl/client.md:12 +msgid "const SERVICE_IDENTIFIER: &str = \"birthdayservice\";" +msgstr "" + +#: src/android/aidl/server.md:15 +msgid "" +"/// Entry point for birthday service.\n" +"fn main() {\n" +" let birthday_service = BirthdayService;\n" +" let birthday_service_binder = BnBirthdayService::new_binder(\n" +" birthday_service,\n" +" binder::BinderFeatures::default(),\n" +" );\n" +" binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder.as_binder())\n" +" .expect(\"Failed to register service\");\n" +" binder::ProcessState::join_thread_pool()\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/server.md:30 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_server\",\n" +" crate_name: \"birthday_server\",\n" +" srcs: [\"src/server.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" \"libbirthdayservice\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:1 +msgid "# Deploy" +msgstr "" + +#: src/android/aidl/deploy.md:3 +msgid "We can now build, push, and start the service:" +msgstr "" + +#: src/android/aidl/deploy.md:5 +msgid "" +"```shell\n" +"$ m birthday_server\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_server\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:11 +msgid "In another terminal, check that the service runs:" +msgstr "" + +#: src/android/aidl/deploy.md:13 +msgid "" +"```shell\n" +"$ adb shell service check birthdayservice\n" +"Service birthdayservice: found\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:18 +msgid "You can also call the service with `service call`:" +msgstr "" + +#: src/android/aidl/deploy.md:20 +msgid "" +"```shell\n" +"$ $ adb shell service call birthdayservice 1 s16 Bob i32 24\n" +"Result: Parcel(\n" +" 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" +" 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" +" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'\n" +" 0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'\n" +" 0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'\n" +" 0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'\n" +" 0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'\n" +" 0x00000070: 00210073 00000000 's.!..... ')\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:1 +msgid "# AIDL Client" +msgstr "" + +#: src/android/aidl/client.md:3 +msgid "Finally, we can create a Rust client for our new service." +msgstr "" + +#: src/android/aidl/client.md:5 +msgid "*birthday_service/src/client.rs*:" +msgstr "" + +#: src/android/aidl/client.md:7 +msgid "" +"```rust,ignore\n" +"//! Birthday service.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::" +"IBirthdayService;\n" +"use com_example_birthdayservice::binder;" +msgstr "" + +#: src/android/aidl/client.md:14 +msgid "" +"/// Connect to the BirthdayService.\n" +"pub fn connect() -> Result, binder::StatusCode> {\n" +" binder::get_interface(SERVICE_IDENTIFIER)\n" +"}" +msgstr "" + +#: src/android/aidl/client.md:19 +msgid "" +"/// Call the birthday service.\n" +"fn main() -> Result<(), binder::Status> {\n" +" let name = std::env::args()\n" +" .nth(1)\n" +" .unwrap_or_else(|| String::from(\"Bob\"));\n" +" let years = std::env::args()\n" +" .nth(2)\n" +" .and_then(|arg| arg.parse::().ok())\n" +" .unwrap_or(42);" +msgstr "" + +#: src/android/aidl/client.md:29 +msgid "" +" binder::ProcessState::start_thread_pool();\n" +" let service = connect().expect(\"Failed to connect to BirthdayService\");\n" +" let msg = service.wishHappyBirthday(&name, years)?;\n" +" println!(\"{msg}\");\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:39 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_client\",\n" +" crate_name: \"birthday_client\",\n" +" srcs: [\"src/client.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:52 +msgid "Notice that the client does not depend on `libbirthdayservice`." +msgstr "" + +#: src/android/aidl/client.md:54 +msgid "Build, push, and run the client on your device:" +msgstr "" + +#: src/android/aidl/client.md:56 +msgid "" +"```shell\n" +"$ m birthday_client\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_client Charlie 60\n" +"Happy Birthday Charlie, congratulations with the 60 years!\n" +"```" +msgstr "" + +#: src/android/aidl/changing.md:1 +msgid "# Changing API" +msgstr "" + +#: src/android/aidl/changing.md:3 +msgid "" +"Let us extend the API with more functionality: we want to let clients specify a\n" +"list of lines for the birthday card:" +msgstr "" + +#: src/android/aidl/changing.md:9 +msgid "" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years, in String[] text);\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:1 +msgid "# Logging" +msgstr "" + +#: src/android/logging.md:3 +msgid "" +"You should use the `log` crate to automatically log to `logcat` (on-device) or\n" +"`stdout` (on-host):" +msgstr "" + +#: src/android/logging.md:6 +msgid "_hello_rust_logs/Android.bp_:" +msgstr "" + +#: src/android/logging.md:8 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_logs\",\n" +" crate_name: \"hello_rust_logs\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"liblog_rust\",\n" +" \"liblogger\",\n" +" ],\n" +" prefer_rlib: true,\n" +" host_supported: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:22 +msgid "_hello_rust_logs/src/main.rs_:" +msgstr "" + +#: src/android/logging.md:24 +msgid "" +"```rust,ignore\n" +"//! Rust logging demo." +msgstr "" + +#: src/android/logging.md:27 +msgid "use log::{debug, error, info};" +msgstr "" + +#: src/android/logging.md:29 +msgid "" +"/// Logs a greeting.\n" +"fn main() {\n" +" logger::init(\n" +" logger::Config::default()\n" +" .with_tag_on_device(\"rust\")\n" +" .with_min_level(log::Level::Trace),\n" +" );\n" +" debug!(\"Starting program.\");\n" +" info!(\"Things are going fine.\");\n" +" error!(\"Something went wrong!\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:42 src/android/interoperability/with-c/bindgen.md:98 +#: src/android/interoperability/with-c/rust.md:73 +msgid "Build, push, and run the binary on your device:" +msgstr "" + +#: src/android/logging.md:44 +msgid "" +"```shell\n" +"$ m hello_rust_logs\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust_logs\n" +"```" +msgstr "" + +#: src/android/logging.md:50 +msgid "The logs show up in `adb logcat`:" +msgstr "" + +#: src/android/logging.md:52 +msgid "" +"```shell\n" +"$ adb logcat -s rust\n" +"09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.\n" +"09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going fine.\n" +"09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went wrong!\n" +"```" +msgstr "" + +#: src/android/interoperability.md:1 +msgid "# Interoperability" +msgstr "" + +#: src/android/interoperability.md:3 +msgid "" +"Rust has excellent support for interoperability with other languages. This means\n" +"that you can:" +msgstr "" + +#: src/android/interoperability.md:6 +msgid "" +"* Call Rust functions from other languages.\n" +"* Call functions written in other languages from Rust." +msgstr "" + +#: src/android/interoperability.md:9 +msgid "" +"When you call functions in a foreign language we say that you're using a\n" +"_foreign function interface_, also known as FFI." +msgstr "" + +#: src/android/interoperability/with-c.md:1 +msgid "# Interoperability with C" +msgstr "" + +#: src/android/interoperability/with-c.md:3 +msgid "" +"Rust has full support for linking object files with a C calling convention.\n" +"Similarly, you can export Rust functions and call them from C." +msgstr "" + +#: src/android/interoperability/with-c.md:6 +msgid "You can do it by hand if you want:" +msgstr "" + +#: src/android/interoperability/with-c.md:8 +msgid "" +"```rust\n" +"extern \"C\" {\n" +" fn abs(x: i32) -> i32;\n" +"}" +msgstr "" + +#: src/android/interoperability/with-c.md:13 +msgid "" +"fn main() {\n" +" let x = -42;\n" +" let abs_x = unsafe { abs(x) };\n" +" println!(\"{x}, {abs_x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c.md:20 +msgid "" +"We already saw this in the [Safe FFI Wrapper\n" +"exercise](../../exercises/day-3/safe-ffi-wrapper.md)." +msgstr "" + +#: src/android/interoperability/with-c.md:23 +msgid "" +"> This assumes full knowledge of the target platform. Not recommended for\n" +"> production." +msgstr "" + +#: src/android/interoperability/with-c.md:26 +msgid "We will look at better options next." +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:1 +msgid "# Using Bindgen" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:3 +msgid "" +"The [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html) tool\n" +"can auto-generate bindings from a C header file." +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:6 +msgid "First create a small C library:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:8 +msgid "_interoperability/bindgen/libbirthday.h_:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:10 +msgid "" +"```c\n" +"typedef struct card {\n" +" const char* name;\n" +" int years;\n" +"} card;" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:16 +msgid "" +"void print_card(const card* card);\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:19 +msgid "_interoperability/bindgen/libbirthday.c_:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:21 +msgid "" +"```c\n" +"#include \n" +"#include \"libbirthday.h\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:25 +msgid "" +"void print_card(const card* card) {\n" +" printf(\"+--------------\\n\");\n" +" printf(\"| Happy Birthday %s!\\n\", card->name);\n" +" printf(\"| Congratulations with the %i years!\\n\", card->years);\n" +" printf(\"+--------------\\n\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:33 +msgid "Add this to your `Android.bp` file:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:35 +#: src/android/interoperability/with-c/bindgen.md:55 +#: src/android/interoperability/with-c/bindgen.md:69 +#: src/android/interoperability/with-c/bindgen.md:108 +msgid "_interoperability/bindgen/Android.bp_:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:37 +msgid "" +"```javascript\n" +"cc_library {\n" +" name: \"libbirthday\",\n" +" srcs: [\"libbirthday.c\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:44 +msgid "" +"Create a wrapper header file for the library (not strictly needed in this\n" +"example):" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:47 +msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:49 +msgid "" +"```c\n" +"#include \"libbirthday.h\"\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:53 +msgid "You can now auto-generate the bindings:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:57 +msgid "" +"```javascript\n" +"rust_bindgen {\n" +" name: \"libbirthday_bindgen\",\n" +" crate_name: \"birthday_bindgen\",\n" +" wrapper_src: \"libbirthday_wrapper.h\",\n" +" source_stem: \"bindings\",\n" +" static_libs: [\"libbirthday\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:67 +msgid "Finally, we can use the bindings in our Rust program:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:71 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"print_birthday_card\",\n" +" srcs: [\"main.rs\"],\n" +" rustlibs: [\"libbirthday_bindgen\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:79 +msgid "_interoperability/bindgen/main.rs_:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:81 +msgid "" +"```rust,compile_fail\n" +"//! Bindgen demo." +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:84 +msgid "use birthday_bindgen::{card, print_card};" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:86 +msgid "" +"fn main() {\n" +" let name = std::ffi::CString::new(\"Peter\").unwrap();\n" +" let card = card {\n" +" name: name.as_ptr(),\n" +" years: 42,\n" +" };\n" +" unsafe {\n" +" print_card(&card as *const card);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:100 +msgid "" +"```shell\n" +"$ m print_birthday_card\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/tmp\n" +"$ adb shell /data/local/tmp/print_birthday_card\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:106 +msgid "Finally, we can run auto-generated tests to ensure the bindings work:" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:110 +msgid "" +"```javascript\n" +"rust_test {\n" +" name: \"libbirthday_bindgen_test\",\n" +" srcs: [\":libbirthday_bindgen\"],\n" +" crate_name: \"libbirthday_bindgen_test\",\n" +" test_suites: [\"general-tests\"],\n" +" auto_gen_config: true,\n" +" clippy_lints: \"none\", // Generated file, skip linting\n" +" lints: \"none\",\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:122 +msgid "" +"```shell\n" +"$ atest libbirthday_bindgen_test\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:1 +msgid "# Calling Rust" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:3 +msgid "Exporting Rust functions and types to C is easy:" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:5 +msgid "_interoperability/rust/libanalyze/analyze.rs_" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:7 +msgid "" +"```rust,editable\n" +"//! Rust FFI demo.\n" +"#![deny(improper_ctypes_definitions)]" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:11 +msgid "use std::os::raw::c_int;" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:13 +msgid "" +"/// Analyze the numbers.\n" +"#[no_mangle]\n" +"pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" +" if x < y {\n" +" println!(\"x ({x}) is smallest!\");\n" +" } else {\n" +" println!(\"y ({y}) is probably larger than x ({x})\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:24 +msgid "_interoperability/rust/libanalyze/analyze.h_" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:26 +msgid "" +"```c\n" +"#ifndef ANALYSE_H\n" +"#define ANALYSE_H" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:30 +msgid "" +"extern \"C\" {\n" +"void analyze_numbers(int x, int y);\n" +"}" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:34 +msgid "" +"#endif\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:37 +msgid "_interoperability/rust/libanalyze/Android.bp_" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:39 +msgid "" +"```javascript\n" +"rust_ffi {\n" +" name: \"libanalyze_ffi\",\n" +" crate_name: \"analyze_ffi\",\n" +" srcs: [\"analyze.rs\"],\n" +" include_dirs: [\".\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:48 +msgid "We can now call this from a C binary:" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:50 +msgid "_interoperability/rust/analyze/main.c_" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:52 +msgid "" +"```c\n" +"#include \"analyze.h\"" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:55 +msgid "" +"int main() {\n" +" analyze_numbers(10, 20);\n" +" analyze_numbers(123, 123);\n" +" return 0;\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:62 +msgid "_interoperability/rust/analyze/Android.bp_" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:64 +msgid "" +"```javascript\n" +"cc_binary {\n" +" name: \"analyze_numbers\",\n" +" srcs: [\"main.c\"],\n" +" static_libs: [\"libanalyze_ffi\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:75 +msgid "" +"```shell\n" +"$ m analyze_numbers\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp\n" +"$ adb shell /data/local/tmp/analyze_numbers\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:83 +msgid "" +"`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol will just be the name " +"of\n" +"the function. You can also use `#[export_name = \"some_name\"]` to specify whatever name you want." +msgstr "" + +#: src/android/interoperability/cpp.md:1 +msgid "# With C++" +msgstr "" + +#: src/android/interoperability/cpp.md:3 +msgid "" +"The [CXX crate][1] makes it possible to do safe interoperability between Rust\n" +"and C++." +msgstr "" + +#: src/android/interoperability/cpp.md:6 +msgid "The overall approach looks like this:" +msgstr "" + +#: src/android/interoperability/cpp.md:8 +msgid "" +msgstr "" + +#: src/android/interoperability/cpp.md:10 +msgid "See the [CXX tutorial][2] for an full example of using this." +msgstr "" + +#: src/android/interoperability/cpp.md:12 +msgid "" +"[1]: https://cxx.rs/\n" +"[2]: https://cxx.rs/tutorial.html" +msgstr "" + +#: src/android/interoperability/java.md:1 +msgid "# Interoperability with Java" +msgstr "" + +#: src/android/interoperability/java.md:3 +msgid "" +"Java can load shared objects via [Java Native Interface\n" +"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). The [`jni`\n" +"crate](https://docs.rs/jni/) allows you to create a compatible library." +msgstr "" + +#: src/android/interoperability/java.md:7 +msgid "First, we create a Rust function to export to Java:" +msgstr "" + +#: src/android/interoperability/java.md:9 +msgid "_interoperability/java/src/lib.rs_:" +msgstr "" + +#: src/android/interoperability/java.md:11 +msgid "" +"```rust,compile_fail\n" +"//! Rust <-> Java FFI demo." +msgstr "" + +#: src/android/interoperability/java.md:14 +msgid "" +"use jni::objects::{JClass, JString};\n" +"use jni::sys::jstring;\n" +"use jni::JNIEnv;" +msgstr "" + +#: src/android/interoperability/java.md:18 +msgid "" +"/// HelloWorld::hello method implementation.\n" +"#[no_mangle]\n" +"pub extern \"system\" fn Java_HelloWorld_hello(\n" +" env: JNIEnv,\n" +" _class: JClass,\n" +" name: JString,\n" +") -> jstring {\n" +" let input: String = env.get_string(name).unwrap().into();\n" +" let greeting = format!(\"Hello, {input}!\");\n" +" let output = env.new_string(greeting).unwrap();\n" +" output.into_inner()\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:32 src/android/interoperability/java.md:62 +msgid "_interoperability/java/Android.bp_:" +msgstr "" + +#: src/android/interoperability/java.md:34 +msgid "" +"```javascript\n" +"rust_ffi_shared {\n" +" name: \"libhello_jni\",\n" +" crate_name: \"hello_jni\",\n" +" srcs: [\"src/lib.rs\"],\n" +" rustlibs: [\"libjni\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:43 +msgid "Finally, we can call this function from Java:" +msgstr "" + +#: src/android/interoperability/java.md:45 +msgid "_interoperability/java/HelloWorld.java_:" +msgstr "" + +#: src/android/interoperability/java.md:47 +msgid "" +"```java\n" +"class HelloWorld {\n" +" private static native String hello(String name);" +msgstr "" + +#: src/android/interoperability/java.md:51 +msgid "" +" static {\n" +" System.loadLibrary(\"hello_jni\");\n" +" }" +msgstr "" + +#: src/android/interoperability/java.md:55 +msgid "" +" public static void main(String[] args) {\n" +" String output = HelloWorld.hello(\"Alice\");\n" +" System.out.println(output);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:64 +msgid "" +"```javascript\n" +"java_binary {\n" +" name: \"helloworld_jni\",\n" +" srcs: [\"HelloWorld.java\"],\n" +" main_class: \"HelloWorld\",\n" +" required: [\"libhello_jni\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:73 +msgid "Finally, you can build, sync, and run the binary:" +msgstr "" + +#: src/android/interoperability/java.md:75 +msgid "" +"```shell\n" +"$ m helloworld_jni\n" +"$ adb sync # requires adb root && adb remount\n" +"$ adb shell /system/bin/helloworld_jni\n" +"```" +msgstr "" + +#: src/exercises/day-4/afternoon.md:3 +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:" +msgstr "" + +#: src/exercises/day-4/afternoon.md:6 +msgid "* Call your AIDL service with a client written in Rust." +msgstr "" + +#: src/exercises/day-4/afternoon.md:8 +msgid "* Move a function from your project to Rust and call it." +msgstr "" + +#: src/exercises/day-4/afternoon.md:12 +msgid "" +"No solution is provided here since this is open-ended: it relies on someone in\n" +"the class having a piece of code which you can turn in to Rust on the fly." +msgstr "" + +#: src/thanks.md:1 +msgid "# Thanks!" +msgstr "" + +#: src/thanks.md:3 +msgid "" +"_Thank you for taking Comprehensive Rust 🦀!_ We hope you enjoyed it and that it\n" +"was useful." +msgstr "" + +#: src/thanks.md:6 +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 "" + +#: src/other-resources.md:1 +msgid "# Other Rust Resources" +msgstr "" + +#: src/other-resources.md:3 +msgid "" +"The Rust community has created a wealth of high-quality and free resources\n" +"online." +msgstr "" + +#: src/other-resources.md:6 +msgid "## Official Documentation" +msgstr "" + +#: src/other-resources.md:8 +msgid "The Rust project hosts many resources. These cover Rust in general:" +msgstr "" + +#: src/other-resources.md:10 +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 "" + +#: src/other-resources.md:22 +msgid "More specialized guides hosted on the official Rust site:" +msgstr "" + +#: src/other-resources.md:24 +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 "" + +#: src/other-resources.md:33 +msgid "## Unofficial Learning Material" +msgstr "" + +#: src/other-resources.md:35 +msgid "A small selection of other guides and tutorial for Rust:" +msgstr "" + +#: src/other-resources.md:37 +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 "" + +#: src/other-resources.md:63 +msgid "" +"Please see the [Little Book of Rust Books](https://lborb.github.io/book/) for\n" +"even more Rust books." +msgstr "" + +#: src/credits.md:1 +msgid "# Credits" +msgstr "" + +#: src/credits.md:3 +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 "" + +#: src/credits.md:7 +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 "" + +#: src/credits.md:10 +msgid "## Rust by Example" +msgstr "" + +#: src/credits.md:12 +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 "" + +#: src/credits.md:17 +msgid "## Rust on Exercism" +msgstr "" + +#: src/credits.md:19 +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 "" + +#: src/credits.md:24 +msgid "## CXX" +msgstr "" + +#: src/credits.md:26 +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 "" + +#: src/exercises/solutions.md:1 +msgid "# Solutions" +msgstr "" + +#: src/exercises/solutions.md:3 +msgid "You will find solutions to the exercises on the following pages." +msgstr "" + +#: src/exercises/solutions.md:5 +msgid "" +"Feel free to ask questions about the solutions [on\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Let us know\n" +"if you have a different or better solution than what is presented here." +msgstr "" + +#: src/exercises/solutions.md:10 +msgid "" +"> **Note:** Please ignore the `// ANCHOR: label` and `// ANCHOR_END: label`\n" +"> comments you see in the solutions. They are there to make it possible to\n" +"> re-use parts of the solutions as the exercises." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:1 +msgid "# Day 1 Morning Exercises" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:3 +msgid "## Arrays and `for` Loops" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:5 +msgid "([back to exercise](for-loops.md))" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:7 src/exercises/day-1/solutions-afternoon.md:7 +#: src/exercises/day-2/solutions-morning.md:7 src/exercises/day-2/solutions-afternoon.md:7 +#: src/exercises/day-2/solutions-afternoon.md:102 src/exercises/day-3/solutions-morning.md:7 +#: src/exercises/day-3/solutions-afternoon.md:7 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." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:22 +msgid "" +"// ANCHOR: transpose\n" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" // ANCHOR_END: transpose\n" +" let mut result = [[0; 3]; 3];\n" +" for i in 0..3 {\n" +" for j in 0..3 {\n" +" result[j][i] = matrix[i][j];\n" +" }\n" +" }\n" +" return result;\n" +"}" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:34 +msgid "" +"// ANCHOR: pretty_print\n" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" // ANCHOR_END: pretty_print\n" +" for row in matrix {\n" +" println!(\"{row:?}\");\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:42 +msgid "" +"// ANCHOR: tests\n" +"#[test]\n" +"fn test_transpose() {\n" +" let matrix = [\n" +" [101, 102, 103], //\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +" let transposed = transpose(matrix);\n" +" assert_eq!(\n" +" transposed,\n" +" [\n" +" [101, 201, 301], //\n" +" [102, 202, 302],\n" +" [103, 203, 303],\n" +" ]\n" +" );\n" +"}\n" +"// ANCHOR_END: tests" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:62 +msgid "" +"// ANCHOR: main\n" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:73 +msgid "" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```\n" +"### Bonus question" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:80 +msgid "" +"It requires more advanced concepts. It might seem that we could use a slice-of-slices " +"(`&[&[i32]]`) as the input type to transpose and thus make our function handle any size of matrix. " +"However, this quickly breaks down: the return type cannot be `&[&[i32]]` since it needs to own the " +"data you return." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:82 +msgid "" +"You can attempt to use something like `Vec>`, but this doesn't work out-of-the-box " +"either: it's hard to convert from `Vec>` to `&[&[i32]]` so now you cannot easily use " +"`pretty_print` either." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:84 +msgid "" +"Once we get to traits and generics, we'll be able to use the [`std::convert::AsRef`][1] trait to " +"abstract over anything that can be referenced as a slice." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:86 +msgid "" +"```rust\n" +"use std::convert::AsRef;\n" +"use std::fmt::Debug;" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:90 +msgid "" +"fn pretty_print(matrix: Matrix)\n" +"where\n" +" T: Debug,\n" +" // A line references a slice of items\n" +" Line: AsRef<[T]>,\n" +" // A matrix references a slice of lines\n" +" Matrix: AsRef<[Line]>\n" +"{\n" +" for row in matrix.as_ref() {\n" +" println!(\"{:?}\", row.as_ref());\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:103 +msgid "" +"fn main() {\n" +" // &[&[i32]]\n" +" pretty_print(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" +" // [[&str; 2]; 2]\n" +" pretty_print([[\"a\", \"b\"], [\"c\", \"d\"]]);\n" +" // Vec>\n" +" pretty_print(vec![vec![1, 2], vec![3, 4]]);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:113 +msgid "" +"In addition, the type itself would not enforce that the child slices are of the same length, so " +"such variable could contain an invalid matrix." +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:115 +msgid "[1]: https://doc.rust-lang.org/std/convert/trait.AsRef.html" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:1 +msgid "# Day 1 Afternoon Exercises" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:3 +msgid "## Designing a Library" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:5 +msgid "([back to exercise](book-library.md))" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:22 +msgid "" +"// ANCHOR: setup\n" +"struct Library {\n" +" books: Vec,\n" +"}" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:42 +msgid "" +"// 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" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:50 +msgid "" +"// ANCHOR: Library_new\n" +"impl Library {\n" +" fn new() -> Library {\n" +" // ANCHOR_END: Library_new\n" +" Library { books: Vec::new() }\n" +" }" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:57 +msgid "" +" // ANCHOR: Library_len\n" +" //fn len(self) -> usize {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_len\n" +" fn len(&self) -> usize {\n" +" self.books.len()\n" +" }" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:66 +msgid "" +" // ANCHOR: Library_is_empty\n" +" //fn is_empty(self) -> bool {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_is_empty\n" +" fn is_empty(&self) -> bool {\n" +" self.books.is_empty()\n" +" }" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:75 +msgid "" +" // ANCHOR: Library_add_book\n" +" //fn add_book(self, book: Book) {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_add_book\n" +" fn add_book(&mut self, book: Book) {\n" +" self.books.push(book)\n" +" }" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:84 +msgid "" +" // ANCHOR: Library_print_books\n" +" //fn print_books(self) {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_print_books\n" +" fn print_books(&self) {\n" +" for book in &self.books {\n" +" println!(\"{}\", book);\n" +" }\n" +" }" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:95 +msgid "" +" // ANCHOR: Library_oldest_book\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // unimplemented!()\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" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:105 +msgid "" +"// ANCHOR: main\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:113 +msgid "" +" //println!(\"Our 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" +" //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" +" //}\n" +" //\n" +" //println!(\"Our library has {} books\", library.len());\n" +"}\n" +"// ANCHOR_END: main" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:129 +msgid "" +"#[test]\n" +"fn test_library_len() {\n" +" let mut library = Library::new();\n" +" assert_eq!(library.len(), 0);\n" +" assert!(library.is_empty());" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:135 +msgid "" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" assert_eq!(library.len(), 2);\n" +" assert!(!library.is_empty());\n" +"}" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:141 +msgid "" +"#[test]\n" +"fn test_library_is_empty() {\n" +" let mut library = Library::new();\n" +" assert!(library.is_empty());" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:146 +msgid "" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert!(!library.is_empty());\n" +"}" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:150 +msgid "" +"#[test]\n" +"fn test_library_print_books() {\n" +" let mut library = Library::new();\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" // We could try and capture stdout, but let us just call the\n" +" // method to start with.\n" +" library.print_books();\n" +"}" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:160 +msgid "" +"#[test]\n" +"fn test_library_oldest_book() {\n" +" let mut library = Library::new();\n" +" assert!(library.oldest_book().is_none());" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:165 +msgid "" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Lord of the Rings\")\n" +" );" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:171 +msgid "" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Alice's Adventures in Wonderland\")\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:1 +msgid "# Day 2 Morning Exercises" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:3 +msgid "## Points and Polygons" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:5 +msgid "([back to exercise](points-polygons.md))" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:22 +msgid "" +"#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" +"// ANCHOR: Point\n" +"pub struct Point {\n" +" // ANCHOR_END: Point\n" +" x: i32,\n" +" y: i32,\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:30 +msgid "" +"// ANCHOR: Point-impl\n" +"impl Point {\n" +" // ANCHOR_END: Point-impl\n" +" pub fn new(x: i32, y: i32) -> Point {\n" +" Point { x, y }\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:37 +msgid "" +" pub fn magnitude(self) -> f64 {\n" +" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:41 +msgid "" +" pub fn dist(self, other: Point) -> f64 {\n" +" (self - other).magnitude()\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:49 +msgid "" +" fn add(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x + other.x,\n" +" y: self.y + other.y,\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:57 +msgid "" +"impl std::ops::Sub for Point {\n" +" type Output = Self;" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:60 +msgid "" +" fn sub(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x - other.x,\n" +" y: self.y - other.y,\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:68 +msgid "" +"// ANCHOR: Polygon\n" +"pub struct Polygon {\n" +" // ANCHOR_END: Polygon\n" +" points: Vec,\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:74 +msgid "" +"// ANCHOR: Polygon-impl\n" +"impl Polygon {\n" +" // ANCHOR_END: Polygon-impl\n" +" pub fn new() -> Polygon {\n" +" Polygon { points: Vec::new() }\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:81 +msgid "" +" pub fn add_point(&mut self, point: Point) {\n" +" self.points.push(point);\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:85 +msgid "" +" pub fn left_most_point(&self) -> Option {\n" +" self.points.iter().min_by_key(|p| p.x).copied()\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:89 +msgid "" +" pub fn iter(&self) -> impl Iterator {\n" +" self.points.iter()\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:93 +msgid "" +" pub fn length(&self) -> f64 {\n" +" if self.points.is_empty() {\n" +" return 0.0;\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:98 +msgid "" +" let mut result = 0.0;\n" +" let mut last_point = self.points[0];\n" +" for point in &self.points[1..] {\n" +" result += last_point.dist(*point);\n" +" last_point = *point;\n" +" }\n" +" result += last_point.dist(self.points[0]);\n" +" result\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:109 +msgid "" +"// ANCHOR: Circle\n" +"pub struct Circle {\n" +" // ANCHOR_END: Circle\n" +" center: Point,\n" +" radius: i32,\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:116 +msgid "" +"// ANCHOR: Circle-impl\n" +"impl Circle {\n" +" // ANCHOR_END: Circle-impl\n" +" pub fn new(center: Point, radius: i32) -> Circle {\n" +" Circle { center, radius }\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:123 +msgid "" +" pub fn circumference(&self) -> f64 {\n" +" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:127 +msgid "" +" pub fn dist(&self, other: &Self) -> f64 {\n" +" self.center.dist(other.center)\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:132 +msgid "" +"// ANCHOR: Shape\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"// ANCHOR_END: Shape" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:139 +msgid "" +"impl From for Shape {\n" +" fn from(poly: Polygon) -> Self {\n" +" Shape::Polygon(poly)\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:145 +msgid "" +"impl From for Shape {\n" +" fn from(circle: Circle) -> Self {\n" +" Shape::Circle(circle)\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:151 +msgid "" +"impl Shape {\n" +" pub fn perimeter(&self) -> f64 {\n" +" match self {\n" +" Shape::Polygon(poly) => poly.length(),\n" +" Shape::Circle(circle) => circle.circumference(),\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:160 +msgid "" +"// ANCHOR: unit-tests\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:213 +msgid "" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"// ANCHOR_END: unit-tests" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:233 src/exercises/day-2/solutions-afternoon.md:174 +msgid "" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:1 +msgid "# Day 2 Afternoon Exercises" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:3 +msgid "## Luhn Algorithm" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:5 +msgid "([back to exercise](luhn.md))" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:22 +msgid "" +"// ANCHOR: luhn\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" // ANCHOR_END: luhn\n" +" let mut digits_seen = 0;\n" +" let mut sum = 0;\n" +" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ').enumerate() {\n" +" match ch.to_digit(10) {\n" +" Some(d) => {\n" +" sum += if i % 2 == 1 {\n" +" let dd = d * 2;\n" +" dd / 10 + dd % 10\n" +" } else {\n" +" d\n" +" };\n" +" digits_seen += 1;\n" +" }\n" +" None => return false,\n" +" }\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:42 +msgid "" +" if digits_seen < 2 {\n" +" return false;\n" +" }" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:46 +msgid "" +" sum % 10 == 0\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:49 +msgid "" +"fn main() {\n" +" let cc_number = \"1234 5678 1234 5670\";\n" +" println!(\n" +" \"Is {} a valid credit card number? {}\",\n" +" cc_number,\n" +" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" +" );\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:58 +msgid "" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:89 +msgid "" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:98 +msgid "## Strings and Iterators" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:100 +msgid "([back to exercise](strings-iterators.md))" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:117 +msgid "" +"// ANCHOR: prefix_matches\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" // ANCHOR_END: prefix_matches\n" +" let prefixes = prefix.split('/');\n" +" let request_paths = request_path\n" +" .split('/')\n" +" .map(|p| Some(p))\n" +" .chain(std::iter::once(None));" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:126 +msgid "" +" for (prefix, request_path) in prefixes.zip(request_paths) {\n" +" match request_path {\n" +" Some(request_path) => {\n" +" if (prefix != \"*\") && (prefix != request_path) {\n" +" return false;\n" +" }\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +" true\n" +"}" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:139 +msgid "" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:166 +msgid "" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"// ANCHOR_END: unit-tests" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:1 +msgid "# Day 3 Morning Exercise" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:3 +msgid "## A Simple GUI Library" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:5 +msgid "([back to exercise](simple-gui.md))" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:22 +msgid "" +"// ANCHOR: setup\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:82 +msgid "// ANCHOR_END: setup" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:84 +msgid "" +"// ANCHOR: Window-width\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" // ANCHOR_END: Window-width\n" +" std::cmp::max(\n" +" self.title.chars().count(),\n" +" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +" )\n" +" }" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:94 +msgid "" +" // ANCHOR: Window-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Window-draw_into\n" +" let mut inner = String::new();\n" +" for widget in &self.widgets {\n" +" widget.draw_into(&mut inner);\n" +" }" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:102 +msgid " let window_width = self.width();" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:104 +msgid "" +" // TODO: after learning about error handling, you can change\n" +" // draw_into to return Result<(), std::fmt::Error>. Then use\n" +" // the ?-operator here instead of .unwrap().\n" +" writeln!(buffer, \"+-{:- usize {\n" +" // ANCHOR_END: Button-width\n" +" self.label.width() + 8 // add a bit of padding\n" +" }" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:124 +msgid "" +" // ANCHOR: Button-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Button-draw_into\n" +" let width = self.width();\n" +" let mut label = String::new();\n" +" self.label.draw_into(&mut label);" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:131 +msgid "" +" writeln!(buffer, \"+{:- usize {\n" +" // ANCHOR_END: Label-width\n" +" self.label\n" +" .lines()\n" +" .map(|line| line.chars().count())\n" +" .max()\n" +" .unwrap_or(0)\n" +" }" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:150 +msgid "" +" // ANCHOR: Label-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Label-draw_into\n" +" writeln!(buffer, \"{}\", &self.label).unwrap();\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:157 +msgid "" +"// ANCHOR: main\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" +"}\n" +"// ANCHOR_END: main\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:1 +msgid "# Day 3 Afternoon Exercises" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:3 +msgid "## Safe FFI Wrapper" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:5 +msgid "([back to exercise](safe-ffi-wrapper.md))" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:22 +msgid "" +"// ANCHOR: ffi\n" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:53 +msgid "" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}\n" +"// ANCHOR_END: ffi" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:60 +msgid "" +"// ANCHOR: DirectoryIterator\n" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" // ANCHOR_END: DirectoryIterator\n" +" let path = CString::new(path).map_err(|err| format!(\"Invalid path: {err}\"))?;\n" +" // SAFETY: path.as_ptr() cannot be NULL.\n" +" let dir = unsafe { ffi::opendir(path.as_ptr()) };\n" +" if dir.is_null() {\n" +" Err(format!(\"Could not open {:?}\", path))\n" +" } else {\n" +" Ok(DirectoryIterator { path, dir })\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:77 +msgid "" +"// ANCHOR: Iterator\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" // ANCHOR_END: Iterator\n" +" // SAFETY: self.dir is never NULL.\n" +" let dirent = unsafe { ffi::readdir(self.dir) };\n" +" if dirent.is_null() {\n" +" // We have reached the end of the directory.\n" +" return None;\n" +" }\n" +" // SAFETY: dirent is not NULL and dirent.d_name is NUL\n" +" // terminated.\n" +" let d_name = unsafe { CStr::from_ptr((*dirent).d_name.as_ptr()) };\n" +" let os_str = OsStr::from_bytes(d_name.to_bytes());\n" +" Some(os_str.to_owned())\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:97 +msgid "" +"// ANCHOR: Drop\n" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" // ANCHOR_END: Drop\n" +" if !self.dir.is_null() {\n" +" // SAFETY: self.dir is not NULL.\n" +" if unsafe { ffi::closedir(self.dir) } != 0 {\n" +" panic!(\"Could not close {:?}\", self.path);\n" +" }\n" +" }\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:111 +msgid "" +"// ANCHOR: main\n" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"// ANCHOR_END: main\n" +"```" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:1 +msgid "# Day 4 Morning Exercise" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:3 +msgid "## Dining Philosophers" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:5 +msgid "([back to exercise](dining-philosophers.md))" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:22 +msgid "" +"// ANCHOR: Philosopher\n" +"use std::sync::mpsc;\n" +"use std::sync::{Arc, Mutex};\n" +"use std::thread;\n" +"use std::time::Duration;" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:30 +msgid "" +"struct Philosopher {\n" +" name: String,\n" +" // ANCHOR_END: Philosopher\n" +" left_fork: Arc>,\n" +" right_fork: Arc>,\n" +" thoughts: mpsc::SyncSender,\n" +"}" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:38 +msgid "" +"// 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" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:47 +msgid "" +" // 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();" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:54 +msgid "" +" // ANCHOR: Philosopher-eat-end\n" +" println!(\"{} is eating...\", &self.name);\n" +" thread::sleep(Duration::from_millis(10));\n" +" }\n" +"}" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:63 +msgid "" +"fn main() {\n" +" // ANCHOR_END: Philosopher-eat-end\n" +" let (tx, rx) = mpsc::sync_channel(10);" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:67 +msgid "" +" let forks = (0..PHILOSOPHERS.len())\n" +" .map(|_| Arc::new(Mutex::new(Fork)))\n" +" .collect::>();" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:71 +msgid "" +" 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();" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:76 +msgid "" +" // To avoid a deadlock, we have to break the symmetry\n" +" // somewhere. This will swap the forks without deinitializing\n" +" // either of them.\n" +" if i == forks.len() - 1 {\n" +" std::mem::swap(&mut left_fork, &mut right_fork);\n" +" }" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:83 +msgid "" +" let philosopher = Philosopher {\n" +" name: PHILOSOPHERS[i].to_string(),\n" +" thoughts: tx,\n" +" left_fork,\n" +" right_fork,\n" +" };" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:90 +msgid "" +" thread::spawn(move || {\n" +" for _ in 0..100 {\n" +" philosopher.eat();\n" +" philosopher.think();\n" +" }\n" +" });\n" +" }" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:98 +msgid "" +" drop(tx);\n" +" for thought in rx {\n" +" println!(\"{thought}\");\n" +" }\n" +"}\n" +"```" +msgstr "" diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..293e4a1 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,17984 @@ +msgid "" +msgstr "" +"Project-Id-Version: Comprehensive Rust 🦀\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2023-04-12 22:05+0200\n" +"Last-Translator: Olivier Charrez \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.2.2\n" + +#: src/SUMMARY.md:3 +msgid "Welcome to Comprehensive Rust 🦀" +msgstr "Bienvenue à Comprehensive Rust(le guide complet de Rust)🦀" + +#: src/SUMMARY.md:4 +msgid "Running the Course" +msgstr "Instruire le cours" + +#: src/SUMMARY.md:5 +msgid "Course Structure" +msgstr "Structure du cours" + +#: src/SUMMARY.md:6 +msgid "Day 4" +msgstr "Jour 4" + +#: src/SUMMARY.md:7 +msgid "Keyboard Shortcuts" +msgstr "Raccourcis de clavier" + +#: src/SUMMARY.md:8 +msgid "Translations" +msgstr "Traductions" + +#: src/SUMMARY.md:9 +msgid "Using Cargo" +msgstr "Utiliser Cargo" + +#: src/SUMMARY.md:10 +msgid "Rust Ecosystem" +msgstr "Écosystème de Rust" + +#: src/SUMMARY.md:11 +msgid "Code Samples" +msgstr "Exemples de code" + +#: src/SUMMARY.md:12 +msgid "Running Cargo Locally" +msgstr "Exécuter Cargo localement" + +#: src/SUMMARY.md:15 +msgid "Day 1: Morning" +msgstr "Jour 1 : Matin" + +#: src/SUMMARY.md:19 src/SUMMARY.md:76 src/SUMMARY.md:129 src/SUMMARY.md:185 src/SUMMARY.md:239 +msgid "Welcome" +msgstr "Bienvenue" + +#: src/SUMMARY.md:20 +msgid "What is Rust?" +msgstr "Qu'est-ce que Rust ?" + +#: src/SUMMARY.md:21 +msgid "Hello World!" +msgstr "Bonjour le monde!" + +#: src/SUMMARY.md:22 +msgid "Small Example" +msgstr "Petit exemple" + +#: src/SUMMARY.md:23 +msgid "Why Rust?" +msgstr "Pourquoi Rust ?" + +#: src/SUMMARY.md:24 +msgid "Compile Time Guarantees" +msgstr "Garanties à la compilation" + +#: src/SUMMARY.md:25 +msgid "Runtime Guarantees" +msgstr "Garanties d'exécution" + +#: src/SUMMARY.md:26 +msgid "Modern Features" +msgstr "Fonctionnalités modernes" + +#: src/SUMMARY.md:27 +msgid "Basic Syntax" +msgstr "Syntaxe de base" + +#: src/SUMMARY.md:28 +msgid "Scalar Types" +msgstr "Types de scalaires" + +#: src/SUMMARY.md:29 +msgid "Compound Types" +msgstr "Types composés" + +#: src/SUMMARY.md:30 +msgid "References" +msgstr "Références" + +#: src/SUMMARY.md:31 +msgid "Dangling References" +msgstr "Références invalides" + +#: src/SUMMARY.md:32 +msgid "Slices" +msgstr "Tranches" + +#: src/SUMMARY.md:33 +msgid "String vs str" +msgstr "String vs str" + +#: src/SUMMARY.md:34 +msgid "Functions" +msgstr "Fonctions" + +#: src/SUMMARY.md:35 +msgid "Rustdoc" +msgstr "Rustdoc" + +#: src/SUMMARY.md:36 src/SUMMARY.md:83 +msgid "Methods" +msgstr "Méthodes" + +#: src/SUMMARY.md:37 +msgid "Overloading" +msgstr "Surcharge" + +#: 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:253 src/SUMMARY.md:279 +msgid "Exercises" +msgstr "Exercices" + +#: src/SUMMARY.md:39 +msgid "Implicit Conversions" +msgstr "Conversions implicites" + +#: src/SUMMARY.md:40 +msgid "Arrays and for Loops" +msgstr "Listes et boucles for" + +#: src/SUMMARY.md:42 +msgid "Day 1: Afternoon" +msgstr "Jour 1 : Après-midi" + +#: src/SUMMARY.md:44 +msgid "Variables" +msgstr "Variables" + +#: src/SUMMARY.md:45 +msgid "Type Inference" +msgstr "Inférence de type" + +#: src/SUMMARY.md:46 +msgid "static & const" +msgstr "static & const" + +#: src/SUMMARY.md:47 +msgid "Scopes and Shadowing" +msgstr "Portée et masquage" + +#: src/SUMMARY.md:48 +msgid "Memory Management" +msgstr "Gestion de la mémoire" + +#: src/SUMMARY.md:49 +msgid "Stack vs Heap" +msgstr "Pile et Tas" + +#: src/SUMMARY.md:50 +msgid "Stack Memory" +msgstr "Mémoire de pile" + +#: src/SUMMARY.md:51 +msgid "Manual Memory Management" +msgstr "Gestion manuelle de la mémoire" + +#: src/SUMMARY.md:52 +msgid "Scope-Based Memory Management" +msgstr "Gestion de la mémoire basée sur la portée" + +#: src/SUMMARY.md:53 +msgid "Garbage Collection" +msgstr "Collecte des ordures" + +#: src/SUMMARY.md:54 +msgid "Rust Memory Management" +msgstr "Gestion de la mémoire avec Rust" + +#: src/SUMMARY.md:55 +msgid "Comparison" +msgstr "Comparaison" + +#: src/SUMMARY.md:56 +msgid "Ownership" +msgstr "Propriété" + +#: src/SUMMARY.md:57 +msgid "Move Semantics" +msgstr "Sémantique de movement" + +#: src/SUMMARY.md:58 +msgid "Moved Strings in Rust" +msgstr "String déplacées avec Rust" + +#: src/SUMMARY.md:59 +msgid "Double Frees in Modern C++" +msgstr "Double libération de mémoire en C++ moderne" + +#: src/SUMMARY.md:60 +msgid "Moves in Function Calls" +msgstr "Déplacements dans les appels de fonction" + +#: src/SUMMARY.md:61 +msgid "Copying and Cloning" +msgstr "Copie et clonage" + +#: src/SUMMARY.md:62 +msgid "Borrowing" +msgstr "Emprunt" + +#: src/SUMMARY.md:63 +msgid "Shared and Unique Borrows" +msgstr "Emprunts partagés et uniques" + +#: src/SUMMARY.md:64 +msgid "Lifetimes" +msgstr "Durées de vie" + +#: src/SUMMARY.md:65 +msgid "Lifetimes in Function Calls" +msgstr "Durées de vie dans les appels de fonction" + +#: src/SUMMARY.md:66 +msgid "Lifetimes in Data Structures" +msgstr "Durées de vie dans les structures de données" + +#: src/SUMMARY.md:68 +msgid "Designing a Library" +msgstr "Conception d'une bibliothèque" + +#: src/SUMMARY.md:69 +msgid "Iterators and Ownership" +msgstr "Itérateurs et propriété" + +#: src/SUMMARY.md:72 +msgid "Day 2: Morning" +msgstr "Jour 2 : Matin" + +#: src/SUMMARY.md:77 +msgid "Structs" +msgstr "Structures" + +#: src/SUMMARY.md:78 +msgid "Tuple Structs" +msgstr "Structures de tuple" + +#: src/SUMMARY.md:79 +msgid "Field Shorthand Syntax" +msgstr "Syntaxe abrégée des champs" + +#: src/SUMMARY.md:80 +msgid "Enums" +msgstr "Énumérations" + +#: src/SUMMARY.md:81 +msgid "Variant Payloads" +msgstr "Contenu variable" + +#: src/SUMMARY.md:82 +msgid "Enum Sizes" +msgstr "Tailles d'énumération" + +#: src/SUMMARY.md:84 +msgid "Method Receiver" +msgstr "Récepteur de méthode" + +#: src/SUMMARY.md:85 src/SUMMARY.md:160 src/SUMMARY.md:195 +msgid "Example" +msgstr "Exemple" + +#: src/SUMMARY.md:86 +msgid "Pattern Matching" +msgstr "Correspondance de motifs" + +#: src/SUMMARY.md:87 +msgid "Destructuring Enums" +msgstr "Déstructuration des énumérations" + +#: src/SUMMARY.md:88 +msgid "Destructuring Structs" +msgstr "Déstructuration des structures" + +#: src/SUMMARY.md:89 +msgid "Destructuring Arrays" +msgstr "Déstructuration des listes" + +#: src/SUMMARY.md:90 +msgid "Match Guards" +msgstr "Gardes de match" + +#: src/SUMMARY.md:92 +msgid "Health Statistics" +msgstr "Statistiques de santé" + +#: src/SUMMARY.md:93 +msgid "Points and Polygons" +msgstr "Points et polygones" + +#: src/SUMMARY.md:95 +msgid "Day 2: Afternoon" +msgstr "Jour 2 : Après-midi" + +#: src/SUMMARY.md:97 +msgid "Control Flow" +msgstr "Flux de contrôle" + +#: src/SUMMARY.md:98 +msgid "Blocks" +msgstr "Blocs" + +#: src/SUMMARY.md:99 +msgid "if expressions" +msgstr "expressions `if`" + +#: src/SUMMARY.md:100 +msgid "if let expressions" +msgstr "expressions `if let`" + +#: src/SUMMARY.md:101 +msgid "while expressions" +msgstr "while expressions" + +#: src/SUMMARY.md:102 +msgid "while let expressions" +msgstr "expressions `while let`" + +#: src/SUMMARY.md:103 +msgid "for expressions" +msgstr "expressions `for`" + +#: src/SUMMARY.md:104 +msgid "loop expressions" +msgstr "expressions `loop`" + +#: src/SUMMARY.md:105 +msgid "match expressions" +msgstr "expressions `match`" + +#: src/SUMMARY.md:106 +msgid "break & continue" +msgstr "break & continue" + +#: src/SUMMARY.md:107 +msgid "Standard Library" +msgstr "Bibliothèque standard" + +#: src/SUMMARY.md:108 +msgid "Option and Result" +msgstr "Option et Result" + +#: src/SUMMARY.md:109 +msgid "String" +msgstr "String" + +#: src/SUMMARY.md:110 +msgid "Vec" +msgstr "Vec" + +#: src/SUMMARY.md:111 +msgid "HashMap" +msgstr "HashMap" + +#: src/SUMMARY.md:112 +msgid "Box" +msgstr "Box" + +#: src/SUMMARY.md:113 +msgid "Recursive Data Types" +msgstr "Types de données récursifs" + +#: src/SUMMARY.md:114 +msgid "Niche Optimization" +msgstr "Optimisation de niche" + +#: src/SUMMARY.md:115 +msgid "Rc" +msgstr "Rc" + +#: src/SUMMARY.md:116 +msgid "Modules" +msgstr "Modules" + +#: src/SUMMARY.md:117 +msgid "Visibility" +msgstr "Visibilité" + +#: src/SUMMARY.md:118 +msgid "Paths" +msgstr "Chemins" + +#: src/SUMMARY.md:119 +msgid "Filesystem Hierarchy" +msgstr "Hiérarchie du système de fichiers" + +#: src/SUMMARY.md:121 +msgid "Luhn Algorithm" +msgstr "Algorithme de Luhn" + +#: src/SUMMARY.md:122 +msgid "Strings and Iterators" +msgstr "Strings et Iterators" + +#: src/SUMMARY.md:125 +msgid "Day 3: Morning" +msgstr "Jour 3 : Matin" + +#: src/SUMMARY.md:130 +msgid "Generics" +msgstr "Génériques" + +#: src/SUMMARY.md:131 +msgid "Generic Data Types" +msgstr "Types de données génériques" + +#: src/SUMMARY.md:132 +msgid "Generic Methods" +msgstr "Méthodes génériques" + +#: src/SUMMARY.md:133 +msgid "Monomorphization" +msgstr "Monomorphisation" + +#: src/SUMMARY.md:134 +msgid "Traits" +msgstr "Caractéristiques" + +#: src/SUMMARY.md:135 +msgid "Trait Objects" +msgstr "Objets implementant des caractéristiques" + +#: src/SUMMARY.md:136 +msgid "Deriving Traits" +msgstr "Caractéristiques dérivées" + +#: src/SUMMARY.md:137 +msgid "Default Methods" +msgstr "Méthodes par défaut" + +#: src/SUMMARY.md:138 +msgid "Trait Bounds" +msgstr "Exigences de caractéristique" + +#: src/SUMMARY.md:139 +msgid "impl Trait" +msgstr "impl caractéristique" + +#: src/SUMMARY.md:140 +msgid "Important Traits" +msgstr "Caractéristiques importantes" + +#: src/SUMMARY.md:141 +msgid "Iterator" +msgstr "Iterator" + +#: src/SUMMARY.md:142 +msgid "FromIterator" +msgstr "FromIterator" + +#: src/SUMMARY.md:143 +msgid "From and Into" +msgstr "From et Into" + +#: src/SUMMARY.md:144 +msgid "Read and Write" +msgstr "Read et Write" + +#: src/SUMMARY.md:145 +msgid "Drop" +msgstr "Drop" + +#: src/SUMMARY.md:146 +msgid "Default" +msgstr "Default" + +#: src/SUMMARY.md:147 +msgid "Operators: Add, Mul, ..." +msgstr "Opérateurs : Add, Mul, ..." + +#: src/SUMMARY.md:148 +msgid "Closures" +msgstr "Fermetures" + +#: src/SUMMARY.md:150 +msgid "A Simple GUI Library" +msgstr "Une bibliothèque d'interface graphique" + +#: src/SUMMARY.md:152 +msgid "Day 3: Afternoon" +msgstr "Jour 3 : Après-midi" + +#: src/SUMMARY.md:154 +msgid "Error Handling" +msgstr "Gestion des erreurs" + +#: src/SUMMARY.md:155 +msgid "Panics" +msgstr "Paniques" + +#: src/SUMMARY.md:156 +msgid "Catching Stack Unwinding" +msgstr "Suspension de la pile" + +#: src/SUMMARY.md:157 +msgid "Structured Error Handling" +msgstr "Gestion structurée des erreurs" + +#: src/SUMMARY.md:158 +msgid "Propagating Errors with ?" +msgstr "Propagation des erreurs avec ?" + +#: src/SUMMARY.md:159 +msgid "Converting Error Types" +msgstr "Conversion des types d'erreur" + +#: src/SUMMARY.md:161 +msgid "Deriving Error Enums" +msgstr "Dérivation des énumérations d'erreur" + +#: src/SUMMARY.md:162 +msgid "Dynamic Error Types" +msgstr "Types d'erreurs dynamiques" + +#: src/SUMMARY.md:163 +msgid "Adding Context to Errors" +msgstr "Ajout de contexte aux erreurs" + +#: src/SUMMARY.md:164 +msgid "Testing" +msgstr "Tester" + +#: src/SUMMARY.md:165 +msgid "Unit Tests" +msgstr "Tests unitaires" + +#: src/SUMMARY.md:166 +msgid "Test Modules" +msgstr "Modules de test" + +#: src/SUMMARY.md:167 +msgid "Documentation Tests" +msgstr "Test de documentation" + +#: src/SUMMARY.md:168 +msgid "Integration Tests" +msgstr "Test d'intégration" + +#: src/SUMMARY.md:169 +msgid "Unsafe Rust" +msgstr "Rust risqué" + +#: src/SUMMARY.md:170 +msgid "Dereferencing Raw Pointers" +msgstr "Déréférencement des pointeurs bruts" + +#: src/SUMMARY.md:171 +msgid "Mutable Static Variables" +msgstr "Variables statiques mutables" + +#: src/SUMMARY.md:172 +msgid "Unions" +msgstr "Unions" + +#: src/SUMMARY.md:173 +msgid "Calling Unsafe Functions" +msgstr "Appel de fonctions risquées" + +#: src/SUMMARY.md:174 +msgid "Writing Unsafe Functions" +msgstr "Ecrire des fonctions risquées" + +#: src/SUMMARY.md:175 +msgid "Extern Functions" +msgstr "Fonctions externes" + +#: src/SUMMARY.md:176 +msgid "Implementing Unsafe Traits" +msgstr "Implémentation de traits risqués" + +#: src/SUMMARY.md:178 +msgid "Safe FFI Wrapper" +msgstr "Enveloppe FFI sûre" + +#: src/SUMMARY.md:181 +msgid "Day 4: Morning" +msgstr "Jour 4 : Matin" + +#: src/SUMMARY.md:186 +msgid "Concurrency" +msgstr "Concurrence" + +#: src/SUMMARY.md:187 +msgid "Threads" +msgstr "Threads" + +#: src/SUMMARY.md:188 +msgid "Scoped Threads" +msgstr "Threads délimités" + +#: src/SUMMARY.md:189 +msgid "Channels" +msgstr "Canaux" + +#: src/SUMMARY.md:190 +msgid "Unbounded Channels" +msgstr "Canaux illimités" + +#: src/SUMMARY.md:191 +msgid "Bounded Channels" +msgstr "Canaux limités" + +#: src/SUMMARY.md:192 +msgid "Shared State" +msgstr "État partagé" + +#: 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 et Sync" + +#: src/SUMMARY.md:196 +msgid "Send" +msgstr "Send" + +#: src/SUMMARY.md:196 +msgid "Sync" +msgstr "Sync" + +#: src/SUMMARY.md:199 +msgid "Examples" +msgstr "Exemples" + +#: src/SUMMARY.md:201 +msgid "Dining Philosophers" +msgstr "Dîner des philosophes" + +#: src/SUMMARY.md:202 +msgid "Multi-threaded Link Checker" +msgstr "Vérificateur de liens à plusieurs threads" + +#: src/SUMMARY.md:204 +msgid "Day 4: Afternoon (Android)" +msgstr "Jour 4 : Après-midi (Android)" + +#: src/SUMMARY.md:204 src/SUMMARY.md:277 +msgid "Android" +msgstr "Android" + +#: src/SUMMARY.md:209 +msgid "Setup" +msgstr "Installation" + +#: src/SUMMARY.md:210 +msgid "Build Rules" +msgstr "Règles de construction" + +#: src/SUMMARY.md:211 +msgid "Binary" +msgstr "Binaire" + +#: src/SUMMARY.md:212 +msgid "Library" +msgstr "Bibliothèque" + +#: src/SUMMARY.md:213 +msgid "AIDL" +msgstr "AIDL" + +#: src/SUMMARY.md:214 +msgid "Interface" +msgstr "Interface" + +#: src/SUMMARY.md:215 +msgid "Implementation" +msgstr "Mise en œuvre" + +#: src/SUMMARY.md:216 +msgid "Server" +msgstr "Serveur" + +#: src/SUMMARY.md:217 +msgid "Deploy" +msgstr "Déployer" + +#: src/SUMMARY.md:218 +msgid "Client" +msgstr "Client" + +#: src/SUMMARY.md:219 +msgid "Changing API" +msgstr "Modification de l'API" + +#: src/SUMMARY.md:220 src/SUMMARY.md:268 +msgid "Logging" +msgstr "Journalisation" + +#: src/SUMMARY.md:221 +msgid "Interoperability" +msgstr "Interopérabilité" + +#: src/SUMMARY.md:222 +msgid "With C" +msgstr "Avec C" + +#: src/SUMMARY.md:223 +msgid "Calling C with Bindgen" +msgstr "Appeler C avec Bindgen" + +#: src/SUMMARY.md:224 +msgid "Calling Rust from C" +msgstr "Appeler Rust depuis C" + +#: src/SUMMARY.md:225 +msgid "With C++" +msgstr "Avec C++" + +#: src/SUMMARY.md:226 +msgid "With Java" +msgstr "Avec Java" + +#: src/SUMMARY.md:229 +msgid "Final Words" +msgstr "Derniers mots" + +#: src/SUMMARY.md:231 +msgid "Thanks!" +msgstr "Merci!" + +#: src/SUMMARY.md:232 +msgid "Other Resources" +msgstr "Autres ressources" + +#: src/SUMMARY.md:233 +msgid "Credits" +msgstr "Crédits" + +#: src/SUMMARY.md:237 +msgid "Bare Metal Rust: Morning" +msgstr "Bare Metal Rust : Matin" + +#: src/SUMMARY.md:240 +msgid "no_std" +msgstr "no_std" + +#: src/SUMMARY.md:241 +msgid "A Minimal Example" +msgstr "Un exemple minimal" + +#: src/SUMMARY.md:242 +msgid "alloc" +msgstr "alloc" + +#: src/SUMMARY.md:243 +msgid "Microcontrollers" +msgstr "Microcontrôleurs" + +#: src/SUMMARY.md:244 +msgid "Raw MMIO" +msgstr "MMIO brut" + +#: src/SUMMARY.md:245 +msgid "PACs" +msgstr "PACs" + +#: src/SUMMARY.md:246 +msgid "HAL Crates" +msgstr "HAL Crates" + +#: src/SUMMARY.md:247 +msgid "Board Support Crates" +msgstr "Board Support Crates" + +#: src/SUMMARY.md:248 +msgid "The Type State Pattern" +msgstr "Le modèle d'état de type" + +#: src/SUMMARY.md:249 +msgid "embedded-hal" +msgstr "embedded-hal" + +#: src/SUMMARY.md:250 +msgid "probe-rs, cargo-embed" +msgstr "probe-rs, cargo-embed" + +#: src/SUMMARY.md:251 +msgid "Debugging" +msgstr "Débogage" + +#: src/SUMMARY.md:252 src/SUMMARY.md:270 +msgid "Other Projects" +msgstr "Autres projets" + +#: src/SUMMARY.md:254 +msgid "Compass" +msgstr "Boussole" + +#: src/SUMMARY.md:256 +msgid "Bare Metal Rust: Afternoon" +msgstr "Bare Metal Rust : Après-midi" + +#: src/SUMMARY.md:258 +msgid "Application Processors" +msgstr "Processeurs d'applications" + +#: src/SUMMARY.md:259 +msgid "Inline Assembly" +msgstr "Assembleur en ligne" + +#: src/SUMMARY.md:260 +msgid "MMIO" +msgstr "MMIO" + +#: src/SUMMARY.md:261 +msgid "Let's Write a UART Driver" +msgstr "Écrivons un pilote UART" + +#: src/SUMMARY.md:262 +msgid "More Traits" +msgstr "Plus de traits" + +#: src/SUMMARY.md:263 +msgid "A Better UART Driver" +msgstr "Un meilleur pilote UART" + +#: src/SUMMARY.md:264 +msgid "Bitflags" +msgstr "Bitflags" + +#: src/SUMMARY.md:265 +msgid "Multiple Registers" +msgstr "Registres multiples" + +#: src/SUMMARY.md:266 +msgid "Driver" +msgstr "Pilote" + +#: src/SUMMARY.md:267 src/SUMMARY.md:269 +msgid "Using It" +msgstr "En l'utilisant" + +#: src/SUMMARY.md:271 +msgid "Useful Crates" +msgstr "Crates utiles" + +#: src/SUMMARY.md:272 +msgid "zerocopy" +msgstr "zerocopy" + +#: src/SUMMARY.md:273 +msgid "aarch64-paging" +msgstr "aarch64-paging" + +#: src/SUMMARY.md:274 +msgid "buddy_system_allocator" +msgstr "buddy_system_allocator" + +#: src/SUMMARY.md:275 +msgid "tinyvec" +msgstr "tinyvec" + +#: src/SUMMARY.md:276 +msgid "spin" +msgstr "spin" + +#: src/SUMMARY.md:278 +msgid "vmbase" +msgstr "vmbase" + +#: src/SUMMARY.md:280 +msgid "RTC Driver" +msgstr "Pilote RTC" + +#: src/SUMMARY.md:284 +msgid "Solutions" +msgstr "Solutions" + +#: src/SUMMARY.md:289 +msgid "Day 1 Morning" +msgstr "Jour 1 Matin" + +#: src/SUMMARY.md:290 +msgid "Day 1 Afternoon" +msgstr "Jour 1 Après-midi" + +#: src/SUMMARY.md:291 +msgid "Day 2 Morning" +msgstr "Jour 2 Matin" + +#: src/SUMMARY.md:292 +msgid "Day 2 Afternoon" +msgstr "Jour 2 Après-midi" + +#: src/SUMMARY.md:293 +msgid "Day 3 Morning" +msgstr "Jour 3 Matin" + +#: src/SUMMARY.md:294 +msgid "Day 3 Afternoon" +msgstr "Jour 3 Après-midi" + +#: src/SUMMARY.md:295 +msgid "Day 4 Morning" +msgstr "Jour 4 Matin" + +#: src/SUMMARY.md:296 +msgid "Bare Metal Rust Morning" +msgstr "Bare Metal Rust Matin" + +#: src/SUMMARY.md:297 +msgid "Bare Metal Rust Afternoon" +msgstr "Bare Metal Rust Après-midi" + +#: src/welcome.md:1 +msgid "# Welcome to Comprehensive Rust 🦀" +msgstr "# Bienvenue à Comprehensive Rust(le guide complet de Rust) 🦀" + +#: src/welcome.md:3 +msgid "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" +"google/comprehensive-rust/actions/workflows/build.yml)" +msgstr "" +"[![Flux de construction](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)" + +#: src/welcome.md:3 +msgid "Build workflow" +msgstr "Flux de construction" + +#: src/welcome.md:3 +msgid "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" +"google/comprehensive-rust/actions/workflows/build.yml)\n" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)" +msgstr "" +"[![Flux de construction](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" +"[![Contributeurs GitHub](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)" + +#: src/welcome.md:4 +msgid "GitHub contributors" +msgstr "Contributeurs GitHub" + +#: src/welcome.md:4 +msgid "" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)\n" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers)" +msgstr "" +"[![Contributeurs GitHub](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)\n" +"[![GitHub étoiles](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers )" + +#: src/welcome.md:5 +msgid "GitHub stars" +msgstr "Étoiles GitHub" + +#: src/welcome.md:5 +msgid "" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers)" +msgstr "" +"[![GitHub étoiles](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers)" + +#: src/welcome.md:7 +msgid "" +"This is a four 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 "" +"Il s'agit d'un cours Rust de quatre jours développé par l'équipe Android. Le cours couvre\n" +"le spectre complet de Rust, de la syntaxe de base aux sujets avancés comme les génériques\n" +"et la gestion des erreurs. Il inclut également du contenu spécifique à Android le dernier jour." + +#: src/welcome.md:11 +msgid "" +"The goal of the course is to teach you Rust. We assume you don't know anything\n" +"about Rust and hope to:" +msgstr "" +"Le but du cours est de vous apprendre Rust. Nous supposons que vous ne savez rien\n" +"à propos de Rust et espérons :" + +#: src/welcome.md:14 +msgid "" +"* Give you a comprehensive understanding of the Rust syntax and language.\n" +"* Enable you to modify existing programs and write new programs in Rust.\n" +"* Show you common Rust idioms." +msgstr "" +"* Vous donner une compréhension complète de la syntaxe et du langage Rust.\n" +"* Vous permettre de modifier des programmes existants et d'écrire de nouveaux programmes dans Rust.\n" +"* Vous montrer les idiomes courants à Rust." + +#: src/welcome.md:18 +msgid "On Day 4, we will cover Android-specific things such as:" +msgstr "Le 4ème jour, nous couvrirons des éléments spécifiques à Android tels que :" + +#: src/welcome.md:20 +msgid "" +"* Building Android components in Rust.\n" +"* AIDL servers and clients.\n" +"* Interoperability with C, C++, and Java." +msgstr "" +"* Construire des composants Android avec Rust.\n" +"* Serveurs et clients AIDL.\n" +"* Interopérabilité avec C, C++ et Java." + +#: src/welcome.md:24 +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 "" +"Il est important de noter que ce cours ne couvre pas un développement d' **application** Android\n" +"avec Rust, et que les parties spécifiques à Android concernent spécifiquement\n" +"l'écriture du code pour le système d'exploitation Android lui même, le système d'exploitation. " + +#: src/welcome.md:28 +msgid "## Non-Goals" +msgstr "## Non-objectifs" + +#: src/welcome.md:30 +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:" +msgstr "" +"Rust est un grand langage et nous ne pourrons pas tout couvrir en quelques jours.\n" +"Certains non-objectifs de ce cours sont :" + +#: src/welcome.md:33 +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 "" +"* Apprenez à utiliser Rust asynchrone --- nous ne mentionnerons Rust asynchrone que lorsque\n" +" couvrant les primitives de concurrence traditionnelles. Veuillez consulter [Programmation\n" +" Asynchrone en Rust](https://rust-lang.github.io/async-book/) à la place de\n" +" détails sur ce sujet.\n" +"* Apprenez à développer des macros, veuillez consulter [Chapitre 19.5 dans le Livre\n" +" Rust](https://doc.rust-lang.org/book/ch19-06-macros.html) et [Rust par\n" +" Exemple](https://doc.rust-lang.org/rust-by-example/macros.html) à la place." + +#: src/welcome.md:41 +msgid "## Assumptions" +msgstr "## Hypothèses" + +#: src/welcome.md:43 +msgid "" +"The course assumes that you already know how to program. Rust is a statically\n" +"typed language and we will sometimes make comparisons with C and C++ to better\n" +"explain or contrast the Rust approach." +msgstr "" +"Le cours suppose que vous savez déjà programmer. Rust est un language\n" +"statiquement typé et on fera parfois des comparaisons avec C et C++ pour mieux\n" +"expliquer ou contraster l'approche de Rust." + +#: src/welcome.md:47 +msgid "" +"If you know how to program in a dynamically typed language such as Python or\n" +"JavaScript, then you will be able to follow along just fine too." +msgstr "" +"Si vous savez programmer dans un langage à typage dynamique tel que Python ou\n" +"JavaScript, alors vous pourrez également très bien suivre." + +#: src/welcome.md:50 src/cargo/rust-ecosystem.md:19 src/cargo/code-samples.md:22 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/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/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/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/bare-metal/minimal.md:15 src/bare-metal/alloc.md:36 +#: 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 src/bare-metal/microcontrollers/type-state.md:30 +#: src/bare-metal/microcontrollers/embedded-hal.md:17 src/bare-metal/microcontrollers/probe-rs.md:14 src/bare-metal/microcontrollers/debugging.md:25 +#: src/bare-metal/microcontrollers/other-projects.md:16 src/exercises/bare-metal/morning.md:5 src/bare-metal/aps.md:7 +#: src/bare-metal/aps/inline-assembly.md:41 src/bare-metal/aps/mmio.md:7 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:47 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/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 +msgid "
" +msgstr "
" + +#: src/welcome.md:52 +msgid "" +"This is an example of a _speaker note_. We will use these to add additional\n" +"information to the slides. This could be key points which the instructor should\n" +"cover as well as answers to typical questions which come up in class." +msgstr "" +"Ceci est un exemple de _note du conférencier_. Nous les utiliserons pour ajouter d'autres\n" +"informations sur les diapositives. Cela pourrait être des points clés que l'instructeur devrait\n" +"couvrir, ainsi que des réponses aux questions typiques posées en classe." + +#: src/welcome.md:56 src/cargo/rust-ecosystem.md:67 src/cargo/code-samples.md:35 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/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 src/memory-management/rust.md:18 +#: src/ownership/move-semantics.md:26 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/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/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/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/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/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/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/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/bare-metal/no_std.md:65 src/bare-metal/minimal.md:26 +#: src/bare-metal/alloc.md:48 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 src/bare-metal/microcontrollers/other-projects.md:26 src/exercises/bare-metal/morning.md:11 +#: 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:53 src/bare-metal/aps/logging.md:52 +#: src/bare-metal/aps/logging/using.md:48 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 +msgid "
" +msgstr "
" + +#: src/running-the-course.md:1 +msgid "# Running the Course" +msgstr "# Exécution du parcours" + +#: 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 "> Cette page est destinée au formateur." + +#: src/running-the-course.md:5 +msgid "" +"Here is a bit of background information about how we've been running the course\n" +"internally at Google." +msgstr "" +"Voici quelques informations générales sur la façon dont nous avons organisé le cours\n" +"en interne chez Google." + +#: src/running-the-course.md:8 +msgid "Before you run the course, you will want to:" +msgstr "Avant de suivre le cours, vous voudriez :" + +#: src/running-the-course.md:10 +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" +" notes!). When presenting, you should make sure to open the speaker notes in a\n" +" 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" +" 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" +" 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" +" In particular, you will be doing a lot of live-coding as an instructor, so a lectern won't\n" +" be very helpful for you.\n" +"\n" +"1. On the day of your course, show up to the room a little early to set things\n" +" up. We recommend presenting directly using `mdbook serve` running on your\n" +" laptop (see the [installation instructions][3]). This ensures optimal performance with no lag as you change pages.\n" +" 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" +" 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." +msgstr "" +"1. Familiarisez-vous avec le matériel de cours. Nous avons inclus les notes du conférencier\n" +" pour aider à mettre en évidence les points clés (veuillez nous aider en contribuant à plus de\n" +" remarques!). Lors de la présentation, vous devez vous assurer d'ouvrir les notes du présentateur dans un\n" +" popup (cliquez sur le lien avec une petite flèche à côté de \"Notes du conférencier\"). Ainsi,\n" +" vous avez un écran propre à présenter à la classe.\n" +"\n" +"1. Sélectionnez votre sujet pour l'après-midi du quatrième jour. Cela peut être basé sur\n" +" le public que vous attendez, ou sur votre propre expertise.\n" +"\n" +"1. Décidez des dates. Comme le parcours est vaste, nous vous recommandons de\n" +" répartir les quatre jours sur deux semaines. Les participants au cours ont dit\n" +" qu'ils trouvent utile d'avoir une pause dans le cours, car cela les aide à traiter\n" +" toutes les informations que nous leur donnons.\n" +"\n" +"1. Trouvez une salle suffisamment grande pour vos participants en personne. Nous recommandons un\n" +" classe de 15 à 20 personnes. C'est assez petit pour que les gens soient à l'aise pour\n" +" poser des questions --- c'est aussi assez petit pour qu'un instructeur ait\n" +" le temps de répondre aux questions. Assurez-vous que la salle dispose de _bureaux_ pour vous et pour les\n" +" étudiants : vous devriez tous pouvoir vous asseoir et travailler avec vos ordinateurs portables.\n" +" En particulier, vous ferez beaucoup de programmation en direct en tant qu'instructeur, donc un pupitre\n" +" ne sera pas très utile pour vous.\n" +"\n" +"1. Le jour de votre cours, présentez-vous à la salle un peu en avance pour préparer les choses.\n" +" Nous vous recommandons de présenter directement en utilisant `mdbook serve` exécuté sur votre\n" +" ordinateur portable (voir les [instructions d'installation][3]). Cela garantit des performances optimales\n" +" sans décalage lorsque vous changez de page.\n" +" L'utilisation de votre ordinateur portable vous permettra également de corriger les fautes de frappe lorsque que vous ou\n" +" les participants les repèrent.\n" +"\n" +"1. Laissez les participants résoudre les exercices seuls ou en petits groupes. Assurez-vous de\n" +" demandez aux gens s'ils sont coincés ou s'il y a quelque chose où vous pouvez aider. Quand\n" +" vous voyez que plusieurs personnes ont le même problème, dites-le à la classe\n" +" et proposez une solution, par exemple en montrant aux gens où trouver les\n" +" informations dans la bibliothèque standard.\n" +"\n" +"1. Préparez tout ce dont vous avez besoin pour l'après-midi du jour 4." + +#: src/running-the-course.md:46 +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!" +msgstr "" +"C'est tout, bonne chance pour suivre le cours ! Nous espérons que ce sera aussi amusant pour\n" +"vous comme il l'a été pour nous !" + +#: src/running-the-course.md:49 +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" +"better. Your students are also very welcome to [send us feedback][2]!" +msgstr "" +"Veuillez [fournir des commentaires][1] par la suite afin que nous puissions continuer à améliorer le\n" +"cours. Nous aimerions savoir ce qui a bien fonctionné pour vous et ce qui peut être mieux fait.\n" +"Vos élèves sont également les bienvenus pour [envoyer des commentaires][2] !" + +#: src/running-the-course/course-structure.md:1 +msgid "# Course Structure" +msgstr "# Structure du cours" + +#: src/running-the-course/course-structure.md:5 +msgid "The course is fast paced and covers a lot of ground:" +msgstr "Le cours est rapide et couvre beaucoup de terrain:" + +#: src/running-the-course/course-structure.md:7 +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." +msgstr "" +"* Jour 1 : Rust de base, propriété et vérificateur d'emprunt.\n" +"* Jour 2 : Types de données composés, filtrage de motifs, bibliothèque standard.\n" +"* Jour 3 : Caractéristiques et génériques, gestion des erreurs, tests, Rust risqué.\n" +"* Jour 4 : Concurrence avec Rust et voir Rust en action." + +#: src/running-the-course/course-structure.md:12 +msgid "## Format" +msgstr "##Format" + +#: src/running-the-course/course-structure.md:14 +msgid "" +"The course is meant to be very interactive and we recommend letting the\n" +"questions drive the exploration of Rust!" +msgstr "" +"Le cours se veut très interactif et nous recommandons de laisser les\n" +"questions guider l'exploration de Rust !" + +#: src/running-the-course/day-4.md:1 +msgid "# Day 4" +msgstr "# Jour 4" + +#: src/running-the-course/day-4.md:5 +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 "" +"L'après-midi du quatrième jour devrait couvrir un sujet de votre choix. Ajoutez\n" +"le sujet dans l'annonce du cours, afin que les participants sachent à quoi\n" +"s'attendre." + +#: src/running-the-course/day-4.md:9 +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 "" +"Cette phase du cours est une chance pour les participants de voir Rust en action sur une\n" +"base de code qu'ils connaissent peut-être. Vous pouvez déjà choisir parmi les sujets\n" +"définis ici, ou planifiez le vôtre." + +#: src/running-the-course/day-4.md:13 +msgid "Some topics need additional preparation:" +msgstr "Certains sujets nécessitent une préparation supplémentaire :" + +#: 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/`." +msgstr "" +"Si vous avez choisi Android pour l'après-midi du jour 4, vous aurez besoin d'un [AOSP checkout][1].\n" +"Effectuez un checkout du [répertoire du cours][2] sur la même machine et déplacez le dossier\n" +"`src/android/` à la racine de votre checkout AOSP. Cela assurera\n" +"que le système de construction d'Android voit les fichiers `Android.bp` dans `src/android/`." + +#: src/running-the-course/day-4.md:22 +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." +msgstr "" +"Assurez-vous que `adb sync` fonctionne avec votre émulateur ou votre appareil réel et pré-construisez\n" +"tous les exemples Android en utilisant `src/android/build_all.sh`. Lisez le script pour voir\n" +"les commandes éxécutées et assurez-vous qu'elles fonctionnent lorsque vous les exécutez à la main." + +#: src/running-the-course/keyboard-shortcuts.md:1 +msgid "# Keyboard Shortcuts" +msgstr "# Raccourcis clavier" + +#: src/running-the-course/keyboard-shortcuts.md:3 +msgid "There are several useful keyboard shortcuts in mdBook:" +msgstr "Il existe plusieurs raccourcis clavier utiles dans mdBook :" + +#: src/running-the-course/keyboard-shortcuts.md:5 +msgid "" +"* Arrow-Left: Navigate to the previous page.\n" +"* Arrow-Right: Navigate to the next page.\n" +"* Ctrl + Enter: Execute the code sample that has focus.\n" +"* s: Activate the search bar." +msgstr "" +"* Flèche vers la gauche : Navigue à la page précédente.\n" +"* Flèche vers la droite : Navigue à la page suivante.\n" +"* Ctrl + Entrée : Exécute l'exemple de code qui a le focus.\n" +"* s : Active la barre de recherche." + +#: src/running-the-course/translations.md:1 +msgid "# Translations" +msgstr "# Traductions" + +#: src/running-the-course/translations.md:3 +msgid "" +"The course has been translated into other languages by a set of wonderful\n" +"volunteers:" +msgstr "" +"Le cours a été traduit dans d'autres langues par un ensemble de merveilleux\n" +"bénévoles:" + +#: src/running-the-course/translations.md:6 +msgid "" +"* [Brazilian Portuguese][pt-BR] by [@rastringer] and [@hugojacob].\n" +"* [Korean][ko] by [@keispace], [@jiyongp] and [@jooyunghan]." +msgstr "" +"* [portugais brésilien][pt-BR] par [@rastringer] et [@hugojacob].\n" +"* [coréen][ko] par [@keispace], [@jiyongp] et [@jooyunghan]." + +#: src/running-the-course/translations.md:9 +msgid "Use the language picker in the top-right corner to switch between languages." +msgstr "Utilisez le sélecteur de langue dans le coin supérieur droit pour basculer entre les langues." + +#: src/running-the-course/translations.md:11 +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]." +msgstr "" +"Si vous souhaitez contribuer à cet effort, veuillez consulter [nos instructions] pour savoir comment\n" +"se lancer. Les traductions sont coordonnées sur le [traqueur de problèmes]." + +#: src/cargo.md:1 +msgid "# Using Cargo" +msgstr "# Utiliser Cargo" + +#: src/cargo.md:3 +msgid "" +"When you start reading about Rust, you will soon meet [Cargo](https://doc.rust-lang.org/cargo/), the standard tool\n" +"used in the Rust ecosystem to build and run Rust applications. Here we want to\n" +"give a brief overview of what Cargo is and how it fits into the wider ecosystem\n" +"and how it fits into this training." +msgstr "" +"Lorsque vous commencerez à lire sur Rust, vous rencontrerez bientôt [Cargo](https://doc.rust-lang.org/cargo/), l'outil standard\n" +"utilisé dans l'écosystème Rust pour créer et exécuter des applications Rust. Ici, nous voulons\n" +"donner un bref aperçu de ce qu'est Cargo et comment il s'intègre dans le large écosystème\n" +"et comment cela s'inscrit dans cette formation." + +#: src/cargo.md:8 +msgid "## Installation" +msgstr "## Installation" + +#: src/cargo.md:10 +msgid "### Rustup (Recommended)" +msgstr "### Rustup (recommandé)" + +#: src/cargo.md:12 +msgid "" +"You can follow the instructions to install cargo and rust compiler, among other standard ecosystem tools with the [rustup][3] tool, which is " +"maintained by the Rust Foundation." +msgstr "" +"Vous pouvez suivre les instructions pour installer Cargo et le compilateur Rust, parmi d'autres outils de l'écosystème standard avec l'outil [rustup]" +"[3], qui est maintenu par la Foundation Rust." + +#: src/cargo.md:14 +msgid "" +"Along with cargo and rustc, Rustup will install itself as a command line utility that you can use to install/switch toolchains, setup cross " +"compilation, etc." +msgstr "" +"Avec cargo et rustc, Rustup s'installera en tant qu'utilitaire de ligne de commande que vous pourrez utiliser pour installer/changer de chaînes " +"d'outils, configurer une compilation croisée, etc." + +#: src/cargo.md:16 +msgid "### Package Managers" +msgstr "### Gestionnaires de packages" + +#: src/cargo.md:18 +msgid "#### Debian" +msgstr "#### Debian" + +#: src/cargo.md:20 +msgid "On Debian/Ubuntu, you can install Cargo, the Rust source and the [Rust formatter][6] with" +msgstr "Sur Debian/Ubuntu, vous pouvez installer Cargo, la source Rust et le [formateur Rust][6] avec" + +#: src/cargo.md:22 +msgid "" +"```shell\n" +"$ sudo apt install cargo rust-src rustfmt\n" +"```" +msgstr "" + +#: src/cargo.md:26 +msgid "" +"This will allow [rust-analyzer][1] to jump to the definitions. We suggest using\n" +"[VS Code][2] to edit the code (but any LSP compatible editor works)." +msgstr "" +"Cela permettra à [rust-analyzer][1] de passer directement aux définitions. Nous suggérons d'utiliser\n" +"[VS Code][2] pour modifier le code (mais tout éditeur LSP compatible fonctionne)." + +#: src/cargo.md:29 +msgid "" +"Some folks also like to use the [JetBrains][4] family of IDEs, which do their own analysis but have their own tradeoffs. If you prefer them, you can " +"install the [Rust Plugin][5]. Please take note that as of January 2023 debugging only works on the CLion version of the JetBrains IDEA suite." +msgstr "" +"Certaines personnes aiment également utiliser la famille d'IDE [JetBrains] [4], qui effectuent leur propre analyse mais ont leurs propres compromis. " +"Si vous les préférez, vous pouvez installer le [Plugin Rust][5]. Veuillez noter qu'à partir de janvier 2023, le débogage ne fonctionne que sur la " +"version CLion de la suite JetBrains IDEA." + +#: src/cargo/rust-ecosystem.md:1 +msgid "# The Rust Ecosystem" +msgstr "# L'écosystème de Rust" + +#: src/cargo/rust-ecosystem.md:3 +msgid "The Rust ecosystem consists of a number of tools, of which the main ones are:" +msgstr "L'écosystème de Rust est composé d'un certain nombre d'outils, dont les principaux sont :" + +#: src/cargo/rust-ecosystem.md:5 +msgid "" +"* `rustc`: the Rust compiler which turns `.rs` files into binaries and other\n" +" intermediate formats.\n" +"\n" +"* `cargo`: the Rust dependency manager and build tool. Cargo knows how to\n" +" download dependencies hosted on and it will pass them to\n" +" `rustc` when building your project. Cargo also comes with a built-in test\n" +" runner which is used to execute unit tests.\n" +"\n" +"* `rustup`: the Rust toolchain installer and updater. This tool is used to\n" +" install and update `rustc` and `cargo` when new versions of Rust is released.\n" +" In addition, `rustup` can also download documentation for the standard\n" +" library. You can have multiple versions of Rust installed at once and `rustup`\n" +" will let you switch between them as needed." +msgstr "" +"* `rustc` : le compilateur Rust qui transforme les fichiers `.rs` en binaires et autres\n" +" formats intermédiaires.\n" +"\n" +"* `cargo` : le gestionnaire de dépendances Rust et l'outil de construction. Cargo sait comment\n" +" télécharger les dépendances hébergées sur et il les transmettra à\n" +" `rustc` lors de la construction de votre projet. Cargo est également livré avec un exécuteur de test\n" +" qui est utilisé pour exécuter des tests unitaires.\n" +"\n" +"* `rustup` : le programme d'installation et de mise à jour de la chaîne d'outils Rust. Cet outil sert à\n" +" installer et mettez à jour `rustc` et `cargo` lorsque de nouvelles versions de Rust sont publiées.\n" +" De plus, `rustup` peut également télécharger la documentation de la \n" +" bibliothèque standard. Vous pouvez avoir plusieurs versions de Rust installées à la fois et `rustup`\n" +" vous permettra de basculer entre elles au besoin." + +#: 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 +msgid "Key points:" +msgstr "Points clés:" + +#: src/cargo/rust-ecosystem.md:23 +msgid "" +"* Rust has a rapid release schedule with a new release coming out\n" +" every six weeks. New releases maintain backwards compatibility with\n" +" old releases --- plus they enable new functionality.\n" +"\n" +"* There are three release channels: \"stable\", \"beta\", and \"nightly\".\n" +"\n" +"* New features are being tested on \"nightly\", \"beta\" is what becomes\n" +" \"stable\" every six weeks.\n" +"\n" +"* Rust also has [editions]: the current edition is Rust 2021. Previous\n" +" editions were Rust 2015 and Rust 2018.\n" +"\n" +" * The editions are allowed to make backwards incompatible changes to\n" +" the language.\n" +"\n" +" * To prevent breaking code, editions are opt-in: you select the\n" +" edition for your crate via the `Cargo.toml` file.\n" +"\n" +" * To avoid splitting the ecosystem, Rust compilers can mix code\n" +" written for different editions.\n" +"\n" +" * Mention that it is quite rare to ever use the compiler directly not through `cargo` (most users never do).\n" +"\n" +" * It might be worth alluding that Cargo itself is an extremely powerful and comprehensive tool. It is capable of many advanced features including " +"but not limited to: \n" +" * Project/package structure\n" +" * [workspaces]\n" +" * Dev Dependencies and Runtime Dependency management/caching\n" +" * [build scripting]\n" +" * [global installation]\n" +" * It is also extensible with sub command plugins as well (such as [cargo clippy]).\n" +" * Read more from the [official Cargo Book]" +msgstr "" +"* Rust a un calendrier de publication rapide avec une nouvelle version qui sort\n" +" toutes les six semaines. Les nouvelles versions maintiennent la rétrocompatibilité avec les\n" +" anciennes versions --- en plus, elles activent de nouvelles fonctionnalités.\n" +"\n" +"* Il existe trois canaux de sortie : \"stable\", \"beta\" et \"nightly\".\n" +"\n" +"* De nouvelles fonctionnalités sont testées sur \"nightly\", \"beta\" est ce qui devient\n" +" \"stable\" toutes les six semaines.\n" +"\n" +"* Rust a également des [éditions] : l'édition actuelle est Rust 2021.\n" +" Les éditions passées étaient Rust 2015 et Rust 2018.\n" +"\n" +" * Les éditions sont autorisées à apporter des modifications rétrocompatibles à\n" +" la langue.\n" +"\n" +" * Pour éviter de casser le code, les éditions sont opt-in : vous sélectionnez\n" +" l'édition pour votre crate via le fichier `Cargo.toml`.\n" +"\n" +" * Pour éviter de diviser l'écosystème, les compilateurs Rust peuvent mélanger le code\n" +" écrit pour différentes éditions.\n" +"\n" +" * Veuillez noter qu'il est assez rare d'utiliser le compilateur directement et non via `cargo` (la plupart des utilisateurs ne le font jamais).\n" +"\n" +" * Il peut être utile de mentionner que Cargo lui-même est un outil extrêmement puissant et complet. Il est capable de nombreuses fonctionnalités " +"avancées, y compris, mais sans s'y limiter :\n" +" * Structure du projet/paquets\n" +" * [espaces de travail]\n" +" * Gestion/mise en cache des dépendances de développement et des dépendances d'exécution\n" +" * [créer des scripts]\n" +" * [installation globale]\n" +" * Il est également extensible avec des plugins de sous-commande (tels que [cargo clippy]).\n" +" * En savoir plus sur le [livre officiel de Cargo]" + +#: src/cargo/code-samples.md:1 +msgid "# Code Samples in This Training" +msgstr "# Échantillons de code dans cette formation" + +#: src/cargo/code-samples.md:3 +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" +"ensures a consistent experience for everyone." +msgstr "" +"Pour cette formation, nous allons surtout explorer le langage Rust à travers des exemples\n" +"qui peuvent être exécuté via votre navigateur. Cela rend la configuration beaucoup plus facile et\n" +"assure une expérience cohérente pour chacun." + +#: src/cargo/code-samples.md:7 +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 "" +"L'installation de Cargo est tout de même encouragée : elle vous facilitera la tâche\n" +"des exercices. Le dernier jour, nous ferons un exercice plus large qui vous montrera comment\n" +"travailler avec des dépendances et pour cela vous avez besoin de Cargo." + +#: src/cargo/code-samples.md:11 +msgid "The code blocks in this course are fully interactive:" +msgstr "Les blocs de code de ce cours sont entièrement interactifs :" + +#: src/cargo/code-samples.md:13 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" println!(\"Edit me!\");\n" +"}\n" +"```" +msgstr "" + +#: src/cargo/code-samples.md:19 +msgid "" +"You can use Ctrl + Enter to execute the code when focus is in the\n" +"text box." +msgstr "" +"Vous pouvez utiliser Ctrl + Entrée pour exécuter le code lorsque le focus est dans la\n" +"zone de texte." + +#: src/cargo/code-samples.md:24 +msgid "" +"Most code samples are editable like shown above. A few code samples\n" +"are not editable for various reasons:" +msgstr "" +"La plupart des exemples de code sont modifiables comme indiqué ci-dessus. Quelques exemples de code\n" +"ne sont pas modifiables pour diverses raisons :" + +#: src/cargo/code-samples.md:27 +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" +"\n" +"* The embedded playgrounds lose their state the moment you navigate\n" +" away from the page! This is the reason that the students should\n" +" solve the exercises using a local Rust installation or via the\n" +" Playground." +msgstr "" +"* Les terrains de jeu intégrés ne peuvent pas exécuter de tests unitaires. Copiez-collez le\n" +" code et ouvrez-le dans le vrai terrain de jeu pour démontrer les tests unitaires.\n" +"\n" +"* Les terrains de jeux intégrées perdent leur état au moment où vous naviguez\n" +" loin de la page! C'est la raison pour laquelle les élèves doivent\n" +" résoudre les exercices en utilisant une installation Rust locale ou via le\n" +" terrain de jeu." + +#: src/cargo/running-locally.md:1 +msgid "# Running Code Locally with Cargo" +msgstr "# Exécuter le code localement avec Cargo" + +#: src/cargo/running-locally.md:3 +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 "" +"Si vous souhaitez expérimenter le code sur votre propre système, vous aurez besoin\n" +"pour installer d'abord de Rust. Pour ce faire, suivez les [instructions dans le livre Rust][1].\n" +"Cela devrait vous donner un \"rustc\" et un \"cargo\" fonctionnels. Au moment de\n" +"l'écriture, la dernière version stable de Rust a ces numéros de version:" + +#: src/cargo/running-locally.md:8 +msgid "" +"```shell\n" +"% rustc --version\n" +"rustc 1.61.0 (fe5b13d68 2022-05-18)\n" +"% cargo --version\n" +"cargo 1.61.0 (a028ae4 2022-04-29)\n" +"```" +msgstr "" + +#: src/cargo/running-locally.md:15 +msgid "" +"With this is in place, then follow these steps to build a Rust binary from one\n" +"of the examples in this training:" +msgstr "" +"Une fois cela en place, suivez ces étapes pour créer un binaire Rust à partir d'un\n" +"des exemples dans cette formation :" + +#: src/cargo/running-locally.md:18 +msgid "" +"1. Click the \"Copy to clipboard\" button on the example you want to copy.\n" +"\n" +"2. Use `cargo new exercise` to create a new `exercise/` directory for your code:\n" +"\n" +" ```shell\n" +" $ cargo new exercise\n" +" Created binary (application) `exercise` package\n" +" ```\n" +"\n" +"3. Navigate into `exercise/` and use `cargo run` to build and run your binary:\n" +"\n" +" ```shell\n" +" $ cd exercise\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +" Running `target/debug/exercise`\n" +" Hello, world!\n" +" ```\n" +"\n" +"4. Replace the boiler-plate code in `src/main.rs` with your own code. For\n" +" example, using the example on the previous page, make `src/main.rs` look like\n" +"\n" +" ```rust\n" +" fn main() {\n" +" println!(\"Edit me!\");\n" +" }\n" +" ```\n" +"\n" +"5. Use `cargo run` to build and run your updated binary:\n" +"\n" +" ```shell\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +" Running `target/debug/exercise`\n" +" Edit me!\n" +" ```\n" +"\n" +"6. Use `cargo check` to quickly check your project for errors, use `cargo build`\n" +" to compile it without running it. You will find the output in `target/debug/`\n" +" for a normal debug build. Use `cargo build --release` to produce an optimized\n" +" release build in `target/release/`.\n" +"\n" +"7. You can add dependencies for your project by editing `Cargo.toml`. When you\n" +" run `cargo` commands, it will automatically download and compile missing\n" +" dependencies for you." +msgstr "" + +#: src/cargo/running-locally.md:70 +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 "" +"Essayez d'encourager les participants à installer Cargo et à utiliser un\n" +"éditeur local. Cela leur facilitera la vie puisqu'ils auront un\n" +"environnement de développement normal." + +#: src/welcome-day-1.md:1 +msgid "# Welcome to Day 1" +msgstr "# Bienvenue au jour 1" + +#: src/welcome-day-1.md:3 +msgid "" +"This is the first day of Comprehensive Rust. We will cover a lot of ground\n" +"today:" +msgstr "" +"C'est le premier jour de Comprehensive Rust(le guide complet de Rust). Nous couvrirons beaucoup de terrain\n" +"aujourd'hui:" + +#: src/welcome-day-1.md:6 +msgid "" +"* Basic Rust syntax: variables, scalar and compound types, enums, structs,\n" +" references, functions, and methods.\n" +"\n" +"* Memory management: stack vs heap, manual memory management, scope-based memory\n" +" management, and garbage collection.\n" +"\n" +"* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." +msgstr "" +"* Syntaxe de base de Rust : variables, types scalaires et composés, énumérations, structures,\n" +" références, fonctions et méthodes.\n" +"\n" +"* Gestion de la mémoire : pile contre tas, gestion manuelle de la mémoire, gestion de la mémoire basée sur la portée\n" +" et le ramassage des ordures.\n" +"\n" +"* Propriété : sémantique de déplacement, copie et clonage, emprunt et durée de vie." + +#: src/welcome-day-1.md:16 +msgid "Please remind the students that:" +msgstr "Veuillez rappeler aux élèves que :" + +#: src/welcome-day-1.md:18 +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" +"* 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 "" +"* Ils doivent poser des questions lorsqu'ils les reçoivent, ne les enregistrez pas jusqu'à la fin.\n" +"* Le cours se veut interactif et les discussions sont vivement encouragées !\n" +" * En tant qu'instructeur, vous devez essayer de garder les discussions pertinentes, c'est-à-dire,\n" +" garder le lien avec la façon dont Rust fait les choses par rapport à un autre langage. Ça peut être\n" +" difficile de trouver le bon équilibre, mais privilégiez les discussions\n" +" car elles engagent les gens bien plus que la communication à sens unique.\n" +"* Les questions signifieront probablement que nous parlons de choses avant les diapositives.\n" +" * C'est tout à fait correct! La répétition est une partie importante de l'apprentissage. N'oubliez pas\n" +" que les diapositives ne sont qu'un support et que vous êtes libre de les sauter si vous le souhaitez." + +#: src/welcome-day-1.md:29 +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 "" +"L'idée du premier jour est de montrer _juste assez_ de Rust pour pouvoir parler\n" +"du célèbre vérificateur d'emprunt. La façon dont Rust gère la mémoire est une caractéristique majeure\n" +"et nous devrions montrer cela aux élèves tout de suite." + +#: src/welcome-day-1.md:33 +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 "" +"Si vous enseignez cela dans une salle de classe, c'est un bon endroit pour passer en revue le\n" +"calendrier. Nous suggérons de diviser la journée en deux parties (suivant les diapositives) :" + +#: src/welcome-day-1.md:36 +msgid "" +"* Morning: 9:00 to 12:00,\n" +"* Afternoon: 13:00 to 16:00." +msgstr "" +"* Matin : 9h00 à 12h00,\n" +"* Après-midi : 13h00 à 16h00." + +#: src/welcome-day-1.md:39 +msgid "" +"You can of course adjust this as necessary. Please make sure to include breaks,\n" +"we recommend a break every hour!" +msgstr "" +"Vous pouvez bien sûr ajuster cela si nécessaire. Assurez-vous d'inclure les pauses,\n" +"nous recommandons une pause toutes les heures !" + +#: src/welcome-day-1/what-is-rust.md:1 +msgid "# What is Rust?" +msgstr "# Qu'est-ce que Rust?" + +#: src/welcome-day-1/what-is-rust.md:3 +msgid "Rust is a new programming language which had its [1.0 release in 2015][1]:" +msgstr "Rust est un nouveau langage de programmation qui a eu sa [version 1.0 en 2015][1] :" + +#: src/welcome-day-1/what-is-rust.md:5 +msgid "" +"* Rust is a statically compiled language in a similar role as C++\n" +" * `rustc` uses LLVM as its backend.\n" +"* Rust supports many [platforms and\n" +" architectures](https://doc.rust-lang.org/nightly/rustc/platform-support.html):\n" +" * x86, ARM, WebAssembly, ...\n" +" * Linux, Mac, Windows, ...\n" +"* Rust is used for a wide range of devices:\n" +" * firmware and boot loaders,\n" +" * smart displays,\n" +" * mobile phones,\n" +" * desktops,\n" +" * servers." +msgstr "" +"* Rust est un langage compilé statiquement dans un rôle similaire à C++\n" +" * `rustc` utilise LLVM comme backend.\n" +"* Rust prend en charge de nombreuses [plates-formes et\n" +" architectures](https://doc.rust-lang.org/nightly/rustc/platform-support.html):\n" +" * x86, ARM, WebAssembly, ...\n" +" *Linux, Mac, Windows, ...\n" +"* Rust est utilisé pour une large gamme d'appareils :\n" +" * firmware et chargeurs de démarrage,\n" +" * écrans intelligents,\n" +" * téléphones portables,\n" +" * ordinateurs de bureau,\n" +" * serveurs." + +#: src/welcome-day-1/what-is-rust.md:21 +msgid "Rust fits in the same area as C++:" +msgstr "Rust s'inscrit dans le même domaine que C++ :" + +#: src/welcome-day-1/what-is-rust.md:23 +msgid "" +"* High flexibility.\n" +"* High level of control.\n" +"* Can be scaled down to very constrained devices like mobile phones.\n" +"* Has no runtime or garbage collection.\n" +"* Focuses on reliability and safety without sacrificing performance." +msgstr "" +"* Grande flexibilité.\n" +"* Haut niveau de contrôle.\n" +"* Peut être réduit à des appareils très limités comme les téléphones mobiles.\n" +"* N'a pas de temps d'exécution ou de récupération d'ordures.\n" +"* Se concentre sur la fiabilité et la sécurité sans sacrifier les performances." + +#: src/hello-world.md:1 +#, fuzzy +msgid "# Hello World!" +msgstr "# Bonjour le monde!" + +#: src/hello-world.md:3 +msgid "" +"Let us jump into the simplest possible Rust program, a classic Hello World\n" +"program:" +msgstr "" +"Passons au programme Rust le plus simple possible, un Bonjour Monde classique\n" +"programme:" + +#: src/hello-world.md:6 +msgid "" +"```rust\n" +"fn main() {\n" +" println!(\"Hello 🌍!\");\n" +"}\n" +"```" +msgstr "" +"```rust\n" +"fn main() {\n" +" println!(\"Bonjour 🌍!\");\n" +"}\n" +"```" + +#: src/hello-world.md:12 +msgid "What you see:" +msgstr "Ce que tu vois:" + +#: src/hello-world.md:14 +msgid "" +"* Functions are introduced with `fn`.\n" +"* Blocks are delimited by curly braces like in C and C++.\n" +"* The `main` function is the entry point of the program.\n" +"* Rust has hygienic macros, `println!` is an example of this.\n" +"* Rust strings are UTF-8 encoded and can contain any Unicode character." +msgstr "" +"* Les fonctions sont introduites avec `fn`.\n" +"* Les blocs sont délimités par des accolades comme en C et C++.\n" +"* La fonction `main` est le point d'entrée du programme.\n" +"* Rust a des macros hygiéniques, `println!` en est un exemple.\n" +"* Les strings Rust sont encodées en UTF-8 et peuvent contenir n'importe quel caractère Unicode." + +#: src/hello-world.md:22 +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 "" +"Cette diapositive tente de mettre les étudiants à l'aise avec le code Rust. Ils en verront\n" +"une tonne durant les quatre prochains jours, alors nous commençons petit avec quelque chose de familier." + +#: src/hello-world.md:27 +msgid "" +"* Rust is very much like other languages in the C/C++/Java tradition. It is\n" +" imperative (not functional) and it doesn't try to reinvent things unless\n" +" absolutely necessary.\n" +"\n" +"* Rust is modern with full support for things like Unicode.\n" +"\n" +"* Rust uses macros for situations where you want to have a variable number of\n" +" arguments (no function [overloading](basic-syntax/functions-interlude.md)).\n" +"\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)." +msgstr "" +"* Rust ressemble beaucoup aux autres langages traditionnels C/C++/Java. C'est\n" +" impératif (non fonctionnel) et il n'essaie pas de réinventer les choses à moins\n" +" qu'absolument nécessaire.\n" +"\n" +"* Rust est moderne avec un support complet pour des choses comme Unicode.\n" +"\n" +"* Rust utilise des macros pour les situations où vous souhaitez avoir un nombre variable\n" +" d'arguments (pas de fonction [surchargées](basic-syntax/functions-interlude.md)).\n" +"\n" +"* Les macros étant \"hygiéniques\", elles ne capturent pas accidentellement les identifiants de\n" +" la portée dans laquelle elles sont utilisées. Les macros Rust ne sont en fait que\n" +" [partiellement hygiénique](https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene.html)." + +#: src/hello-world/small-example.md:1 +msgid "# Small Example" +msgstr "# Petit exemple" + +#: src/hello-world/small-example.md:3 +msgid "Here is a small example program in Rust:" +msgstr "Voici un petit exemple de programme en Rust :" + +#: src/hello-world/small-example.md:5 +msgid "" +"```rust,editable\n" +"fn main() { // Program entry point\n" +" let mut x: i32 = 6; // Mutable variable binding\n" +" print!(\"{x}\"); // Macro for printing, like printf\n" +" while x != 1 { // No parenthesis around expression\n" +" if x % 2 == 0 { // Math like in other languages\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +" print!(\" -> {x}\");\n" +" }\n" +" println!();\n" +"}\n" +"```" +msgstr "" +"```rust,editable\n" +"fn main() { // Entrée du programme\n" +" let mut x: i32 = 6; // Liaison mutable de variable\n" +" print!(\"{x}\"); // Macro pour impression, comme printf\n" +" while x != 1 { // Pas de parenthèses autour des expressions\n" +" if x % 2 == 0 { // Les mathématiques comme dans d'autre langages\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +" print!(\" -> {x}\");\n" +" }\n" +" println!();\n" +"}\n" +"```" + +#: src/hello-world/small-example.md:23 +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 "" +"Le code implémente la conjecture de Collatz : on pense que la boucle\n" +"finissent toujours, mais cela n'est pas encore prouvé. Modifiez le code et jouez avec différentes\n" +"entrées." + +#: src/hello-world/small-example.md:29 +msgid "" +"* Explain that all variables are statically typed. Try removing `i32` to trigger\n" +" type inference. Try with `i8` instead and trigger a runtime integer overflow.\n" +"\n" +"* Change `let mut x` to `let x`, discuss the compiler error.\n" +"\n" +"* Show how `print!` gives a compilation error if the arguments don't match the\n" +" format string.\n" +"\n" +"* Show how you need to use `{}` as a placeholder if you want to print an\n" +" expression which is more complex than just a single variable.\n" +"\n" +"* Show the students the standard library, show them how to search for `std::fmt`\n" +" 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 "" +"* Expliquez que toutes les variables sont typées statiquement. Essayez de supprimer `i32` pour déclencher\n" +" l'inférence de type. Essayez avec `i8` à la place et déclenchez un débordement d'entier à l'exécution.\n" +"\n" +"* Remplacez `let mut x` par `let x`, discutez de l'erreur du compilateur.\n" +"\n" +"* Montrez comment `print!` génère une erreur de compilation si les arguments ne correspondent pas aux\n" +" format des string.\n" +"\n" +"* Montrez comment vous devez utiliser `{}` comme espace réservé si vous souhaitez imprimer une\n" +" expression qui est plus complexe qu'une simple variable.\n" +"\n" +"* Montrez aux étudiants la bibliothèque standard, montrez-leur comment rechercher `std :: fmt`\n" +" qui a les règles du mini-langage de formatage. Il est important que le\n" +" les étudiants se familiarisent avec la recherche dans la bibliothèque standard." + +#: src/why-rust.md:1 +msgid "# Why Rust?" +msgstr "# Pourquoi Rust ?" + +#: src/why-rust.md:3 +msgid "Some unique selling points of Rust:" +msgstr "Quelques arguments de vente uniques à Rust :" + +#: src/why-rust.md:5 +msgid "" +"* Compile time memory safety.\n" +"* Lack of undefined runtime behavior.\n" +"* Modern language features." +msgstr "" +"* Sécurité de la mémoire à la compilation.\n" +"* Absence de comportement d'exécution indéfini.\n" +"* Caractéristiques du langage moderne." + +#: src/why-rust.md:11 +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 "" +"Assurez-vous de demander à la classe dans quelles langues ils ont de l'expérience. Selon\n" +"la réponse, vous pouvez mettre en évidence différentes fonctionnalités de Rust :" + +#: src/why-rust.md:14 +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" +" have the memory unsafety issues. In addition, you get a modern language with\n" +" constructs like pattern matching and built-in dependency management.\n" +"\n" +"* Experience with Java, Go, Python, JavaScript...: You get the same memory safety\n" +" as in those languages, plus a similar high-level language feeling. In addition\n" +" 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 "" +"* Expérience avec C ou C++ : Rust élimine toute une classe d'_erreurs d'exécution_\n" +" via le vérificateur d'emprunt. Vous obtenez des performances comme en C et C++, mais sans\n" +" problèmes d'insécurité de la mémoire. De plus, vous obtenez une langue moderne avec\n" +" des constructions telles que la correspondance de motifs et la gestion intégrée des dépendances.\n" +"\n" +"* Expérience avec Java, Go, Python, JavaScript... : Vous bénéficiez de la même sécurité mémoire\n" +" comme dans ces langages, plus un sentiment de langage de haut niveau similaire. En outre\n" +" vous obtenez des performances rapides et prévisibles comme C et C++ (pas de ramassage d'ordures)\n" +" ainsi que l'accès au matériel de bas niveau (si vous en avez besoin)" + +#: src/why-rust/compile-time.md:1 +msgid "# Compile Time Guarantees" +msgstr "# Garanties à la compilation" + +#: src/why-rust/compile-time.md:3 +msgid "Static memory management at compile time:" +msgstr "Gestion de la mémoire statique à la compilation :" + +#: src/why-rust/compile-time.md:5 +msgid "" +"* No uninitialized variables.\n" +"* No memory leaks (_mostly_, see notes).\n" +"* No double-frees.\n" +"* No use-after-free.\n" +"* No `NULL` pointers.\n" +"* No forgotten locked mutexes.\n" +"* No data races between threads.\n" +"* No iterator invalidation." +msgstr "" +"* Aucune variable non initialisée.\n" +"* Aucune fuite de mémoire (_surtout_, voir les notes).\n" +"* Pas de double libération de mémoire.\n" +"* Aucune utilisation après la libération.\n" +"* Pas de pointeurs `NULL`.\n" +"* Pas de mutex verrouillés oubliés.\n" +"* Pas de courses de données entre les threads.\n" +"* Aucune invalidation d'itérateur." + +#: src/why-rust/compile-time.md:16 +msgid "" +"It is possible to produce memory leaks in (safe) Rust. Some examples\n" +"are:" +msgstr "" +"Il est possible de produire des fuites de mémoire avec Rust (sûr). Quelques exemples\n" +"sont:" + +#: src/why-rust/compile-time.md:19 +msgid "" +"* You can for 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" +"* You can also accidentally create a [reference cycle] with `Rc` or\n" +" `Arc`.\n" +"* In fact, some will consider infinitely populating a collection a memory\n" +" leak and Rust does not protect from those." +msgstr "" +"* Vous pouvez utiliser [`Box::leak`] pour divulguer un pointeur. Une utilisation de cela pourrait\n" +" être d'obtenir des variables statiques initialisées et dimensionnées à l'exécution\n" +"* Vous pouvez utiliser [`std::mem::forget`] pour que le compilateur \"oublie\"\n" +" une valeur (ce qui signifie que le destructeur n'est jamais exécuté).\n" +"* Vous pouvez également créer accidentellement un [cycle de référence] avec `Rc` ou\n" +" \"Arc\".\n" +"* En fait, certains considéreront le fait de peupler à l'infini une collection tel qu'une\n" +" fuite de mémoire et Rust ne protège pas de celles-ci." + +#: src/why-rust/compile-time.md:28 +msgid "" +"For the purpose of this course, \"No memory leaks\" should be understood\n" +"as \"Pretty much no *accidental* memory leaks\"." +msgstr "" +"Pour les besoins de ce cours, \"Aucune fuite de mémoire\" doit être compris\n" +"comme \"Pratiquement pas de fuites de mémoire *accidentelles*\"." + +#: src/why-rust/runtime.md:1 +msgid "# Runtime Guarantees" +msgstr "# Garanties au temps d'exécution" + +#: src/why-rust/runtime.md:3 +#, fuzzy +msgid "No undefined behavior at runtime:" +msgstr "Aucun comportement indéfini à l'exécution :" + +#: src/why-rust/runtime.md:5 +#, fuzzy +msgid "" +"* Array access is bounds checked.\n" +"* Integer overflow is defined." +msgstr "" +"* L'accès au tableau est vérifié dans les limites.\n" +"* Le débordement d'entier est défini." + +#: 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" +" semantics. By default, you get panics in debug mode (`cargo build`)\n" +" and wrap-around in release mode (`cargo build --release`).\n" +"\n" +"* Bounds checking cannot be disabled with a compiler flag. It can also\n" +" not be disabled directly with the `unsafe` keyword. However,\n" +" `unsafe` allows you to call functions such as `slice::get_unchecked`\n" +" which does not do bounds checking." +msgstr "" +"* Le débordement d'entier est défini via un indicateur de compilation. Les options sont\n" +" soit une panique (un plantage contrôlé du programme) ou un bouclage\n" +" sémantique. Par défaut, vous obtenez des paniques en mode débogage (`cargo build`)\n" +" et bouclage en mode release (`cargo build --release`).\n" +"\n" +"* La vérification des limites ne peut pas être désactivée avec un indicateur de compilateur. Ça peut aussi\n" +" ne pas être désactivé directement avec le mot-clé `unsafe`. Cependant,\n" +" `unsafe` vous permet d'appeler des fonctions telles que `slice::get_unchecked`\n" +" qui ne vérifie pas les bornes." + +#: src/why-rust/modern.md:1 +#, fuzzy +msgid "# Modern Features" +msgstr "# Fonctionnalités modernes" + +#: src/why-rust/modern.md:3 +#, fuzzy +msgid "Rust is built with all the experience gained in the last 40 years." +msgstr "Rust est construit avec toute l'expérience acquise au cours des 40 dernières années." + +#: src/why-rust/modern.md:5 +#, fuzzy +msgid "## Language Features" +msgstr "## Caractéristiques linguistiques" + +#: src/why-rust/modern.md:7 +#, fuzzy +msgid "" +"* Enums and pattern matching.\n" +"* Generics.\n" +"* No overhead FFI.\n" +"* Zero-cost abstractions." +msgstr "" +"* Énumérations et correspondance de modèles.\n" +"* Génériques.\n" +"* Pas de frais généraux FFI.\n" +"* Abstractions à coût zéro." + +#: src/why-rust/modern.md:12 +#, fuzzy +msgid "## Tooling" +msgstr "## Outillage" + +#: 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 "" +"* Grandes erreurs de compilation.\n" +"* Gestionnaire de dépendances intégré.\n" +"* Support intégré pour les tests.\n" +"* Excellente prise en charge du protocole de serveur de langue." + +#: src/why-rust/modern.md:23 +#, fuzzy +msgid "" +"* Zero-cost abstractions, similar to C++, means that you don't have to 'pay'\n" +" for higher-level programming constructs with memory or CPU. For example,\n" +" writing a loop using `for` should result in roughly the same low level\n" +" instructions as using the `.iter().fold()` construct.\n" +"\n" +"* It may be worth mentioning that Rust enums are 'Algebraic Data Types', also\n" +" known as 'sum types', which allow the type system to express things like\n" +" `Option` and `Result`.\n" +"\n" +"* Remind people to read the errors --- many developers have gotten used to\n" +" ignore lengthy compiler output. The Rust compiler is significantly more\n" +" talkative than other compilers. It will often provide you with _actionable_\n" +" feedback, ready to copy-paste into your code.\n" +"\n" +"* The Rust standard library is small compared to languages like Java, Python,\n" +" and Go. Rust does not come with several things you might consider standard and\n" +" essential:\n" +"\n" +" * a random number generator, but see [rand].\n" +" * support for SSL or TLS, but see [rusttls].\n" +" * support for JSON, but see [serde_json].\n" +"\n" +" The reasoning behind this is that functionality in the standard library cannot\n" +" go away, so it has to be very stable. For the examples above, the Rust\n" +" community is still working on finding the best solution --- and perhaps there\n" +" isn't a single \"best solution\" for some of these things.\n" +"\n" +" Rust comes with a built-in package manager in the form of Cargo and this makes\n" +" it trivial to download and compile third-party crates. A consequence of this\n" +" is that the standard library can be smaller.\n" +"\n" +" Discovering good third-party crates can be a problem. Sites like\n" +" help with this by letting you compare health metrics for\n" +" crates to find a good and trusted one.\n" +" \n" +"* [rust-analyzer] is a well supported LSP implementation used in major\n" +" IDEs and text editors." +msgstr "" +"* Les abstractions à coût nul, similaires à C++, signifient que vous n'avez pas à \"payer\"\n" +" pour les constructions de programmation de niveau supérieur avec mémoire ou CPU. Par exemple,\n" +" écrire une boucle en utilisant `for` devrait aboutir à peu près au même niveau bas\n" +" instructions comme utilisant la construction `.iter().fold()`.\n" +"\n" +"* Il peut être utile de mentionner que les énumérations Rust sont des \"types de données algébriques\", également\n" +" connus sous le nom de \"types de somme\", qui permettent au système de type d'exprimer des choses comme\n" +" `Option` et `Résultat`.\n" +"\n" +"* Rappelez aux gens de lire les erreurs --- de nombreux développeurs se sont habitués à\n" +" ignorer la longue sortie du compilateur. Le compilateur Rust est beaucoup plus\n" +" bavard que les autres compilateurs. Il vous fournira souvent _actionnable_\n" +" feedback, prêt à copier-coller dans votre code.\n" +"\n" +"* La bibliothèque standard Rust est petite comparée à des langages comme Java, Python,\n" +" et aller. La rouille ne vient pas avec plusieurs choses que vous pourriez considérer comme standard et\n" +" essentiel:\n" +"\n" +" * un générateur de nombres aléatoires, mais voir [rand].\n" +" * prise en charge de SSL ou TLS, mais voir [rusttls].\n" +" * support pour JSON, mais voir [serde_json].\n" +"\n" +" Le raisonnement sous-jacent est que la fonctionnalité de la bibliothèque standard ne peut pas\n" +" s'en aller, il doit donc être très stable. Pour les exemples ci-dessus, le Rust\n" +" la communauté travaille toujours à trouver la meilleure solution --- et peut-être là\n" +" n'est pas une seule \"meilleure solution\" pour certaines de ces choses.\n" +"\n" +" Rust est livré avec un gestionnaire de packages intégré sous la forme de Cargo, ce qui rend\n" +" il est trivial de télécharger et de compiler des caisses tierces. Une conséquence de ce\n" +" est que la bibliothèque standard peut être plus petite.\n" +"\n" +" Découvrir de bonnes caisses tierces peut être un problème. Des sites comme\n" +" aide à cela en vous permettant de comparer les mesures de santé pour\n" +" caisses pour en trouver une bonne et de confiance.\n" +" \n" +"* [rust-analyzer] est une implémentation LSP bien prise en charge utilisée dans les principaux\n" +" IDE et éditeurs de texte." + +#: src/basic-syntax.md:1 +#, fuzzy +msgid "# Basic Syntax" +msgstr "# Syntaxe de base" + +#: src/basic-syntax.md:3 +#, fuzzy +msgid "Much of the Rust syntax will be familiar to you from C, C++ or Java:" +msgstr "Une grande partie de la syntaxe de Rust vous sera familière en C, C++ ou Java :" + +#: 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" +" */`.\n" +"* Keywords like `if` and `while` work the same.\n" +"* Variable assignment is done with `=`, comparison is done with `==`." +msgstr "" +"* Les blocs et les portées sont délimités par des accolades.\n" +"* Les commentaires de ligne commencent par `//`, les commentaires de bloc sont délimités par `/* ...\n" +" */`.\n" +"* Des mots-clés comme `if` et `while` fonctionnent de la même manière.\n" +"* L'affectation des variables se fait avec `=`, la comparaison se fait avec `==`." + +#: src/basic-syntax/scalar-types.md:1 +#, fuzzy +msgid "# Scalar Types" +msgstr "# Types scalaires" + +#: src/basic-syntax/scalar-types.md:3 +#, fuzzy +msgid "" +"| | Types | Literals |\n" +"|------------------------|--------------------------------------------|-------------------------------|\n" +"| Signed integers | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `-10`, `0`, `1_000`, `123i64` |\n" +"| Unsigned integers | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, `10u16` |\n" +"| Floating point numbers | `f32`, `f64` | `3.14`, `-10.0e20`, `2f32` |\n" +"| Strings | `&str` | `\"foo\"`, `r#\"\\\\\"#` |\n" +"| Unicode scalar values | `char` | `'a'`, `'α'`, `'∞'` |\n" +"| Byte strings | `&[u8]` | `b\"abc\"`, `br#\" \" \"#` |\n" +"| Booleans | `bool` | `true`, `false` |" +msgstr "" +"| | Types | Littéraux |\n" +"|-----------------------|------------------------ --------------------|-------------------------------------- --|\n" +"| Entiers signés | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `-10`, `0`, `1_000`, `123i64` |\n" +"| Entiers non signés | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, `10u16` |\n" +"| Nombres à virgule flottante | `f32`, `f64` | `3.14`, `-10.0e20`, `2f32` |\n" +"| Cordes | `&str` | `\"foo\"`, `r#\"\\\\\"#` |\n" +"| Valeurs scalaires Unicode | `car` | `'a'`, `'α'`, `'∞'` |\n" +"| Chaînes d'octets | `&[u8]` | `b\"abc\"`, `br#\" \" \"#` |\n" +"| Booléens | `bool` | 'vrai', 'faux' |" + +#: src/basic-syntax/scalar-types.md:13 +#, fuzzy +msgid "The types have widths as follows:" +msgstr "Les types ont des largeurs comme suit :" + +#: src/basic-syntax/scalar-types.md:15 +#, fuzzy +msgid "" +"* `iN`, `uN`, and `fN` are _N_ bits wide,\n" +"* `isize` and `usize` are the width of a pointer,\n" +"* `char` is 32 bit wide,\n" +"* `bool` is 8 bit wide." +msgstr "" +"* `iN`, `uN` et `fN` ont une largeur de _N_ bits,\n" +"* `isize` et `usize` sont la largeur d'un pointeur,\n" +"* `char` a une largeur de 32 bits,\n" +"* `bool` a une largeur de 8 bits." + +#: src/basic-syntax/compound-types.md:1 +#, fuzzy +msgid "# Compound Types" +msgstr "# Types de composés" + +#: src/basic-syntax/compound-types.md:3 +msgid "" +"| | Types | Literals |\n" +"|--------|-------------------------------|-----------------------------------|\n" +"| Arrays | `[T; N]` | `[20, 30, 40]`, `[0; 3]` |\n" +"| Tuples | `()`, `(T,)`, `(T1, T2)`, ... | `()`, `('x',)`, `('x', 1.2)`, ... |" +msgstr "" + +#: src/basic-syntax/compound-types.md:8 +#, fuzzy +msgid "Array assignment and access:" +msgstr "Affectation et accès aux baies :" + +#: src/basic-syntax/compound-types.md:10 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut a: [i8; 10] = [42; 10];\n" +" a[5] = 0;\n" +" println!(\"a: {:?}\", a);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/compound-types.md:18 +#, fuzzy +msgid "Tuple assignment and access:" +msgstr "Affectation et accès aux tuples :" + +#: src/basic-syntax/compound-types.md:20 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let t: (i8, bool) = (7, true);\n" +" println!(\"1st index: {}\", t.0);\n" +" println!(\"2nd index: {}\", t.1);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/compound-types.md:32 +#, fuzzy +msgid "Arrays:" +msgstr "Tableaux :" + +#: src/basic-syntax/compound-types.md:34 +msgid "" +"* Arrays have elements of the same type, `T`, and length, `N`, which is a compile-time constant.\n" +" Note that the length of the array is *part of its type*, which means that `[u8; 3]` and\n" +" `[u8; 4]` are considered two different types.\n" +"\n" +"* We can use literals to assign values to arrays.\n" +"\n" +"* In the main function, the print statement asks for the debug implementation with the `?` format\n" +" parameter: `{}` gives the default output, `{:?}` gives the debug output. We\n" +" could also have used `{a}` and `{a:?}` without specifying the value after the\n" +" format string.\n" +"\n" +"* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read." +msgstr "" + +#: src/basic-syntax/compound-types.md:47 +#, fuzzy +msgid "Tuples:" +msgstr "Tuples :" + +#: src/basic-syntax/compound-types.md:49 +#, fuzzy +msgid "" +"* Like arrays, tuples have a fixed length.\n" +"\n" +"* Tuples group together values of different types into a compound type.\n" +"\n" +"* Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`.\n" +"\n" +"* The empty tuple `()` is also known as the \"unit type\". It is both a type, and\n" +" the only valid value of that type - that is to say both the type and its value\n" +" are expressed as `()`. It is used to indicate, for example, that a function or\n" +" expression has no return value, as we'll see in a future slide. \n" +" * You can think of it as `void` that can be familiar to you from other \n" +" programming languages." +msgstr "" +"* Comme les tableaux, les tuples ont une longueur fixe.\n" +"\n" +"* Les tuples regroupent des valeurs de différents types dans un type composé.\n" +"\n" +"* Les champs d'un tuple sont accessibles par le point et l'index de la valeur, par ex. `t.0`, `t.1`.\n" +"\n" +"* Le tuple vide `()` est également appelé \"type d'unité\". C'est à la fois un type et\n" +" la seule valeur valide de ce type - c'est-à-dire à la fois le type et sa valeur\n" +" sont exprimés par `()`. Il est utilisé pour indiquer, par exemple, qu'une fonction ou\n" +" expression n'a pas de valeur de retour, comme nous le verrons dans une prochaine diapositive.\n" +" * Vous pouvez le considérer comme un \"vide\" qui peut vous être familier d'autres\n" +" langages de programmation." + +#: src/basic-syntax/references.md:1 +#, fuzzy +msgid "# References" +msgstr "# Les références" + +#: src/basic-syntax/references.md:3 +#, fuzzy +msgid "Like C++, Rust has references:" +msgstr "Comme C++, Rust a des références :" + +#: src/basic-syntax/references.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x: i32 = 10;\n" +" let ref_x: &mut i32 = &mut x;\n" +" *ref_x = 20;\n" +" println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/references.md:14 +#, fuzzy +msgid "Some notes:" +msgstr "Quelques notes:" + +#: 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 "" +"* Nous devons déréférencer `ref_x` lors de son affectation, comme pour les pointeurs C et C++.\n" +"* Rust déréférencera automatiquement dans certains cas, en particulier lors de l'appel\n" +" méthodes (essayez `ref_x.count_ones()`).\n" +"* Les références déclarées comme \"mut\" peuvent être liées à différentes valeurs au cours de leur durée de vie." + +#: src/basic-syntax/references.md:21 +#, fuzzy +msgid "" +"
\n" +"Key points:" +msgstr "" +"\n" +"Points clés:" + +#: src/basic-syntax/references.md:24 +#, fuzzy +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 "" +"* Assurez-vous de noter la différence entre `let mut ref_x: &i32` et `let ref_x:\n" +" &mut i32`. Le premier représente une référence mutable qui peut être liée à\n" +" différentes valeurs, tandis que la seconde représente une référence à une valeur modifiable." + +#: src/basic-syntax/references-dangling.md:1 +#, fuzzy +msgid "# Dangling References" +msgstr "# Références pendantes" + +#: src/basic-syntax/references-dangling.md:3 +#, fuzzy +msgid "Rust will statically forbid dangling references:" +msgstr "Rust interdira statiquement les références pendantes :" + +#: src/basic-syntax/references-dangling.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let ref_x: &i32;\n" +" {\n" +" let x: i32 = 10;\n" +" ref_x = &x;\n" +" }\n" +" println!(\"ref_x: {ref_x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/references-dangling.md:16 +#, 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 "" +"* Une référence est dite \"emprunter\" la valeur à laquelle elle se réfère.\n" +"* Rust suit la durée de vie de toutes les références pour s'assurer qu'elles durent longtemps\n" +" assez.\n" +"* Nous parlerons davantage de l'emprunt lorsque nous arriverons à la propriété." + +#: src/basic-syntax/slices.md:1 +#, fuzzy +msgid "# Slices" +msgstr "# tranches" + +#: src/basic-syntax/slices.md:3 +#, fuzzy +msgid "A slice gives you a view into a larger collection:" +msgstr "Une tranche vous donne une vue dans une plus grande collection :" + +#: src/basic-syntax/slices.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" +" println!(\"a: {a:?}\");\n" +"\n" +" let s: &[i32] = &a[2..4];\n" +" println!(\"s: {s:?}\");\n" +"}\n" +"```" +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 "" +"* Les tranches empruntent des données au type en tranches.\n" +"* Question : Que se passe-t-il si vous modifiez `a[3]` ?" + +#: 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" +"* If the slice starts at index 0, Rust’s range syntax allows us to drop the starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are " +"identical.\n" +" \n" +"* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are identical.\n" +"\n" +"* To easily create a slice of the full array, we can therefore use `&a[..]`.\n" +"\n" +"* `s` is a reference to a slice of `i32`s. Notice that the type of `s` (`&[i32]`) no longer mentions the array length. This allows us to perform " +"computation on slices of different sizes.\n" +" \n" +"* Slices always borrow from another object. In this example, `a` has to remain 'alive' (in scope) for at least as long as our slice. \n" +" \n" +"* The question about modifying `a[3]` can spark an interesting discussion, but the answer is that for memory safety reasons\n" +" you cannot do it through `a` after you created a slice, but you can read the data from both `a` and `s` safely. \n" +" More details will be explained in the borrow checker section." +msgstr "" +"* Nous créons une tranche en empruntant `a` et en spécifiant les index de début et de fin entre parenthèses.\n" +"\n" +"* Si la tranche commence à l'index 0, la syntaxe de plage de Rust nous permet de supprimer l'index de départ, ce qui signifie que `&a[0..a.len()]` " +"et `&a[..a.len()]` sont identiques .\n" +" \n" +"* Il en va de même pour le dernier index, donc `&a[2..a.len()]` et `&a[2..]` sont identiques.\n" +"\n" +"* Pour créer facilement une tranche du tableau complet, on peut donc utiliser `&a[..]`.\n" +"\n" +"* `s` est une référence à une tranche de `i32`s. Notez que le type de `s` (`&[i32]`) ne mentionne plus la longueur du tableau. Cela nous permet " +"d'effectuer des calculs sur des tranches de tailles différentes.\n" +" \n" +"* Les tranches empruntent toujours à un autre objet. Dans cet exemple, \"a\" doit rester \"vivant\" (dans la portée) au moins aussi longtemps que " +"notre tranche.\n" +" \n" +"* La question sur la modification de `a[3]` peut susciter une discussion intéressante, mais la réponse est que pour des raisons de sécurité de la " +"mémoire\n" +" vous ne pouvez pas le faire via `a` après avoir créé une tranche, mais vous pouvez lire les données de `a` et `s` en toute sécurité.\n" +" Plus de détails seront expliqués dans la section Vérificateur d'emprunt." + +#: src/basic-syntax/string-slices.md:1 +#, fuzzy +msgid "# `String` vs `str`" +msgstr "# `Chaîne` vs `chaîne`" + +#: src/basic-syntax/string-slices.md:3 +#, fuzzy +msgid "We can now understand the two string types in Rust:" +msgstr "Nous pouvons maintenant comprendre les deux types de string avec Rust :" + +#: src/basic-syntax/string-slices.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: &str = \"World\";\n" +" println!(\"s1: {s1}\");\n" +"\n" +" let mut s2: String = String::from(\"Hello \");\n" +" println!(\"s2: {s2}\");\n" +" s2.push_str(s1);\n" +" println!(\"s2: {s2}\");\n" +" \n" +" let s3: &str = &s2[6..];\n" +" println!(\"s3: {s3}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/string-slices.md:20 +#, fuzzy +msgid "Rust terminology:" +msgstr "Terminologie de la rouille :" + +#: src/basic-syntax/string-slices.md:22 +#, fuzzy +msgid "" +"* `&str` an immutable reference to a string slice.\n" +"* `String` a mutable string buffer." +msgstr "" +"* `&str` une référence immuable à une tranche de chaîne.\n" +"* `String` un tampon de chaîne mutable." + +#: src/basic-syntax/string-slices.md:27 +msgid "" +"* `&str` introduces a string slice, which is an immutable reference to UTF-8 encoded string data \n" +" stored in a block of memory. String literals (`”Hello”`), are stored in the program’s binary.\n" +"\n" +"* Rust’s `String` type is a wrapper around a vector of bytes. As with a `Vec`, it is owned.\n" +" \n" +"* As with many other types `String::from()` creates a string from a string literal; `String::new()` \n" +" creates a new empty string, to which string data can be added using the `push()` and `push_str()` methods.\n" +"\n" +"* The `format!()` macro is a convenient way to generate an owned string from dynamic values. It \n" +" accepts the same format specification as `println!()`.\n" +" \n" +"* You can borrow `&str` slices from `String` via `&` and optionally range selection.\n" +" \n" +"* For C++ programmers: think of `&str` as `const char*` from C++, but the one that always points \n" +" to a valid string in memory. Rust `String` is a rough equivalent of `std::string` from C++ \n" +" (main difference: it can only contain UTF-8 encoded bytes and will never use a small-string optimization).\n" +" " +msgstr "" + +#: src/basic-syntax/functions.md:1 +#, fuzzy +msgid "# Functions" +msgstr "# Les fonctions" + +#: src/basic-syntax/functions.md:3 +#, fuzzy +msgid "A Rust version of the famous [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz) interview question:" +msgstr "Une version Rust de la célèbre question d'entrevue [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz) :" + +#: src/basic-syntax/functions.md:5 +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 "" + +#: src/basic-syntax/functions.md:35 +msgid "" +"* We refer in `main` to a function written below. Neither forward declarations nor headers are necessary. \n" +"* Declaration parameters are followed by a type (the reverse of some programming languages), then a return type.\n" +"* The last expression in a function body (or any block) becomes the return value. Simply omit the `;` 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" +" " +msgstr "" + +#: src/basic-syntax/rustdoc.md:1 +#, fuzzy +msgid "# Rustdoc" +msgstr "# Rustdoc" + +#: src/basic-syntax/rustdoc.md:3 +#, fuzzy +msgid "All language items in Rust can be documented using special `///` syntax." +msgstr "Tous les éléments de langage de Rust peuvent être documentés à l'aide de la syntaxe spéciale `///`." + +#: src/basic-syntax/rustdoc.md:5 +msgid "" +"```rust,editable\n" +"/// Determine whether the first argument is divisible by the second argument.\n" +"///\n" +"/// If the second argument is zero, the result is false.\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" +"```" +msgstr "" + +#: src/basic-syntax/rustdoc.md:17 +#, fuzzy +msgid "" +"The contents are treated as Markdown. All published Rust library crates are\n" +"automatically documented at [`docs.rs`](https://docs.rs) using the\n" +"[rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It is\n" +"idiomatic to document all public items in an API using this pattern." +msgstr "" +"Le contenu est traité comme Markdown. Toutes les caisses de bibliothèque Rust publiées sont\n" +"automatiquement documenté sur [`docs.rs`](https://docs.rs) en utilisant le\n" +"[rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html). C'est\n" +"idiomatic pour documenter tous les éléments publics dans une API utilisant ce modèle." + +#: src/basic-syntax/rustdoc.md:24 +#, fuzzy +msgid "" +"* Show students the generated docs for the `rand` crate at\n" +" [`docs.rs/rand`](https://docs.rs/rand).\n" +"\n" +"* This course does not include rustdoc on slides, just to save space, but in\n" +" real code they should be present.\n" +"\n" +"* Inner doc comments are discussed later (in the page on modules) and need not\n" +" be addressed here." +msgstr "" +"* Montrez aux élèves les documents générés pour la caisse \"rand\" sur\n" +" [`docs.rs/rand`](https://docs.rs/rand).\n" +"\n" +"* Ce cours n'inclut pas rustdoc sur les diapositives, juste pour économiser de l'espace, mais dans\n" +" code réel, ils doivent être présents.\n" +"\n" +"* Les commentaires de la documentation interne sont discutés plus tard (dans la page sur les modules) et n'ont pas besoin\n" +" être abordé ici." + +#: src/basic-syntax/methods.md:1 src/methods.md:1 +#, fuzzy +msgid "# Methods" +msgstr "# Méthodes" + +#: 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:" +msgstr "" +"Rust a des méthodes, ce sont simplement des fonctions qui sont associées à un type particulier. Le\n" +"le premier argument d'une méthode est une instance du type auquel elle est associée :" + +#: src/basic-syntax/methods.md:6 +msgid "" +"```rust,editable\n" +"struct Rectangle {\n" +" width: u32,\n" +" height: u32,\n" +"}\n" +"\n" +"impl Rectangle {\n" +" fn area(&self) -> u32 {\n" +" self.width * self.height\n" +" }\n" +"\n" +" fn inc_width(&mut self, delta: u32) {\n" +" self.width += delta;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut rect = Rectangle { width: 10, height: 5 };\n" +" println!(\"old area: {}\", rect.area());\n" +" rect.inc_width(5);\n" +" println!(\"new area: {}\", rect.area());\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/methods.md:30 +#, fuzzy +msgid "* We will look much more at methods in today's exercise and in tomorrow's class." +msgstr "* Nous nous pencherons beaucoup plus sur les méthodes dans l'exercice d'aujourd'hui et dans le cours de demain." + +#: src/basic-syntax/functions-interlude.md:1 +#, fuzzy +msgid "# Function Overloading" +msgstr "# Surcharge de fonction" + +#: src/basic-syntax/functions-interlude.md:3 +#, fuzzy +msgid "Overloading is not supported:" +msgstr "La surcharge n'est pas prise en charge :" + +#: src/basic-syntax/functions-interlude.md:5 +#, fuzzy +msgid "" +"* Each function has a single implementation:\n" +" * Always takes a fixed number of parameters.\n" +" * Always takes a single set of parameter types.\n" +"* Default values are not supported:\n" +" * All call sites have the same number of arguments.\n" +" * Macros are sometimes used as an alternative." +msgstr "" +"* Chaque fonction a une seule implémentation :\n" +" * Prend toujours un nombre fixe de paramètres.\n" +" * Prend toujours un seul ensemble de types de paramètres.\n" +"* Les valeurs par défaut ne sont pas prises en charge :\n" +" * Tous les sites d'appel ont le même nombre d'arguments.\n" +" * Les macros sont parfois utilisées comme alternative." + +#: src/basic-syntax/functions-interlude.md:12 +#, fuzzy +msgid "However, function parameters can be generic:" +msgstr "Cependant, les paramètres de fonction peuvent être génériques :" + +#: src/basic-syntax/functions-interlude.md:14 +msgid "" +"```rust,editable\n" +"fn pick_one(a: T, b: T) -> T {\n" +" if std::process::id() % 2 == 0 { a } else { b }\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"coin toss: {}\", pick_one(\"heads\", \"tails\"));\n" +" println!(\"cash prize: {}\", pick_one(500, 1000));\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/functions-interlude.md:27 +#, fuzzy +msgid "" +"* When using generics, the standard library's `Into` can provide a kind of limited\n" +" polymorphism on argument types. We will see more details in a later section." +msgstr "" +"* Lors de l'utilisation de génériques, la bibliothèque standard `Into` peut fournir une sorte de\n" +" polymorphisme sur les types d'arguments. Nous verrons plus de détails dans une section ultérieure." + +#: src/basic-syntax/functions-interlude.md:30 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/day-1/morning.md:1 +#, fuzzy +msgid "# Day 1: Morning Exercises" +msgstr "# Jour 1 : Exercices du matin" + +#: src/exercises/day-1/morning.md:3 +#, fuzzy +msgid "In these exercises, we will explore two parts of Rust:" +msgstr "Dans ces exercices, nous allons explorer deux parties de Rust :" + +#: src/exercises/day-1/morning.md:5 +#, fuzzy +msgid "" +"* Implicit conversions between types.\n" +"\n" +"* Arrays and `for` loops." +msgstr "" +"* Conversions implicites entre les types.\n" +"\n" +"* Tableaux et boucles \"for\"." + +#: src/exercises/day-1/morning.md:11 +#, fuzzy +msgid "A few things to consider while solving the exercises:" +msgstr "Quelques points à considérer lors de la résolution des exercices :" + +#: src/exercises/day-1/morning.md:13 +#, fuzzy +msgid "" +"* Use a local Rust installation, if possible. This way you can get\n" +" auto-completion in your editor. See the page about [Using Cargo] for details\n" +" on installing Rust.\n" +"\n" +"* Alternatively, use the Rust Playground." +msgstr "" +"* Utilisez une installation Rust locale, si possible. De cette façon, vous pouvez obtenir\n" +" auto-complétion dans votre éditeur. Voir la page sur [Utiliser Cargo] pour plus de détails\n" +" lors de l'installation de Rust.\n" +"\n" +"* Vous pouvez également utiliser le Rust Playground." + +#: src/exercises/day-1/morning.md:19 +#, fuzzy +msgid "" +"The code snippets are not editable on purpose: the inline code snippets lose\n" +"their state if you navigate away from the page." +msgstr "" +"Les extraits de code ne sont pas modifiables à dessein : les extraits de code en ligne perdent\n" +"leur état si vous quittez la page." + +#: 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 +#, fuzzy +msgid "After looking at the exercises, you can look at the [solutions] provided." +msgstr "Après avoir regardé les exercices, vous pouvez regarder les [solutions] fournies." + +#: src/exercises/day-1/implicit-conversions.md:1 +#, fuzzy +msgid "# Implicit Conversions" +msgstr "# Conversions implicites" + +#: src/exercises/day-1/implicit-conversions.md:3 +#, fuzzy +msgid "" +"Rust will not automatically apply _implicit conversions_ between types ([unlike\n" +"C++][3]). You can see this in a program like this:" +msgstr "" +"Rust n'appliquera pas automatiquement les _conversions implicites_ entre les types ([contrairement à\n" +"C++][3]). Vous pouvez le voir dans un programme comme celui-ci :" + +#: src/exercises/day-1/implicit-conversions.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"fn multiply(x: i16, y: i16) -> i16 {\n" +" x * y\n" +"}\n" +"\n" +"fn main() {\n" +" let x: i8 = 15;\n" +" let y: i16 = 1000;\n" +"\n" +" println!(\"{x} * {y} = {}\", multiply(x, y));\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/implicit-conversions.md:19 +#, fuzzy +msgid "" +"The Rust integer types all implement the [`From`][1] and [`Into`][2]\n" +"traits to let us convert between them. The `From` trait has a single `from()`\n" +"method and similarly, the `Into` trait has a single `into()` method.\n" +"Implementing these traits is how a type expresses that it can be converted into\n" +"another type." +msgstr "" +"Les types entiers Rust implémentent tous les [`From`][1] et [`Into`][2]\n" +"traits pour nous permettre de convertir entre eux. Le trait `From` a un seul `from()`\n" +"et de même, le trait `Into` a une seule méthode `into()`.\n" +"La mise en œuvre de ces traits est la façon dont un type exprime qu'il peut être converti en\n" +"un autre type." + +#: src/exercises/day-1/implicit-conversions.md:25 +#, fuzzy +msgid "" +"The standard library has an implementation of `From for i16`, which means\n" +"that we can convert a variable `x` of type `i8` to an `i16` by calling \n" +"`i16::from(x)`. Or, simpler, with `x.into()`, because `From for i16`\n" +"implementation automatically create an implementation of `Into for i8`." +msgstr "" +"La bibliothèque standard a une implémentation de `From for i16`, ce qui signifie\n" +"que nous pouvons convertir une variable `x` de type `i8` en un `i16` en appelant\n" +"`i16::from(x)`. Ou, plus simple, avec `x.into()`, car `From for i16`\n" +"créer automatiquement une implémentation de `Into for i8`." + +#: src/exercises/day-1/implicit-conversions.md:30 +#, fuzzy +msgid "" +"The same applies for your own `From` implementations for your own types, so it is\n" +"sufficient to only implement `From` to get a respective `Into` implementation automatically." +msgstr "" +"Il en va de même pour vos propres implémentations `From` pour vos propres types, il est donc\n" +"suffisant pour implémenter uniquement `From` pour obtenir automatiquement une implémentation `Into` respective." + +#: src/exercises/day-1/implicit-conversions.md:33 +#, fuzzy +msgid "" +"1. Execute the above program and look at the compiler error.\n" +"\n" +"2. Update the code above to use `into()` to do the conversion.\n" +"\n" +"3. Change the types of `x` and `y` to other things (such as `f32`, `bool`,\n" +" `i128`) to see which types you can convert to which other types. Try\n" +" converting small types to big types and the other way around. Check the\n" +" [standard library documentation][1] to see if `From` is implemented for\n" +" the pairs you check." +msgstr "" +"1. Exécutez le programme ci-dessus et examinez l'erreur du compilateur.\n" +"\n" +"2. Mettez à jour le code ci-dessus pour utiliser `into()` pour effectuer la conversion.\n" +"\n" +"3. Remplacez les types de `x` et `y` par d'autres éléments (tels que `f32`, `bool`,\n" +" `i128`) pour voir quels types vous pouvez convertir vers quels autres types. Essayer\n" +" convertir de petits types en grands types et inversement. Vérifier la\n" +" [documentation de la bibliothèque standard][1] pour voir si `From` est implémenté pour\n" +" les paires que vous cochez." + +#: src/exercises/day-1/for-loops.md:1 +#, fuzzy +msgid "# Arrays and `for` Loops" +msgstr "# Tableaux et boucles `for`" + +#: src/exercises/day-1/for-loops.md:3 +#, fuzzy +msgid "We saw that an array can be declared like this:" +msgstr "Nous avons vu qu'un tableau peut être déclaré comme ceci :" + +#: src/exercises/day-1/for-loops.md:5 +msgid "" +"```rust\n" +"let array = [10, 20, 30];\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:9 +#, fuzzy +msgid "You can print such an array by asking for its debug representation with `{:?}`:" +msgstr "Vous pouvez imprimer un tel tableau en demandant sa représentation de débogage avec `{:?}` :" + +#: src/exercises/day-1/for-loops.md:11 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" println!(\"array: {array:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:18 +#, fuzzy +msgid "" +"Rust lets you iterate over things like arrays and ranges using the `for`\n" +"keyword:" +msgstr "" +"Rust vous permet d'itérer sur des choses comme des tableaux et des plages en utilisant le `for`\n" +"mot-clé:" + +#: src/exercises/day-1/for-loops.md:21 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" print!(\"Iterating over array:\");\n" +" for n in array {\n" +" print!(\" {n}\");\n" +" }\n" +" println!();\n" +"\n" +" print!(\"Iterating over range:\");\n" +" for i in 0..3 {\n" +" print!(\" {}\", array[i]);\n" +" }\n" +" println!();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:38 +#, fuzzy +msgid "" +"Use the above to write a function `pretty_print` which pretty-print a matrix and\n" +"a function `transpose` which will transpose a matrix (turn rows into columns):" +msgstr "" +"Utilisez ce qui précède pour écrire une fonction `pretty_print` qui imprime joliment une matrice et\n" +"une fonction `transpose` qui va transposer une matrice (transformer les lignes en colonnes):" + +#: src/exercises/day-1/for-loops.md:41 +msgid "" +"```bob\n" +" ⎛⎡1 2 3⎤⎞ ⎡1 4 7⎤\n" +"\"transpose\"⎜⎢4 5 6⎥⎟ \"==\"⎢2 5 8⎥\n" +" ⎝⎣7 8 9⎦⎠ ⎣3 6 9⎦\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:47 +#, fuzzy +msgid "Hard-code both functions to operate on 3 × 3 matrices." +msgstr "Codez en dur les deux fonctions pour qu'elles fonctionnent sur des matrices 3 × 3." + +#: src/exercises/day-1/for-loops.md:49 +#, fuzzy +msgid "" +"Copy the code below to and implement the\n" +"functions:" +msgstr "" +"Copiez le code ci-dessous sur et implémentez le\n" +"les fonctions:" + +#: src/exercises/day-1/for-loops.md:52 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" unimplemented!()\n" +"}\n" +"\n" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" unimplemented!()\n" +"}\n" +"\n" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:80 +#, fuzzy +msgid "## Bonus Question" +msgstr "## Question bonus" + +#: src/exercises/day-1/for-loops.md:82 +#, fuzzy +msgid "" +"Could you use `&[i32]` slices instead of hard-coded 3 × 3 matrices for your\n" +"argument and return types? Something like `&[&[i32]]` for a two-dimensional\n" +"slice-of-slices. Why or why not?" +msgstr "" +"Pourriez-vous utiliser des tranches `&[i32]` au lieu de matrices 3 × 3 codées en dur pour votre\n" +"types d'argument et de retour ? Quelque chose comme `&[&[i32]]` pour un fichier bidimensionnel\n" +"tranche de tranches. Pourquoi ou pourquoi pas?" + +#: src/exercises/day-1/for-loops.md:87 +#, fuzzy +msgid "" +"See the [`ndarray` crate](https://docs.rs/ndarray/) for a production quality\n" +"implementation." +msgstr "" +"Voir le [`ndarray` crate](https://docs.rs/ndarray/) pour une qualité de production\n" +"mise en œuvre." + +#: src/exercises/day-1/for-loops.md:92 +#, fuzzy +msgid "" +"The solution and the answer to the bonus section are available in the \n" +"[Solution](solutions-morning.md#arrays-and-for-loops) section." +msgstr "" +"La solution et la réponse à la section bonus sont disponibles dans le\n" +"Section [Solution](solutions-morning.md#arrays-and-for-loops)." + +#: src/basic-syntax/variables.md:1 +#, fuzzy +msgid "# Variables" +msgstr "#Variable" + +#: src/basic-syntax/variables.md:3 +#, fuzzy +msgid "" +"Rust provides type safety via static typing. Variable bindings are immutable by\n" +"default:" +msgstr "" +"Rust fournit une sécurité de type via le typage statique. Les liaisons variables sont immuables par\n" +"défaut:" + +#: src/basic-syntax/variables.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x: i32 = 10;\n" +" println!(\"x: {x}\");\n" +" // x = 20;\n" +" // println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/variables.md:17 +#, fuzzy +msgid "" +"* Due to type inference the `i32` is optional. We will gradually show the types less and less as the course progresses.\n" +"* Note that since `println!` is a macro, `x` is not moved, even using the function like syntax of `println!(\"x: {}\", x)`" +msgstr "" +"* En raison de l'inférence de type, le `i32` est facultatif. Nous montrerons progressivement les types de moins en moins au fur et à mesure que le " +"cours avance.\n" +"* Notez que puisque `println!` est une macro, `x` n'est pas déplacé, même en utilisant la fonction comme syntaxe de `println!(\"x: {}\", x)`" + +#: src/basic-syntax/type-inference.md:1 +#, fuzzy +msgid "# Type Inference" +msgstr "# Inférence de type" + +#: src/basic-syntax/type-inference.md:3 +#, fuzzy +msgid "Rust will look at how the variable is _used_ to determine the type:" +msgstr "Rust examinera comment la variable est _utilisée_ pour déterminer le type :" + +#: src/basic-syntax/type-inference.md:5 +msgid "" +"```rust,editable\n" +"fn takes_u32(x: u32) {\n" +" println!(\"u32: {x}\");\n" +"}\n" +"\n" +"fn takes_i8(y: i8) {\n" +" println!(\"i8: {y}\");\n" +"}\n" +"\n" +"fn main() {\n" +" let x = 10;\n" +" let y = 20;\n" +"\n" +" takes_u32(x);\n" +" takes_i8(y);\n" +" // takes_u32(y);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/type-inference.md:26 +#, fuzzy +msgid "This slide demonstrates how the Rust compiler infers types based on constraints given by variable declarations and usages." +msgstr "" +"Cette diapositive montre comment le compilateur Rust déduit les types en fonction des contraintes données par les déclarations et les utilisations " +"des variables." + +#: src/basic-syntax/type-inference.md:28 +#, fuzzy +msgid "" +"It is very important to emphasize that variables declared like this are not of some sort of dynamic \"any type\" that can\n" +"hold any data. The machine code generated by such declaration is identical to the explicit declaration of a type.\n" +"The compiler does the job for us and helps us write more concise code." +msgstr "" +"Il est très important de souligner que les variables déclarées de cette manière ne sont pas d'une sorte de \"tout type\" dynamique qui peut\n" +"détenir des données. Le code machine généré par une telle déclaration est identique à la déclaration explicite d'un type.\n" +"Le compilateur fait le travail pour nous et nous aide à écrire un code plus concis." + +#: src/basic-syntax/type-inference.md:32 +#, fuzzy +msgid "" +"The following code tells the compiler to copy into a certain generic container without the code ever explicitly specifying the contained type, using " +"`_` as a placeholder:" +msgstr "" +"Le code suivant indique au compilateur de copier dans un certain conteneur générique sans que le code ne spécifie jamais explicitement le type " +"contenu, en utilisant `_` comme espace réservé :" + +#: src/basic-syntax/type-inference.md:34 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut v = Vec::new();\n" +" v.push((10, false));\n" +" v.push((20, true));\n" +" println!(\"v: {v:?}\");\n" +"\n" +" let vv = v.iter().collect::>();\n" +" println!(\"vv: {vv:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/type-inference.md:46 +#, fuzzy +msgid "" +"[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.collect) relies on `FromIterator`, which [`HashSet`](https://doc." +"rust-lang.org/std/iter/trait.FromIterator.html) implements." +msgstr "" +"[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.collect) repose sur `FromIterator`, qui [`HashSet`](https:/ /doc." +"rust-lang.org/std/iter/trait.FromIterator.html) implémente." + +#: src/basic-syntax/static-and-const.md:1 +#, fuzzy +msgid "# Static and Constant Variables" +msgstr "# Variables statiques et constantes" + +#: src/basic-syntax/static-and-const.md:3 +#, fuzzy +msgid "Global state is managed with static and constant variables." +msgstr "L'état global est géré avec des variables statiques et constantes." + +#: src/basic-syntax/static-and-const.md:5 +#, fuzzy +msgid "## `const`" +msgstr "## `const`" + +#: src/basic-syntax/static-and-const.md:7 +#, fuzzy +msgid "You can declare compile-time constants:" +msgstr "Vous pouvez déclarer des constantes de compilation :" + +#: src/basic-syntax/static-and-const.md:9 +msgid "" +"```rust,editable\n" +"const DIGEST_SIZE: usize = 3;\n" +"const ZERO: Option = Some(42);\n" +"\n" +"fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {\n" +" let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];\n" +" for (idx, &b) in text.as_bytes().iter().enumerate() {\n" +" digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE].wrapping_add(b);\n" +" }\n" +" digest\n" +"}\n" +"\n" +"fn main() {\n" +" let digest = compute_digest(\"Hello\");\n" +" println!(\"Digest: {digest:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/static-and-const.md:27 +#, fuzzy +msgid "According the the [Rust RFC Book][1] these are inlined upon use." +msgstr "Selon le [Rust RFC Book] [1], ceux-ci sont intégrés lors de l'utilisation." + +#: src/basic-syntax/static-and-const.md:29 +#, fuzzy +msgid "## `static`" +msgstr "## `statique`" + +#: src/basic-syntax/static-and-const.md:31 +#, fuzzy +msgid "You can also declare static variables:" +msgstr "Vous pouvez également déclarer des variables statiques :" + +#: src/basic-syntax/static-and-const.md:33 +msgid "" +"```rust,editable\n" +"static BANNER: &str = \"Welcome to RustOS 3.14\";\n" +"\n" +"fn main() {\n" +" println!(\"{BANNER}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/static-and-const.md:41 +#, fuzzy +msgid "" +"As noted in the [Rust RFC Book][1], these are not inlined upon use and have an actual associated memory location. This is useful for unsafe and " +"embedded code, and the variable lives through the entirety of the program execution." +msgstr "" +"Comme indiqué dans le [Rust RFC Book] [1], ceux-ci ne sont pas alignés lors de l'utilisation et ont un emplacement de mémoire associé réel. Ceci est " +"utile pour le code non sécurisé et intégré, et la variable vit tout au long de l'exécution du programme." + +#: src/basic-syntax/static-and-const.md:44 +#, fuzzy +msgid "We will look at mutating static data in the [chapter on Unsafe Rust](../unsafe.md)." +msgstr "Nous examinerons la mutation des données statiques dans le [chapitre sur Unsafe Rust](../unsafe.md)." + +#: src/basic-syntax/static-and-const.md:48 +#, fuzzy +msgid "" +"* Mention that `const` behaves semantically similar to C++'s `constexpr`.\n" +"* `static`, on the other hand, is much more similar to a `const` or mutable global variable in C++.\n" +"* It isn't super common that one would need a runtime evaluated constant, but it is helpful and safer than using a static." +msgstr "" +"* Mentionnez que `const` se comporte sémantiquement de la même manière que `constexpr` de C++.\n" +"* `static`, d'autre part, ressemble beaucoup plus à une variable globale `const` ou mutable en C++.\n" +"* Il n'est pas très courant d'avoir besoin d'une constante évaluée à l'exécution, mais c'est utile et plus sûr que d'utiliser un statique." + +#: src/basic-syntax/scopes-shadowing.md:1 +#, fuzzy +msgid "# Scopes and Shadowing" +msgstr "# Portées et ombrage" + +#: src/basic-syntax/scopes-shadowing.md:3 +#, fuzzy +msgid "" +"You can shadow variables, both those from outer scopes and variables from the\n" +"same scope:" +msgstr "" +"Vous pouvez masquer des variables, à la fois celles des portées externes et celles des\n" +"même périmètre :" + +#: src/basic-syntax/scopes-shadowing.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a = 10;\n" +" println!(\"before: {a}\");\n" +"\n" +" {\n" +" let a = \"hello\";\n" +" println!(\"inner scope: {a}\");\n" +"\n" +" let a = true;\n" +" println!(\"shadowed in inner scope: {a}\");\n" +" }\n" +"\n" +" println!(\"after: {a}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:25 +#, fuzzy +msgid "" +"* Definition: Shadowing is different from mutation, because after shadowing both variable's memory locations exist at the same time. Both are " +"available under the same name, depending where you use it in the code. \n" +"* A shadowing variable can have a different type. \n" +"* Shadowing looks obscure at first, but is convenient for holding on to values after `.unwrap()`.\n" +"* The following code demonstrates why the compiler can't simply reuse memory locations when shadowing an immutable variable in a scope, even if the " +"type does not change." +msgstr "" +"* Définition : l'occultation est différente de la mutation, car après l'occultation, les emplacements de mémoire des deux variables existent en même " +"temps. Les deux sont disponibles sous le même nom, selon l'endroit où vous l'utilisez dans le code.\n" +"* Une variable d'occultation peut avoir un type différent.\n" +"* L'ombrage semble obscur au début, mais est pratique pour conserver les valeurs après `.unwrap()`.\n" +"* Le code suivant montre pourquoi le compilateur ne peut pas simplement réutiliser les emplacements de mémoire lors de l'observation d'une variable " +"immuable dans une portée, même si le type ne change pas." + +#: src/basic-syntax/scopes-shadowing.md:30 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a = 1;\n" +" let b = &a;\n" +" let a = a + 1;\n" +" println!(\"{a} {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management.md:1 +#, fuzzy +msgid "# Memory Management" +msgstr "# Gestion de la mémoire" + +#: src/memory-management.md:3 +#, fuzzy +msgid "Traditionally, languages have fallen into two broad categories:" +msgstr "Traditionnellement, les langues se répartissent en deux grandes catégories :" + +#: src/memory-management.md:5 +#, fuzzy +msgid "" +"* Full control via manual memory management: C, C++, Pascal, ...\n" +"* Full safety via automatic memory management at runtime: Java, Python, Go, Haskell, ..." +msgstr "" +"* Contrôle total via la gestion manuelle de la mémoire : C, C++, Pascal, ...\n" +"* Sécurité totale via la gestion automatique de la mémoire à l'exécution : Java, Python, Go, Haskell, ..." + +#: src/memory-management.md:8 +#, fuzzy +msgid "Rust offers a new mix:" +msgstr "Rust propose un nouveau mix :" + +#: src/memory-management.md:10 +#, fuzzy +msgid "" +"> Full control *and* safety via compile time enforcement of correct memory\n" +"> management." +msgstr "" +"> Contrôle total * et * sécurité via l'application du temps de compilation de la mémoire correcte\n" +"> gestion." + +#: src/memory-management.md:13 +#, fuzzy +msgid "It does this with an explicit ownership concept." +msgstr "Il le fait avec un concept de propriété explicite." + +#: src/memory-management.md:15 +#, fuzzy +msgid "First, let's refresh how memory management works." +msgstr "Tout d'abord, rafraîchissons le fonctionnement de la gestion de la mémoire." + +#: src/memory-management/stack-vs-heap.md:1 +#, fuzzy +msgid "# The Stack vs The Heap" +msgstr "# La pile contre le tas" + +#: src/memory-management/stack-vs-heap.md:3 +#, fuzzy +msgid "" +"* Stack: Continuous area of memory for local variables.\n" +" * Values have fixed sizes known at compile time.\n" +" * Extremely fast: just move a stack pointer.\n" +" * Easy to manage: follows function calls.\n" +" * Great memory locality.\n" +"\n" +"* Heap: Storage of values outside of function calls.\n" +" * Values have dynamic sizes determined at runtime.\n" +" * Slightly slower than the stack: some book-keeping needed.\n" +" * No guarantee of memory locality." +msgstr "" +"* Pile : Zone continue de mémoire pour les variables locales.\n" +" * Les valeurs ont des tailles fixes connues au moment de la compilation.\n" +" * Extrêmement rapide : il suffit de déplacer un pointeur de pile.\n" +" * Facile à gérer : suit les appels de fonction.\n" +" * Grande localité de mémoire.\n" +"\n" +"* Heap : Stockage de valeurs en dehors des appels de fonction.\n" +" * Les valeurs ont des tailles dynamiques déterminées au moment de l'exécution.\n" +" * Légèrement plus lent que la pile : une certaine comptabilité est nécessaire.\n" +" * Aucune garantie de localisation de la mémoire." + +#: src/memory-management/stack.md:1 +#, fuzzy +msgid "# Stack Memory" +msgstr "# Mémoire de pile" + +#: src/memory-management/stack.md:3 +#, fuzzy +msgid "" +"Creating a `String` puts fixed-sized data on the stack and dynamically sized\n" +"data on the heap:" +msgstr "" +"La création d'une \"chaîne\" place des données de taille fixe sur la pile et dimensionnées dynamiquement\n" +"données sur le tas :" + +#: src/memory-management/stack.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1 = String::from(\"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:12 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | e | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:28 +msgid "" +"* Mention that a `String` is backed by a `Vec`, so it has a capacity and length and can grow if mutable via reallocation on the heap.\n" +"\n" +"* If students ask about it, you can mention that the underlying memory is heap allocated using the [System Allocator] and custom allocators can be " +"implemented using the [Allocator API]\n" +"\n" +"* We can inspect the memory layout with `unsafe` code. However, you should point out that this is rightfully unsafe!\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could lead to\n" +" // undefined behavior.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +" }\n" +" }\n" +" ```" +msgstr "" + +#: src/memory-management/manual.md:1 +#, fuzzy +msgid "# Manual Memory Management" +msgstr "# Gestion manuelle de la mémoire" + +#: src/memory-management/manual.md:3 +#, fuzzy +msgid "You allocate and deallocate heap memory yourself." +msgstr "Vous allouez et désallouez vous-même la mémoire de tas." + +#: src/memory-management/manual.md:5 +#, fuzzy +msgid "If not done with care, this can lead to crashes, bugs, security vulnerabilities, and memory leaks." +msgstr "Si cela n'est pas fait avec soin, cela peut entraîner des plantages, des bogues, des failles de sécurité et des fuites de mémoire." + +#: src/memory-management/manual.md:7 +#, fuzzy +msgid "## C Example" +msgstr "## C Exemple" + +#: src/memory-management/manual.md:9 +#, fuzzy +msgid "You must call `free` on every pointer you allocate with `malloc`:" +msgstr "Vous devez appeler `free` sur chaque pointeur que vous allouez avec `malloc` :" + +#: src/memory-management/manual.md:11 +msgid "" +"```c\n" +"void foo(size_t n) {\n" +" int* int_array = (int*)malloc(n * sizeof(int));\n" +" //\n" +" // ... lots of code\n" +" //\n" +" free(int_array);\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/manual.md:21 +#, fuzzy +msgid "" +"Memory is leaked if the function returns early between `malloc` and `free`: the\n" +"pointer is lost and we cannot deallocate the memory." +msgstr "" +"La mémoire est perdue si la fonction revient tôt entre `malloc` et `free` : le\n" +"pointeur est perdu et nous ne pouvons pas désallouer la mémoire." + +#: src/memory-management/scope-based.md:1 +#, fuzzy +msgid "# Scope-Based Memory Management" +msgstr "# Gestion de la mémoire basée sur la portée" + +#: src/memory-management/scope-based.md:3 +#, fuzzy +msgid "Constructors and destructors let you hook into the lifetime of an object." +msgstr "Les constructeurs et les destructeurs vous permettent de vous connecter à la durée de vie d'un objet." + +#: src/memory-management/scope-based.md:5 +#, fuzzy +msgid "" +"By wrapping a pointer in an object, you can free memory when the object is\n" +"destroyed. The compiler guarantees that this happens, even if an exception is\n" +"raised." +msgstr "" +"En enveloppant un pointeur dans un objet, vous pouvez libérer de la mémoire lorsque l'objet est\n" +"détruit. Le compilateur garantit que cela se produit, même si une exception est\n" +"soulevé." + +#: src/memory-management/scope-based.md:9 +#, fuzzy +msgid "" +"This is often called _resource acquisition is initialization_ (RAII) and gives\n" +"you smart pointers." +msgstr "" +"Ceci est souvent appelé _l'acquisition de ressources est initialisée_ (RAII) et donne\n" +"vous pointeurs intelligents." + +#: src/memory-management/scope-based.md:12 +#, fuzzy +msgid "## C++ Example" +msgstr "## Exemple C++" + +#: src/memory-management/scope-based.md:14 +msgid "" +"```c++\n" +"void say_hello(std::unique_ptr person) {\n" +" std::cout << \"Hello \" << person->name << std::endl;\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/scope-based.md:20 +#, fuzzy +msgid "" +"* The `std::unique_ptr` object is allocated on the stack, and points to\n" +" memory allocated on the heap.\n" +"* At the end of `say_hello`, the `std::unique_ptr` destructor will run.\n" +"* The destructor frees the `Person` object it points to." +msgstr "" +"* L'objet `std::unique_ptr` est alloué sur la pile et pointe vers\n" +" mémoire allouée sur le tas.\n" +"* À la fin de `say_hello`, le destructeur `std::unique_ptr` s'exécutera.\n" +"* Le destructeur libère l'objet `Person` vers lequel il pointe." + +#: src/memory-management/scope-based.md:25 +#, fuzzy +msgid "Special move constructors are used when passing ownership to a function:" +msgstr "Des constructeurs de mouvement spéciaux sont utilisés lors du transfert de propriété à une fonction :" + +#: src/memory-management/scope-based.md:27 +msgid "" +"```c++\n" +"std::unique_ptr person = find_person(\"Carla\");\n" +"say_hello(std::move(person));\n" +"```" +msgstr "" + +#: src/memory-management/garbage-collection.md:1 +#, fuzzy +msgid "# Automatic Memory Management" +msgstr "# Gestion automatique de la mémoire" + +#: src/memory-management/garbage-collection.md:3 +#, fuzzy +msgid "" +"An alternative to manual and scope-based memory management is automatic memory\n" +"management:" +msgstr "" +"Une alternative à la gestion manuelle et basée sur la portée de la mémoire est la mémoire automatique\n" +"gestion:" + +#: src/memory-management/garbage-collection.md:6 +#, fuzzy +msgid "" +"* The programmer never allocates or deallocates memory explicitly.\n" +"* A garbage collector finds unused memory and deallocates it for the programmer." +msgstr "" +"* Le programmeur n'alloue ou ne libère jamais de mémoire explicitement.\n" +"* Un ramasse-miettes trouve la mémoire inutilisée et la libère pour le programmeur." + +#: src/memory-management/garbage-collection.md:9 +#, fuzzy +msgid "## Java Example" +msgstr "## Exemple Java" + +#: src/memory-management/garbage-collection.md:11 +#, fuzzy +msgid "The `person` object is not deallocated after `sayHello` returns:" +msgstr "L'objet `person` n'est pas désalloué après le retour de `sayHello` :" + +#: src/memory-management/garbage-collection.md:13 +msgid "" +"```java\n" +"void sayHello(Person person) {\n" +" System.out.println(\"Hello \" + person.getName());\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/rust.md:1 +#, fuzzy +msgid "# Memory Management in Rust" +msgstr "# Gestion de la mémoire avec Rust" + +#: src/memory-management/rust.md:3 +#, fuzzy +msgid "Memory management in Rust is a mix:" +msgstr "La gestion de la mémoire avec Rust est un mélange :" + +#: src/memory-management/rust.md:5 +#, fuzzy +msgid "" +"* Safe and correct like Java, but without a garbage collector.\n" +"* Depending on which abstraction (or combination of abstractions) you choose, can be a single unique pointer, reference counted, or atomically " +"reference counted.\n" +"* Scope-based like C++, but the compiler enforces full adherence.\n" +"* A Rust user can choose the right abstraction for the situation, some even have no cost at runtime like C." +msgstr "" +"* Sûr et correct comme Java, mais sans ramasse-miettes.\n" +"* Selon l'abstraction (ou la combinaison d'abstractions) que vous choisissez, il peut s'agir d'un seul pointeur unique, d'une référence comptée ou " +"d'une référence atomique comptée.\n" +"* Basé sur la portée comme C++, mais le compilateur applique une adhésion totale.\n" +"* Un utilisateur de Rust peut choisir la bonne abstraction pour la situation, certains n'ont même aucun coût à l'exécution comme C." + +#: src/memory-management/rust.md:10 +#, fuzzy +msgid "It achieves this by modeling _ownership_ explicitly." +msgstr "Il y parvient en modélisant explicitement _ownership_." + +#: src/memory-management/rust.md:14 +#, fuzzy +msgid "" +"* If asked how at this point, you can mention that in Rust this is usually handled by RAII wrapper types such as [Box], [Vec], [Rc], or [Arc]. These " +"encapsulate ownership and memory allocation via various means, and prevent the potential errors in C.\n" +"\n" +"* You may be asked about destructors here, the [Drop] trait is the Rust equivalent." +msgstr "" +"* Si on vous demande comment à ce stade, vous pouvez mentionner qu'avec Rust, cela est généralement géré par des types de wrapper RAII tels que " +"[Box], [Vec], [Rc] ou [Arc]. Ceux-ci encapsulent la propriété et l'allocation de mémoire par divers moyens et empêchent les erreurs potentielles " +"dans C.\n" +"\n" +"* Vous pouvez être interrogé sur les destructeurs ici, le trait [Drop] est l'équivalent de Rust." + +#: src/memory-management/comparison.md:1 +#, fuzzy +msgid "# Comparison" +msgstr "# Comparaison" + +#: src/memory-management/comparison.md:3 +#, fuzzy +msgid "Here is a rough comparison of the memory management techniques." +msgstr "Voici une comparaison approximative des techniques de gestion de la mémoire." + +#: src/memory-management/comparison.md:5 +#, fuzzy +msgid "## Pros of Different Memory Management Techniques" +msgstr "## Avantages des différentes techniques de gestion de la mémoire" + +#: src/memory-management/comparison.md:7 +#, fuzzy +msgid "" +"* Manual like C:\n" +" * No runtime overhead.\n" +"* Automatic like Java:\n" +" * Fully automatic.\n" +" * Safe and correct.\n" +"* Scope-based like C++:\n" +" * Partially automatic.\n" +" * No runtime overhead.\n" +"* Compiler-enforced scope-based like Rust:\n" +" * Enforced by compiler.\n" +" * No runtime overhead.\n" +" * Safe and correct." +msgstr "" +"* Manuel comme C :\n" +" * Aucune surcharge d'exécution.\n" +"* Automatique comme Java :\n" +" * Entièrement automatique.\n" +" * Sûr et correct.\n" +"* Basé sur la portée comme C++ :\n" +" * Partiellement automatique.\n" +" * Aucune surcharge d'exécution.\n" +"* Basé sur la portée imposée par le compilateur comme Rust :\n" +" * Appliqué par le compilateur.\n" +" * Aucune surcharge d'exécution.\n" +" * Sûr et correct." + +#: src/memory-management/comparison.md:20 +#, fuzzy +msgid "## Cons of Different Memory Management Techniques" +msgstr "## Inconvénients des différentes techniques de gestion de la mémoire" + +#: src/memory-management/comparison.md:22 +#, fuzzy +msgid "" +"* Manual like C:\n" +" * Use-after-free.\n" +" * Double-frees.\n" +" * Memory leaks.\n" +"* Automatic like Java:\n" +" * Garbage collection pauses.\n" +" * Destructor delays.\n" +"* Scope-based like C++:\n" +" * Complex, opt-in by programmer.\n" +" * Potential for use-after-free.\n" +"* Compiler-enforced and scope-based like Rust:\n" +" * Some upfront complexity.\n" +" * Can reject valid programs." +msgstr "" +"* Manuel comme C :\n" +" * Utiliser-après-libre.\n" +" * Double-gratuit.\n" +" * Fuites de mémoire.\n" +"* Automatique comme Java :\n" +" * La collecte des ordures s'arrête.\n" +" * Retards de destructeur.\n" +"* Basé sur la portée comme C++ :\n" +" * Complexe, opt-in par le programmeur.\n" +" * Potentiel d'utilisation-après-libre.\n" +"* Renforcé par le compilateur et basé sur la portée comme Rust :\n" +" * Une certaine complexité initiale.\n" +" * Peut rejeter les programmes valides." + +#: src/ownership.md:1 +#, fuzzy +msgid "# Ownership" +msgstr "# La possession" + +#: src/ownership.md:3 +#, fuzzy +msgid "" +"All variable bindings have a _scope_ where they are valid and it is an error to\n" +"use a variable outside its scope:" +msgstr "" +"Toutes les liaisons de variables ont un _scope_ où elles sont valides et c'est une erreur de\n" +"utiliser une variable en dehors de sa portée :" + +#: src/ownership.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" {\n" +" let p = Point(3, 4);\n" +" println!(\"x: {}\", p.0);\n" +" }\n" +" println!(\"y: {}\", p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership.md:18 +#, fuzzy +msgid "" +"* At the end of the scope, the variable is _dropped_ and the data is freed.\n" +"* A destructor can run here to free up resources.\n" +"* We say that the variable _owns_ the value." +msgstr "" +"* A la fin du scope, la variable est _dropped_ et les données sont libérées.\n" +"* Un destructeur peut s'exécuter ici pour libérer des ressources.\n" +"* On dit que la variable _possède_ la valeur." + +#: src/ownership/move-semantics.md:1 +#, fuzzy +msgid "# Move Semantics" +msgstr "# Déplacer la sémantique" + +#: src/ownership/move-semantics.md:3 +#, fuzzy +msgid "An assignment will transfer ownership between variables:" +msgstr "Une affectation transférera la propriété entre les variables :" + +#: src/ownership/move-semantics.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Hello!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/move-semantics.md:14 +#, fuzzy +msgid "" +"* The assignment of `s1` to `s2` transfers ownership.\n" +"* The data was _moved_ from `s1` and `s1` is no longer accessible.\n" +"* When `s1` goes out of scope, nothing happens: it has no ownership.\n" +"* When `s2` goes out of scope, the string data is freed.\n" +"* There is always _exactly_ one variable binding which owns a value." +msgstr "" +"* L'affectation de `s1` à `s2` transfère la propriété.\n" +"* Les données ont été _déplacées_ de `s1` et `s1` n'est plus accessible.\n" +"* Lorsque `s1` sort de la portée, rien ne se passe : il n'a pas de propriété.\n" +"* Lorsque `s2` sort de la portée, les données de la chaîne sont libérées.\n" +"* Il y a toujours _exactement_ une liaison de variable qui possède une valeur." + +#: src/ownership/move-semantics.md:22 +#, fuzzy +msgid "" +"* Mention that this is the opposite of the defaults in C++, which copies by value unless you use `std::move` (and the move constructor is " +"defined!).\n" +"\n" +"* In Rust, clones are explicit (by using `clone`)." +msgstr "" +"* Mentionnez que c'est l'opposé des valeurs par défaut en C++, qui copie par valeur à moins que vous n'utilisiez `std::move` (et que le constructeur " +"de déplacement soit défini !).\n" +"\n" +"* Dans Rust, les clones sont explicites (en utilisant `clone`)." + +#: src/ownership/moved-strings-rust.md:1 +#, fuzzy +msgid "# Moved Strings in Rust" +msgstr "# Chaînes déplacées dans Rust" + +#: src/ownership/moved-strings-rust.md:3 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Rust\");\n" +" let s2: String = s1;\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:10 +#, fuzzy +msgid "" +"* The heap data from `s1` is reused for `s2`.\n" +"* When `s1` goes out of scope, nothing happens (it has been moved from)." +msgstr "" +"* Les données de tas de `s1` sont réutilisées pour `s2`.\n" +"* Lorsque `s1` sort de la portée, rien ne se passe (il a été déplacé de)." + +#: src/ownership/moved-strings-rust.md:13 +#, fuzzy +msgid "Before move to `s2`:" +msgstr "Avant de passer à `s2` :" + +#: src/ownership/moved-strings-rust.md:15 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| R | u | s | t | :\n" +": | len | 4 | : : +----+----+----+----+ :\n" +": | capacity | 4 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - -'\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:30 +#, fuzzy +msgid "After move to `s2`:" +msgstr "Après le passage à `s2` :" + +#: src/ownership/moved-strings-rust.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 \"(inaccessible)\" : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" +": | len | 4 | : | : +----+----+----+----+ :\n" +": | capacity | 4 | : | : :\n" +": +-----------+-------+ : | : :\n" +": : | `- - - - - - - - - - - - - -'\n" +": s2 : |\n" +": +-----------+-------+ : |\n" +": | ptr | o---+---+--'\n" +": | len | 4 | :\n" +": | capacity | 4 | :\n" +": +-----------+-------+ :\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:1 +#, fuzzy +msgid "# Double Frees in Modern C++" +msgstr "# Double Frees en C++ moderne" + +#: src/ownership/double-free-modern-cpp.md:3 +#, fuzzy +msgid "Modern C++ solves this differently:" +msgstr "Le C++ moderne résout cela différemment :" + +#: src/ownership/double-free-modern-cpp.md:5 +msgid "" +"```c++\n" +"std::string s1 = \"Cpp\";\n" +"std::string s2 = s1; // Duplicate the data in s1.\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:10 +#, fuzzy +msgid "" +"* The heap data from `s1` is duplicated and `s2` gets its own independent copy.\n" +"* When `s1` and `s2` go out of scope, they each free their own memory." +msgstr "" +"* Les données de tas de `s1` sont dupliquées et `s2` obtient sa propre copie indépendante.\n" +"* Lorsque `s1` et `s2` sortent de la portée, ils libèrent chacun leur propre mémoire." + +#: src/ownership/double-free-modern-cpp.md:13 +#, fuzzy +msgid "Before copy-assignment:" +msgstr "Avant l'affectation de copie :" + +#: src/ownership/double-free-modern-cpp.md:16 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:30 +#, fuzzy +msgid "After copy-assignment:" +msgstr "Après l'affectation de copie :" + +#: src/ownership/double-free-modern-cpp.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : : :\n" +": s2 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+-----+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:1 +#, fuzzy +msgid "# Moves in Function Calls" +msgstr "# Déplacements dans les appels de fonction" + +#: src/ownership/moves-function-calls.md:3 +#, fuzzy +msgid "" +"When you pass a value to a function, the value is assigned to the function\n" +"parameter. This transfers ownership:" +msgstr "" +"Lorsque vous transmettez une valeur à une fonction, la valeur est affectée à la fonction\n" +"paramètre. Cela transfère la propriété :" + +#: src/ownership/moves-function-calls.md:6 +msgid "" +"```rust,editable\n" +"fn say_hello(name: String) {\n" +" println!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let name = String::from(\"Alice\");\n" +" say_hello(name);\n" +" // say_hello(name);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:20 +#, fuzzy +msgid "" +"* With the first call to `say_hello`, `main` gives up ownership of `name`. Afterwards, `name` cannot be used anymore within `main`.\n" +"* The heap memory allocated for `name` will be freed at the end of the `say_hello` function.\n" +"* `main` can retain ownership if it passes `name` as a reference (`&name`) and if `say_hello` accepts a reference as a parameter.\n" +"* Alternatively, `main` can pass a clone of `name` in the first call (`name.clone()`).\n" +"* Rust makes it harder than C++ to inadvertently create copies by making move semantics the default, and by forcing programmers to make clones " +"explicit." +msgstr "" +"* Avec le premier appel à `say_hello`, `main` abandonne la propriété de `name`. Ensuite, `name` ne peut plus être utilisé dans `main`.\n" +"* La mémoire de tas allouée pour `name` sera libérée à la fin de la fonction `say_hello`.\n" +"* `main` peut conserver la propriété s'il passe `name` comme référence (`&name`) et si `say_hello` accepte une référence comme paramètre.\n" +"* Alternativement, `main` peut passer un clone de `name` dans le premier appel (`name.clone()`).\n" +"* Rust rend plus difficile que C++ la création de copies par inadvertance en faisant de la sémantique de déplacement la valeur par défaut et en " +"forçant les programmeurs à rendre les clones explicites." + +#: src/ownership/copy-clone.md:1 +#, fuzzy +msgid "# Copying and Cloning" +msgstr "# Copie et clonage" + +#: src/ownership/copy-clone.md:3 +#, fuzzy +msgid "While move semantics are the default, certain types are copied by default:" +msgstr "Bien que la sémantique de déplacement soit la valeur par défaut, certains types sont copiés par défaut :" + +#: src/ownership/copy-clone.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = 42;\n" +" let y = x;\n" +" println!(\"x: {x}\");\n" +" println!(\"y: {y}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:14 +#, fuzzy +msgid "These types implement the `Copy` trait." +msgstr "Ces types implémentent le trait \"Copier\"." + +#: src/ownership/copy-clone.md:16 +#, fuzzy +msgid "You can opt-in your own types to use copy semantics:" +msgstr "Vous pouvez activer vos propres types pour utiliser la sémantique de copie :" + +#: src/ownership/copy-clone.md:18 +msgid "" +"```rust,editable\n" +"#[derive(Copy, Clone, Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = p1;\n" +" println!(\"p1: {p1:?}\");\n" +" println!(\"p2: {p2:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:30 +#, fuzzy +msgid "" +"* After the assignment, both `p1` and `p2` own their own data.\n" +"* We can also use `p1.clone()` to explicitly copy the data." +msgstr "" +"* Après l'affectation, `p1` et `p2` possèdent leurs propres données.\n" +"* Nous pouvons également utiliser `p1.clone()` pour copier explicitement les données." + +#: src/ownership/copy-clone.md:35 +#, fuzzy +msgid "Copying and cloning are not the same thing:" +msgstr "La copie et le clonage ne sont pas la même chose :" + +#: src/ownership/copy-clone.md:37 +#, fuzzy +msgid "" +"* Copying refers to bitwise copies of memory regions and does not work on arbitrary objects.\n" +"* Copying does not allow for custom logic (unlike copy constructors in C++).\n" +"* Cloning is a more general operation and also allows for custom behavior by implementing the `Clone` trait.\n" +"* Copying does not work on types that implement the `Drop` trait." +msgstr "" +"* La copie fait référence aux copies au niveau du bit des régions de mémoire et ne fonctionne pas sur des objets arbitraires.\n" +"* La copie ne permet pas de logique personnalisée (contrairement aux constructeurs de copie en C++).\n" +"* Le clonage est une opération plus générale et permet également un comportement personnalisé en implémentant le trait \"Cloner\".\n" +"* La copie ne fonctionne pas sur les types qui implémentent le trait `Drop`." + +#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 +#, fuzzy +msgid "In the above example, try the following:" +msgstr "Dans l'exemple ci-dessus, essayez ce qui suit :" + +#: src/ownership/copy-clone.md:44 +#, fuzzy +msgid "" +"* Add a `String` field to `struct Point`. It will not compile because `String` is not a `Copy` type.\n" +"* Remove `Copy` from the `derive` attribute. The compiler error is now in the `println!` for `p1`.\n" +"* Show that it works if you clone `p1` instead." +msgstr "" +"* Ajoutez un champ `String` à `struct Point`. Il ne sera pas compilé car `String` n'est pas un type `Copy`.\n" +"* Supprimer `Copy` de l'attribut `derive`. L'erreur du compilateur est maintenant dans `println!` pour `p1`.\n" +"* Montrez que cela fonctionne si vous clonez `p1` à la place." + +#: src/ownership/copy-clone.md:48 +#, fuzzy +msgid "" +"If students ask about `derive`, it is sufficient to say that this is a way to generate code in Rust\n" +"at compile time. In this case the default implementations of `Copy` and `Clone` traits are generated." +msgstr "" +"Si les étudiants posent des questions sur \"dériver\", il suffit de dire que c'est un moyen de générer du code dans Rust\n" +"au moment de la compilation. Dans ce cas, les implémentations par défaut des traits `Copy` et `Clone` sont générées." + +#: src/ownership/borrowing.md:1 +#, fuzzy +msgid "# Borrowing" +msgstr "# Emprunter" + +#: src/ownership/borrowing.md:3 +#, fuzzy +msgid "" +"Instead of transferring ownership when calling a function, you can let a\n" +"function _borrow_ the value:" +msgstr "" +"Au lieu de transférer la propriété lors de l'appel d'une fonction, vous pouvez laisser une\n" +"la fonction _emprunte_ la valeur :" + +#: src/ownership/borrowing.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn add(p1: &Point, p2: &Point) -> Point {\n" +" Point(p1.0 + p2.0, p1.1 + p2.1)\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/borrowing.md:22 +#, fuzzy +msgid "" +"* The `add` function _borrows_ two points and returns a new point.\n" +"* The caller retains ownership of the inputs." +msgstr "" +"* La fonction `add` _emprunte_ deux points et renvoie un nouveau point.\n" +"* L'appelant conserve la propriété des entrées." + +#: src/ownership/borrowing.md:27 +#, fuzzy +msgid "Notes on stack returns:" +msgstr "Remarques sur les retours de pile :" + +#: src/ownership/borrowing.md:28 +msgid "" +"* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy operation. Change the above code to print stack " +"addresses and run it on the [Playground]. In the \"DEBUG\" optimization level, the addresses should change, while they stay the same when changing " +"to the \"RELEASE\" setting:\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn add(p1: &Point, p2: &Point) -> Point {\n" +" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" +" println!(\"&p.0: {:p}\", &p.0);\n" +" p\n" +" }\n" +"\n" +" fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"&p3.0: {:p}\", &p3.0);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +" }\n" +" ```\n" +"* The Rust compiler can do return value optimization (RVO).\n" +"* In C++, copy elision has to be defined in the language specification because constructors can have side effects. In Rust, this is not an issue at " +"all. If RVO did not happen, Rust will always performs a simple and efficient `memcpy` copy." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:1 +#, fuzzy +msgid "# Shared and Unique Borrows" +msgstr "# Emprunts partagés et uniques" + +#: src/ownership/shared-unique-borrows.md:3 +#, fuzzy +msgid "Rust puts constraints on the ways you can borrow values:" +msgstr "Rust impose des contraintes sur la manière dont vous pouvez emprunter des valeurs :" + +#: src/ownership/shared-unique-borrows.md:5 +#, fuzzy +msgid "" +"* You can have one or more `&T` values at any given time, _or_\n" +"* You can have exactly one `&mut T` value." +msgstr "" +"* Vous pouvez avoir une ou plusieurs valeurs `&T` à tout moment, _ou_\n" +"* Vous pouvez avoir exactement une valeur `&mut T`." + +#: src/ownership/shared-unique-borrows.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let mut a: i32 = 10;\n" +" let b: &i32 = &a;\n" +"\n" +" {\n" +" let c: &mut i32 = &mut a;\n" +" *c = 20;\n" +" }\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:25 +#, fuzzy +msgid "" +"* The above code does not compile because `a` is borrowed as mutable (through `c`) and as immutable (through `b`) at the same time.\n" +"* Move the `println!` statement for `b` before the scope that introduces `c` to make the code compile.\n" +"* After that change, the compiler realizes that `b` is only ever used before the new mutable borrow of `a` through `c`. This is a feature of the " +"borrow checker called \"non-lexical lifetimes\"." +msgstr "" +"* Le code ci-dessus ne se compile pas car 'a' est emprunté comme mutable (via 'c') et comme immuable (via 'b') en même temps.\n" +"* Déplacez l'instruction `println!` pour `b` avant la portée qui introduit `c` pour que le code soit compilé.\n" +"* Après ce changement, le compilateur se rend compte que 'b' n'est utilisé qu'avant le nouvel emprunt mutable de 'a' à 'c'. Il s'agit d'une " +"fonctionnalité du vérificateur d'emprunt appelée \"durées de vie non lexicales\"." + +#: src/ownership/lifetimes.md:1 +#, fuzzy +msgid "# Lifetimes" +msgstr "# Durées de vie" + +#: src/ownership/lifetimes.md:3 +#, fuzzy +msgid "A borrowed value has a _lifetime_:" +msgstr "Une valeur empruntée a une _durée de vie_ :" + +#: src/ownership/lifetimes.md:5 +msgid "" +"* The lifetime can be elided: `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." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:1 +#, fuzzy +msgid "# Lifetimes in Function Calls" +msgstr "# Durées de vie dans les appels de fonction" + +#: src/ownership/lifetimes-function-calls.md:3 +#, fuzzy +msgid "In addition to borrowing its arguments, a function can return a borrowed value:" +msgstr "En plus d'emprunter ses arguments, une fonction peut renvoyer une valeur empruntée :" + +#: src/ownership/lifetimes-function-calls.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p2: Point = Point(20, 20);\n" +" let p3: &Point = left_most(&p1, &p2);\n" +" println!(\"left-most point: {:?}\", p3);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:21 +#, fuzzy +msgid "" +"* `'a` is a generic parameter, it is inferred by the compiler.\n" +"* Lifetimes start with `'` and `'a` is a typical default name.\n" +"* Read `&'a Point` as \"a borrowed `Point` which is valid for at least the\n" +" lifetime `a`\".\n" +" * The _at least_ part is important when parameters are in different scopes." +msgstr "" +"* `'a` est un paramètre générique, il est déduit par le compilateur.\n" +"* Les durées de vie commencent par `'` et `'a` est un nom par défaut typique.\n" +"* Lire `&'a Point` comme \"un `Point` emprunté qui est valide pour au moins\n" +" durée de vie 'a'\".\n" +" * La partie _au moins_ est importante lorsque les paramètres sont dans des portées différentes." + +#: src/ownership/lifetimes-function-calls.md:31 +msgid "" +"* Move the declaration of `p2` and `p3` into a a new scope (`{ ... }`), resulting in the following code:\n" +" ```rust,ignore\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +" }\n" +"\n" +" fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p3: &Point;\n" +" {\n" +" let p2: Point = Point(20, 20);\n" +" p3 = left_most(&p1, &p2);\n" +" }\n" +" println!(\"left-most point: {:?}\", p3);\n" +" }\n" +" ```\n" +" Note how this does not compile since `p3` outlives `p2`.\n" +"\n" +"* Reset the workspace and change the function signature to `fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " +"because the relationship between the lifetimes `'a` and `'b` is unclear.\n" +"* Another way to explain it:\n" +" * 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" +" for longer than a variable from where the reference came from." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:1 +#, fuzzy +msgid "# Lifetimes in Data Structures" +msgstr "# Durées de vie dans les structures de données" + +#: src/ownership/lifetimes-data-structures.md:3 +#, fuzzy +msgid "If a data type stores borrowed data, it must be annotated with a lifetime:" +msgstr "Si un type de données stocke des données empruntées, il doit être annoté avec une durée de vie :" + +#: src/ownership/lifetimes-data-structures.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Highlight<'doc>(&'doc str);\n" +"\n" +"fn erase(text: String) {\n" +" println!(\"Bye {text}!\");\n" +"}\n" +"\n" +"fn main() {\n" +" let text = String::from(\"The quick brown fox jumps over the lazy dog.\");\n" +" let fox = Highlight(&text[4..19]);\n" +" let dog = Highlight(&text[35..43]);\n" +" // erase(text);\n" +" println!(\"{fox:?}\");\n" +" println!(\"{dog:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:25 +#, fuzzy +msgid "" +"* In the above example, the annotation on `Highlight` enforces that the data underlying the contained `&str` lives at least as long as any instance " +"of `Highlight` that uses that data.\n" +"* If `text` is consumed before the end of the lifetime of `fox` (or `dog`), the borrow checker throws an error.\n" +"* Types with borrowed data force users to hold on to the original data. This can be useful for creating lightweight views, but it generally makes " +"them somewhat harder to use.\n" +"* When possible, make data structures own their data directly.\n" +"* Some structs with multiple references inside can have more than one lifetime annotation. This can be necessary if there is a need to describe " +"lifetime relationships between the references themselves, in addition to the lifetime of the struct itself. Those are very advanced use cases." +msgstr "" +"* Dans l'exemple ci-dessus, l'annotation sur `Highlight` impose que les données sous-jacentes au `&str` contenu vivent au moins aussi longtemps que " +"toute instance de `Highlight` qui utilise ces données.\n" +"* Si `text` est consommé avant la fin de la durée de vie de `fox` (ou `dog`), le vérificateur d'emprunt génère une erreur.\n" +"* Les types avec des données empruntées obligent les utilisateurs à conserver les données d'origine. Cela peut être utile pour créer des vues " +"légères, mais cela les rend généralement un peu plus difficiles à utiliser.\n" +"* Dans la mesure du possible, faites en sorte que les structures de données soient directement propriétaires de leurs données.\n" +"* Certaines structures contenant plusieurs références peuvent avoir plusieurs annotations de durée de vie. Cela peut être nécessaire s'il est " +"nécessaire de décrire les relations de durée de vie entre les références elles-mêmes, en plus de la durée de vie de la structure elle-même. Ce sont " +"des cas d'utilisation très avancés." + +#: src/exercises/day-1/afternoon.md:1 +#, fuzzy +msgid "# Day 1: Afternoon Exercises" +msgstr "# Jour 1 : Exercices de l'après-midi" + +#: src/exercises/day-1/afternoon.md:3 +#, fuzzy +msgid "We will look at two things:" +msgstr "Nous allons regarder deux choses :" + +#: src/exercises/day-1/afternoon.md:5 +#, fuzzy +msgid "" +"* A small book library,\n" +"\n" +"* Iterators and ownership (hard)." +msgstr "" +"* Une petite bibliothèque de livres,\n" +"\n" +"* Itérateurs et propriété (difficile)." + +#: src/exercises/day-1/book-library.md:1 +#, fuzzy +msgid "# Designing a Library" +msgstr "# Concevoir une bibliothèque" + +#: src/exercises/day-1/book-library.md:3 +#, fuzzy +msgid "" +"We will learn much more about structs and the `Vec` type tomorrow. For now,\n" +"you just need to know part of its API:" +msgstr "" +"Nous en apprendrons beaucoup plus sur les structures et le type `Vec` demain. Pour l'instant,\n" +"vous avez juste besoin de connaître une partie de son API :" + +#: src/exercises/day-1/book-library.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut vec = vec![10, 20];\n" +" vec.push(30);\n" +" println!(\"middle value: {}\", vec[vec.len() / 2]);\n" +" for item in vec.iter() {\n" +" println!(\"item: {item}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:17 +#, fuzzy +msgid "" +"Use this to create a library application. Copy the code below to\n" +" and update the types to make it compile:" +msgstr "" +"Utilisez-le pour créer une application de bibliothèque. Copiez le code ci-dessous pour\n" +" et mettez à jour les types pour le faire compiler :" + +#: src/exercises/day-1/book-library.md:20 +msgid "" +"```rust,should_panic\n" +"\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// 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" +"impl Library {\n" +" fn new() -> Library {\n" +" unimplemented!()\n" +" }\n" +"\n" +" //fn len(self) -> usize {\n" +" // unimplemented!()\n" +" //}\n" +"\n" +" //fn is_empty(self) -> bool {\n" +" // unimplemented!()\n" +" //}\n" +"\n" +" //fn add_book(self, book: Book) {\n" +" // unimplemented!()\n" +" //}\n" +"\n" +" //fn print_books(self) {\n" +" // unimplemented!()\n" +" //}\n" +"\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // unimplemented!()\n" +" //}\n" +"}\n" +"\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();\n" +"\n" +" //println!(\"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" +" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\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" +" //}\n" +" //\n" +" //println!(\"Our library has {} books\", library.len());\n" +" for book in library.books {\n" +" println!(\"{book}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:104 +#, fuzzy +msgid "[Solution](solutions-afternoon.md#designing-a-library)" +msgstr "[Solution](solutions-afternoon.md#designing-a-library)" + +#: src/exercises/day-1/iterators-and-ownership.md:1 +#, fuzzy +msgid "# Iterators and Ownership" +msgstr "# Itérateurs et propriété" + +#: src/exercises/day-1/iterators-and-ownership.md:3 +#, fuzzy +msgid "" +"The ownership model of Rust affects many APIs. An example of this is the\n" +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and\n" +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)\n" +"traits." +msgstr "" +"Le modèle de propriété de Rust affecte de nombreuses API. Un exemple en est le\n" +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) et\n" +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)\n" +"caractéristiques." + +#: src/exercises/day-1/iterators-and-ownership.md:8 +#, fuzzy +msgid "## `Iterator`" +msgstr "## `Itérateur`" + +#: src/exercises/day-1/iterators-and-ownership.md:10 +#, fuzzy +msgid "" +"Traits are like interfaces: they describe behavior (methods) for a type. The\n" +"`Iterator` trait simply says that you can call `next` until you get `None` back:" +msgstr "" +"Les traits sont comme des interfaces : ils décrivent le comportement (méthodes) d'un type. Le\n" +"Le trait `Iterator` indique simplement que vous pouvez appeler `next` jusqu'à ce que vous obteniez `None` :" + +#: src/exercises/day-1/iterators-and-ownership.md:13 +msgid "" +"```rust\n" +"pub trait Iterator {\n" +" type Item;\n" +" fn next(&mut self) -> Option;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:20 +#, fuzzy +msgid "You use this trait like this:" +msgstr "Vous utilisez ce trait comme ceci :" + +#: src/exercises/day-1/iterators-and-ownership.md:22 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" println!(\"v[0]: {:?}\", iter.next());\n" +" println!(\"v[1]: {:?}\", iter.next());\n" +" println!(\"v[2]: {:?}\", iter.next());\n" +" println!(\"No more items: {:?}\", iter.next());\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:34 +#, fuzzy +msgid "What is the type returned by the iterator? Test your answer here:" +msgstr "Quel est le type retourné par l'itérateur ? Testez votre réponse ici :" + +#: src/exercises/day-1/iterators-and-ownership.md:36 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:46 +#, fuzzy +msgid "Why is this type used?" +msgstr "Pourquoi ce type est-il utilisé ?" + +#: src/exercises/day-1/iterators-and-ownership.md:48 +#, fuzzy +msgid "## `IntoIterator`" +msgstr "## `IntoIterator`" + +#: src/exercises/day-1/iterators-and-ownership.md:50 +#, fuzzy +msgid "" +"The `Iterator` trait tells you how to _iterate_ once you have created an\n" +"iterator. The related trait `IntoIterator` tells you how to create the iterator:" +msgstr "" +"Le trait `Iterator` vous indique comment _itérer_ une fois que vous avez créé un\n" +"itérateur. Le trait connexe \"IntoIterator\" vous indique comment créer l'itérateur :" + +#: src/exercises/day-1/iterators-and-ownership.md:53 +msgid "" +"```rust\n" +"pub trait IntoIterator {\n" +" type Item;\n" +" type IntoIter: Iterator;\n" +"\n" +" fn into_iter(self) -> Self::IntoIter;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:62 +#, fuzzy +msgid "" +"The syntax here means that every implementation of `IntoIterator` must\n" +"declare two types:" +msgstr "" +"La syntaxe ici signifie que chaque implémentation de `IntoIterator` doit\n" +"déclarer deux types :" + +#: src/exercises/day-1/iterators-and-ownership.md:65 +#, fuzzy +msgid "" +"* `Item`: the type we iterate over, such as `i8`,\n" +"* `IntoIter`: the `Iterator` type returned by the `into_iter` method." +msgstr "" +"* `Item` : le type sur lequel nous itérons, tel que `i8`,\n" +"* `IntoIter` : le type `Iterator` renvoyé par la méthode `into_iter`." + +#: src/exercises/day-1/iterators-and-ownership.md:68 +#, fuzzy +msgid "" +"Note that `IntoIter` and `Item` are linked: the iterator must have the same\n" +"`Item` type, which means that it returns `Option`" +msgstr "" +"Notez que `IntoIter` et `Item` sont liés : l'itérateur doit avoir le même\n" +"Type `Item`, ce qui signifie qu'il renvoie `Option`" + +#: src/exercises/day-1/iterators-and-ownership.md:71 +#, fuzzy +msgid "Like before, what is the type returned by the iterator?" +msgstr "Comme précédemment, quel est le type retourné par l'itérateur ?" + +#: src/exercises/day-1/iterators-and-ownership.md:73 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];\n" +" let mut iter = v.into_iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:83 +#, fuzzy +msgid "## `for` Loops" +msgstr "## Boucles `for`" + +#: src/exercises/day-1/iterators-and-ownership.md:85 +#, fuzzy +msgid "" +"Now that we know both `Iterator` and `IntoIterator`, we can build `for` loops.\n" +"They call `into_iter()` on an expression and iterates over the resulting\n" +"iterator:" +msgstr "" +"Maintenant que nous connaissons à la fois `Iterator` et `IntoIterator`, nous pouvons construire des boucles `for`.\n" +"Ils appellent `into_iter()` sur une expression et itèrent sur le résultat\n" +"itérateur :" + +#: src/exercises/day-1/iterators-and-ownership.md:89 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];\n" +"\n" +" for word in &v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"\n" +" for word in v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:103 +#, fuzzy +msgid "What is the type of `word` in each loop?" +msgstr "Quel est le type de \"mot\" dans chaque boucle ?" + +#: src/exercises/day-1/iterators-and-ownership.md:105 +#, fuzzy +msgid "" +"Experiment with the code above and then consult the documentation for [`impl\n" +"IntoIterator for\n" +"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E)\n" +"and [`impl IntoIterator for\n" +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-Vec%3CT%2C%20A%3E)\n" +"to check your answers." +msgstr "" +"Expérimentez avec le code ci-dessus, puis consultez la documentation de [`impl\n" +"IntoIterator pour\n" +"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E)\n" +"et [`impl IntoIterator for\n" +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-Vec%3CT%2C%20A%3E)\n" +"pour vérifier vos réponses." + +#: src/welcome-day-2.md:1 +#, fuzzy +msgid "# Welcome to Day 2" +msgstr "# Bienvenue au jour 2" + +#: src/welcome-day-2.md:3 +#, fuzzy +msgid "Now that we have seen a fair amount of Rust, we will continue with:" +msgstr "Maintenant que nous avons vu une bonne quantité de Rust, nous allons continuer avec :" + +#: src/welcome-day-2.md:5 +#, fuzzy +msgid "" +"* Structs, enums, methods.\n" +"\n" +"* Pattern matching: destructuring enums, structs, and arrays.\n" +"\n" +"* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and\n" +" `continue`.\n" +"\n" +"* The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, `Rc`\n" +" and `Arc`.\n" +"\n" +"* Modules: visibility, paths, and filesystem hierarchy." +msgstr "" +"* Structures, énumérations, méthodes.\n" +"\n" +"* Pattern matching : déstructuration des énumérations, des structures et des tableaux.\n" +"\n" +"* Constructions de flux de contrôle : `if`, `if let`, `while`, `while let`, `break` et\n" +" 'continuer'.\n" +"\n" +"* La bibliothèque standard : `String`, `Option` et `Result`, `Vec`, `HashMap`, `Rc`\n" +" et \"Arc\".\n" +"\n" +"* Modules : visibilité, chemins et hiérarchie du système de fichiers." + +#: src/structs.md:1 +#, fuzzy +msgid "# Structs" +msgstr "# Structures" + +#: src/structs.md:3 +#, fuzzy +msgid "Like C and C++, Rust has support for custom structs:" +msgstr "Comme C et C++, Rust prend en charge les structures personnalisées :" + +#: src/structs.md:5 +msgid "" +"```rust,editable\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" peter.age = 28;\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" let jackie = Person {\n" +" name: String::from(\"Jackie\"),\n" +" ..peter\n" +" };\n" +" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" +"}\n" +"```" +msgstr "" + +#: src/structs.md:29 +#, fuzzy +msgid "" +"
\n" +"Key Points: " +msgstr "" +"\n" +"Points clés:" + +#: src/structs.md:32 +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" +" * Unlike in C++, there is no inheritance between structs.\n" +"* Methods are defined in an `impl` block, which we will see in following slides.\n" +"* This may be a good time to let people know there are different types of structs. \n" +" * Zero-sized structs `e.g., struct Foo;` might be used when implementing a trait on some type but don’t have any data that you want to store in " +"the value itself. \n" +" * The next slide will introduce Tuple structs, used when the field names are not important.\n" +"* The syntax `..peter` allows us to copy the majority of the fields from the old struct without having to explicitly type it all out. It must always " +"be the last element." +msgstr "" + +#: src/structs/tuple-structs.md:1 +#, fuzzy +msgid "# Tuple Structs" +msgstr "# Structures de tuple" + +#: src/structs/tuple-structs.md:3 +#, fuzzy +msgid "If the field names are unimportant, you can use a tuple struct:" +msgstr "Si les noms de champ ne sont pas importants, vous pouvez utiliser une structure tuple :" + +#: src/structs/tuple-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p = Point(17, 23);\n" +" println!(\"({}, {})\", p.0, p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:14 +#, fuzzy +msgid "This is often used for single-field wrappers (called newtypes):" +msgstr "Ceci est souvent utilisé pour les wrappers à champ unique (appelés newtypes):" + +#: src/structs/tuple-structs.md:16 +msgid "" +"```rust,editable,compile_fail\n" +"struct PoundOfForce(f64);\n" +"struct Newtons(f64);\n" +"\n" +"fn compute_thruster_force() -> PoundOfForce {\n" +" todo!(\"Ask a rocket scientist at NASA\")\n" +"}\n" +"\n" +"fn set_thruster_force(force: Newtons) {\n" +" // ...\n" +"}\n" +"\n" +"fn main() {\n" +" let force = compute_thruster_force();\n" +" set_thruster_force(force);\n" +"}\n" +"\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:37 +#, fuzzy +msgid "" +"* Newtypes are a great way to encode additional information about the value in a primitive type, for example:\n" +" * The number is measured in some units: `Newtons` in the example above.\n" +" * The value passed some validation when it was created, so you no longer have to validate it again at every use: 'PhoneNumber(String)` or " +"`OddNumber(u32)`.\n" +"* Demonstrate how to add a `f64` value to a `Newtons` type by accessing the single field in the newtype.\n" +" * Rust generally doesn’t like inexplicit things, like automatic unwrapping or for instance using booleans as integers.\n" +" * Operator overloading is discussed on Day 3 (generics). " +msgstr "" +"* Les nouveaux types sont un excellent moyen d'encoder des informations supplémentaires sur la valeur dans un type primitif, par exemple :\n" +" * Le nombre est mesuré dans certaines unités : `Newtons` dans l'exemple ci-dessus.\n" +" * La valeur a été validée lors de sa création, vous n'avez donc plus besoin de la valider à chaque utilisation : 'PhoneNumber(String)` ou " +"`OddNumber(u32)`.\n" +"* Montrez comment ajouter une valeur `f64` à un type `Newtons` en accédant au champ unique dans le nouveau type.\n" +" * Rust n'aime généralement pas les choses inexplicites, comme le déballage automatique ou, par exemple, l'utilisation de booléens comme entiers.\n" +" * La surcharge des opérateurs est discutée le jour 3 (génériques)." + +#: src/structs/field-shorthand.md:1 +#, fuzzy +msgid "# Field Shorthand Syntax" +msgstr "# Syntaxe abrégée du champ" + +#: src/structs/field-shorthand.md:3 +#, fuzzy +msgid "" +"If you already have variables with the right names, then you can create the\n" +"struct using a shorthand:" +msgstr "" +"Si vous avez déjà des variables avec les bons noms, vous pouvez créer le\n" +"struct en utilisant un raccourci :" + +#: src/structs/field-shorthand.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn new(name: String, age: u8) -> Person {\n" +" Person { name, age }\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person::new(String::from(\"Peter\"), 27);\n" +" println!(\"{peter:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/structs/field-shorthand.md:27 +msgid "" +"* The `new` function could be written using `Self` as a type, as it is interchangeable with the struct type name\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Person {\n" +" fn new(name: String, age: u8) -> Self {\n" +" Self { name, age }\n" +" }\n" +" }\n" +" ``` \n" +"* Implement the `Default` trait for the struct. Define some fields and use the default values for the other fields.\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Default for Person {\n" +" fn default() -> Person {\n" +" Person {\n" +" name: \"Bot\".to_string(),\n" +" age: 0,\n" +" }\n" +" }\n" +" }\n" +" fn create_default() {\n" +" let tmp = Person {\n" +" ..Default::default()\n" +" };\n" +" let tmp = Person {\n" +" name: \"Sam\".to_string(),\n" +" ..Default::default()\n" +" };\n" +" }\n" +" ```\n" +"\n" +"* Methods are defined in the `impl` block.\n" +"* Use struct update syntax to define a new structure using `peter`. Note that the variable `peter` will no longer be accessible afterwards.\n" +"* Use `{:#?}` when printing structs to request the `Debug` representation." +msgstr "" + +#: src/enums.md:1 +#, fuzzy +msgid "# Enums" +msgstr "# Énumérations" + +#: src/enums.md:3 +#, fuzzy +msgid "" +"The `enum` keyword allows the creation of a type which has a few\n" +"different variants:" +msgstr "" +"Le mot clé `enum` permet la création d'un type qui a quelques\n" +"différentes variantes :" + +#: src/enums.md:6 +msgid "" +"```rust,editable\n" +"fn generate_random_number() -> i32 {\n" +" 4 // Chosen by fair dice roll. Guaranteed to be random.\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"enum CoinFlip {\n" +" Heads,\n" +" Tails,\n" +"}\n" +"\n" +"fn flip_coin() -> CoinFlip {\n" +" let random_number = generate_random_number();\n" +" if random_number % 2 == 0 {\n" +" return CoinFlip::Heads;\n" +" } else {\n" +" return CoinFlip::Tails;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"You got: {:?}\", flip_coin());\n" +"}\n" +"```" +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 "Points clés:" + +#: src/enums.md:35 +#, fuzzy +msgid "" +"* Enumerations allow you to collect a set of values under one type\n" +"* This page offers an enum type `CoinFlip` with two variants `Heads` and `Tail`. You might note the namespace when using variants.\n" +"* This might be a good time to compare Structs and Enums:\n" +" * In both, you can have a simple version without fields (unit struct) or one with different types of fields (variant payloads). \n" +" * In both, associated functions are defined within an `impl` block.\n" +" * You could even implement the different variants of an enum with separate structs but then they wouldn’t be the same type as they would if they " +"were all defined in an enum. " +msgstr "" +"* Les énumérations vous permettent de collecter un ensemble de valeurs sous un type\n" +"* Cette page propose un type d'énumération `CoinFlip` avec deux variantes `Heads` et `Tail`. Vous pouvez noter l'espace de noms lors de " +"l'utilisation de variantes.\n" +"* C'est peut-être le bon moment pour comparer Structs et Enums :\n" +" * Dans les deux cas, vous pouvez avoir une version simple sans champs (structure d'unité) ou une version avec différents types de champs (charges " +"utiles variantes).\n" +" * Dans les deux cas, les fonctions associées sont définies dans un bloc `impl`.\n" +" * Vous pouvez même implémenter les différentes variantes d'une énumération avec des structures distinctes, mais elles ne seraient alors pas du " +"même type que si elles étaient toutes définies dans une énumération." + +#: src/enums/variant-payloads.md:1 +#, fuzzy +msgid "# Variant Payloads" +msgstr "# Charges utiles variantes" + +#: src/enums/variant-payloads.md:3 +#, fuzzy +msgid "" +"You can define richer enums where the variants carry data. You can then use the\n" +"`match` statement to extract the data from each variant:" +msgstr "" +"Vous pouvez définir des énumérations plus riches où les variantes transportent des données. Vous pouvez ensuite utiliser le\n" +"instruction `match` pour extraire les données de chaque variante :" + +#: src/enums/variant-payloads.md:6 +msgid "" +"```rust,editable\n" +"enum WebEvent {\n" +" PageLoad, // Variant without payload\n" +" KeyPress(char), // Tuple struct variant\n" +" Click { x: i64, y: i64 }, // Full struct variant\n" +"}\n" +"\n" +"#[rustfmt::skip]\n" +"fn inspect(event: WebEvent) {\n" +" match event {\n" +" WebEvent::PageLoad => println!(\"page loaded\"),\n" +" WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" +" WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let load = WebEvent::PageLoad;\n" +" let press = WebEvent::KeyPress('x');\n" +" let click = WebEvent::Click { x: 20, y: 80 };\n" +"\n" +" inspect(load);\n" +" inspect(press);\n" +" inspect(click);\n" +"}\n" +"```" +msgstr "" + +#: src/enums/variant-payloads.md:35 +#, fuzzy +msgid "" +"* The values in the enum variants can only be accessed after being pattern matched. The pattern binds references to the fields in the \"match arm\" " +"after the `=>`.\n" +" * The expression is matched against the patterns from top to bottom. There is no fall-through like in C or C++.\n" +" * The match expression has a value. The value is the last expression in the match arm which was executed.\n" +" * Starting from the top we look for what pattern matches the value then run the code following the arrow. Once we find a match, we stop. \n" +"* Demonstrate what happens when the search is inexhaustive. Note the advantage the Rust compiler provides by confirming when all cases are " +"handled. \n" +"* `match` inspects a hidden discriminant field in the `enum`.\n" +"* It is possible to retrieve the discriminant by calling `std::mem::discriminant()`\n" +" * This is useful, for example, if implementing `PartialEq` for structs where comparing field values doesn't affect equality.\n" +"* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::Click(Click)` with a top level `struct Click { ... }`. The inlined version cannot " +"implement traits, for example. \n" +" " +msgstr "" +"* Les valeurs des variantes enum ne sont accessibles qu'après avoir été mises en correspondance avec le modèle. Le modèle lie les références aux " +"champs dans le \"match arm\" après le `=>`.\n" +" * L'expression est comparée aux modèles de haut en bas. Il n'y a pas de basculement comme en C ou C++.\n" +" * L'expression de correspondance a une valeur. La valeur est la dernière expression du bras de correspondance qui a été exécutée.\n" +" * En partant du haut, nous cherchons quel modèle correspond à la valeur, puis exécutons le code en suivant la flèche. Une fois que nous trouvons " +"une correspondance, nous nous arrêtons.\n" +"* Démontrer ce qui se passe lorsque la recherche est inépuisable. Notez l'avantage que le compilateur Rust fournit en confirmant quand tous les cas " +"sont traités.\n" +"* `match` inspecte un champ discriminant caché dans `enum`.\n" +"* Il est possible de récupérer le discriminant en appelant `std::mem::discriminant()`\n" +" * Ceci est utile, par exemple, si vous implémentez `PartialEq` pour des structures où la comparaison des valeurs de champ n'affecte pas " +"l'égalité.\n" +"* `WebEvent::Click { ... }` n'est pas exactement le même que `WebEvent::Click(Click)` avec un niveau supérieur `struct Click { ... }`. La version en " +"ligne ne peut pas implémenter de traits, par exemple.\n" +" " + +#: src/enums/sizes.md:1 +#, fuzzy +msgid "# Enum Sizes" +msgstr "# Tailles d'énumération" + +#: src/enums/sizes.md:3 +#, fuzzy +msgid "Rust enums are packed tightly, taking constraints due to alignment into account:" +msgstr "Les énumérations de rouille sont emballées étroitement, en tenant compte des contraintes dues à l'alignement :" + +#: src/enums/sizes.md:5 +msgid "" +"```rust,editable\n" +"use std::mem::{align_of, size_of};\n" +"\n" +"macro_rules! dbg_size {\n" +" ($t:ty) => {\n" +" println!(\"{}: size {} bytes, align: {} bytes\",\n" +" stringify!($t), size_of::<$t>(), align_of::<$t>());\n" +" };\n" +"}\n" +"\n" +"enum Foo {\n" +" A,\n" +" B,\n" +"}\n" +"\n" +"fn main() {\n" +" dbg_size!(Foo);\n" +"}\n" +"```" +msgstr "" + +#: src/enums/sizes.md:25 +#, fuzzy +msgid "* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout.html)." +msgstr "* Voir la [Rust Reference](https://doc.rust-lang.org/reference/type-layout.html)." + +#: src/enums/sizes.md:31 +msgid "" +" * Internally Rust is using a field (discriminant) to keep track of the enum variant.\n" +"\n" +" * You can control the discriminant if needed (e.g., for compatibility with C):\n" +" \n" +" ```rust,editable\n" +" #[repr(u32)]\n" +" enum Bar {\n" +" A, // 0\n" +" B = 10000,\n" +" C, // 10001\n" +" }\n" +" \n" +" fn main() {\n" +" println!(\"A: {}\", Bar::A as u32);\n" +" println!(\"B: {}\", Bar::B as u32);\n" +" println!(\"C: {}\", Bar::C as u32);\n" +" }\n" +" ```\n" +"\n" +" Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2\n" +" bytes.\n" +"\n" +"\n" +" * Try out other types such as\n" +" \n" +" * `dbg_size!(bool)`: size 1 bytes, align: 1 bytes,\n" +" * `dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche optimization, see below),\n" +" * `dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit machine),\n" +" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer optimization, see below).\n" +"\n" +" * Niche optimization: Rust will merge use unused bit patterns for the enum\n" +" discriminant.\n" +"\n" +" * Null pointer optimization: For [some\n" +" types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees\n" +" that `size_of::()` equals `size_of::>()`.\n" +"\n" +" Example code if you want to show how the bitwise representation *may* look like in practice.\n" +" It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally unsafe.\n" +"\n" +" ```rust,editable\n" +" use std::mem::transmute;\n" +"\n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" println!(\"Bitwise representation of bool\");\n" +" dbg_bits!(false, u8);\n" +" dbg_bits!(true, u8);\n" +"\n" +" println!(\"Bitwise representation of Option\");\n" +" dbg_bits!(None::, u8);\n" +" dbg_bits!(Some(false), u8);\n" +" dbg_bits!(Some(true), u8);\n" +"\n" +" println!(\"Bitwise representation of Option>\");\n" +" dbg_bits!(Some(Some(false)), u8);\n" +" dbg_bits!(Some(Some(true)), u8);\n" +" dbg_bits!(Some(None::), u8);\n" +" dbg_bits!(None::>, u8);\n" +"\n" +" println!(\"Bitwise representation of Option<&i32>\");\n" +" dbg_bits!(None::<&i32>, usize);\n" +" dbg_bits!(Some(&0i32), usize);\n" +" }\n" +" }\n" +" ```\n" +"\n" +" More complex example if you want to discuss what happens when we chain more than 256 `Option`s together.\n" +"\n" +" ```rust,editable\n" +" #![recursion_limit = \"1000\"]\n" +"\n" +" use std::mem::transmute;\n" +" \n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" // Macro to wrap a value in 2^n Some() where n is the number of \"@\" signs.\n" +" // Increasing the recursion limit is required to evaluate this macro.\n" +" macro_rules! many_options {\n" +" ($value:expr) => { Some($value) };\n" +" ($value:expr, @) => {\n" +" Some(Some($value))\n" +" };\n" +" ($value:expr, @ $($more:tt)+) => {\n" +" many_options!(many_options!($value, $($more)+), $($more)+)\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" assert_eq!(many_options!(false), Some(false));\n" +" assert_eq!(many_options!(false, @), Some(Some(false)));\n" +" assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));\n" +"\n" +" println!(\"Bitwise representation of a chain of 128 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" +" dbg_bits!(many_options!(true, @@@@@@@), u8);\n" +"\n" +" println!(\"Bitwise representation of a chain of 256 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(true, @@@@@@@@), u16);\n" +"\n" +" println!(\"Bitwise representation of a chain of 257 Option's.\");\n" +" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" +" }\n" +" }\n" +" ```" +msgstr "" + +#: src/methods.md:3 +#, fuzzy +msgid "" +"Rust allows you to associate functions with your new types. You do this with an\n" +"`impl` block:" +msgstr "" +"Rust vous permet d'associer des fonctions à vos nouveaux types. Vous faites cela avec un\n" +"Bloc `impl` :" + +#: src/methods.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn say_hello(&self) {\n" +" println!(\"Hello, my name is {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" peter.say_hello();\n" +"}\n" +"```" +msgstr "" + +#: src/methods.md:31 +#, fuzzy +msgid "" +"* It can be helpful to introduce methods by comparing them to functions.\n" +" * Methods are called on an instance of a type (such as a struct or enum), the first parameter represents the instance as `self`.\n" +" * Developers may choose to use methods to take advantage of method receiver syntax and to help keep them more organized. By using methods we can " +"keep all the implementation code in one predictable place.\n" +"* Point out the use of the keyword `self`, a method receiver. \n" +" * Show that it is an abbreviated term for `self:&Self` and perhaps show how the struct name could also be used. \n" +" * Explain that `Self` is a type alias for the type the `impl` block is in and can be used elsewhere in the block.\n" +" * Note how `self` is used like other structs and dot notation can be used to refer to individual fields.\n" +" * This might be a good time to demonstrate how the `&self` differs from `self` by modifying the code and trying to run say_hello twice. \n" +"* We describe the distinction between method receivers next.\n" +" " +msgstr "" +"* Il peut être utile d'introduire des méthodes en les comparant à des fonctions.\n" +" * Les méthodes sont appelées sur une instance d'un type (tel qu'un struct ou un enum), le premier paramètre représente l'instance en tant que " +"\"self\".\n" +" * Les développeurs peuvent choisir d'utiliser des méthodes pour tirer parti de la syntaxe du récepteur de méthode et pour mieux les organiser. En " +"utilisant des méthodes, nous pouvons conserver tout le code d'implémentation en un seul endroit prévisible.\n" +"* Soulignez l'utilisation du mot-clé `self`, un récepteur de méthode.\n" +" * Montrez qu'il s'agit d'un terme abrégé pour `self:&Self` et montrez peut-être comment le nom de la structure pourrait également être utilisé.\n" +" * Expliquez que `Self` est un alias de type pour le type dans lequel se trouve le bloc `impl` et peut être utilisé ailleurs dans le bloc.\n" +" * Notez comment `self` est utilisé comme d'autres structures et la notation par points peut être utilisée pour faire référence à des champs " +"individuels.\n" +" * C'est peut-être le bon moment pour démontrer en quoi `&self` diffère de `self` en modifiant le code et en essayant d'exécuter say_hello deux " +"fois.\n" +"* Nous décrivons ensuite la distinction entre les récepteurs de méthode.\n" +" " + +#: src/methods/receiver.md:1 +#, fuzzy +msgid "# Method Receiver" +msgstr "# Méthode Récepteur" + +#: src/methods/receiver.md:3 +#, fuzzy +msgid "" +"The `&self` above indicates that the method borrows the object immutably. There\n" +"are other possible receivers for a method:" +msgstr "" +"Le `&self` ci-dessus indique que la méthode emprunte l'objet de manière immuable. Là\n" +"sont d'autres récepteurs possibles pour une méthode :" + +#: src/methods/receiver.md:6 +#, fuzzy +msgid "" +"* `&self`: borrows the object from the caller using a shared and immutable\n" +" reference. The object can be used again afterwards.\n" +"* `&mut self`: borrows the object from the caller using a unique and mutable\n" +" reference. The object can be used again afterwards.\n" +"* `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" +"* No receiver: this becomes a static method on the struct. Typically used to\n" +" create constructors which are called `new` by convention." +msgstr "" +"* `&self` : emprunte l'objet à l'appelant en utilisant un partage et immuable\n" +" référence. L'objet peut être réutilisé par la suite.\n" +"* `&mut self` : emprunte l'objet à l'appelant en utilisant un nom unique et mutable\n" +" référence. L'objet peut être réutilisé par la suite.\n" +"* `self` : prend possession de l'objet et l'éloigne de l'appelant. Le\n" +" méthode devient le propriétaire de l'objet. L'objet sera supprimé (désalloué)\n" +" lorsque la méthode revient, sauf si sa propriété est explicitement\n" +" transmis.\n" +"* `mut self` : comme ci-dessus, mais tant que la méthode possède l'objet, elle peut\n" +" le faire muter aussi. La propriété complète ne signifie pas automatiquement la mutabilité.\n" +"* Pas de récepteur : cela devient une méthode statique sur la structure. Généralement utilisé pour\n" +" créer des constructeurs appelés \"nouveaux\" par convention." + +#: src/methods/receiver.md:19 +#, fuzzy +msgid "" +"Beyond variants on `self`, there are also\n" +"[special wrapper types](https://doc.rust-lang.org/reference/special-types-and-traits.html)\n" +"allowed to be receiver types, such as `Box`." +msgstr "" +"Au-delà des variantes sur \"self\", il y a aussi\n" +"[types d'emballage spéciaux] (https://doc.rust-lang.org/reference/special-types-and-traits.html)\n" +"autorisés à être des types de récepteurs, tels que `Box`." + +#: src/methods/receiver.md:25 +#, fuzzy +msgid "" +"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". These constraints always come\n" +"together in Rust due to borrow checker rules, and `self` is no exception. It isn't possible to\n" +"reference a struct from multiple locations and call a mutating (`&mut self`) method on it." +msgstr "" +"Pensez à mettre l'accent sur \"partagé et immuable\" et \"unique et modifiable\". Ces contraintes viennent toujours\n" +"ensemble dans Rust en raison des règles du vérificateur d'emprunt, et \"self\" ne fait pas exception. Il n'est pas possible de\n" +"référencez une structure à partir de plusieurs emplacements et appelez une méthode de mutation (`&mut self`) sur celle-ci." + +#: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 +#, fuzzy +msgid "# Example" +msgstr "# Exemple" + +#: src/methods/example.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Race {\n" +" name: String,\n" +" laps: Vec,\n" +"}\n" +"\n" +"impl Race {\n" +" fn new(name: &str) -> Race { // No receiver, a static method\n" +" Race { name: String::from(name), laps: Vec::new() }\n" +" }\n" +"\n" +" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write access to self\n" +" self.laps.push(lap);\n" +" }\n" +"\n" +" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" +" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" +" for (idx, lap) in self.laps.iter().enumerate() {\n" +" println!(\"Lap {idx}: {lap} sec\");\n" +" }\n" +" }\n" +"\n" +" fn finish(self) { // Exclusive ownership of self\n" +" let total = self.laps.iter().sum::();\n" +" println!(\"Race {} is finished, total lap time: {}\", self.name, total);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut race = Race::new(\"Monaco Grand Prix\");\n" +" race.add_lap(70);\n" +" race.add_lap(68);\n" +" race.print_laps();\n" +" race.add_lap(71);\n" +" race.print_laps();\n" +" race.finish();\n" +" // race.add_lap(42);\n" +"}\n" +"```" +msgstr "" + +#: src/methods/example.md:47 +#, fuzzy +msgid "" +"* All four methods here use a different method receiver.\n" +" * You can point out how that changes what the function can do with the variable values and if/how it can be used again in `main`.\n" +" * You can showcase the error that appears when trying to call `finish` twice.\n" +"* Note that although the method receivers are different, the non-static functions are called the same way in the main body. Rust enables automatic " +"referencing and dereferencing when calling methods. Rust automatically adds in the `&`, `*`, `muts` so that that object matches the method " +"signature.\n" +"* You might point out that `print_laps` is using a vector that is iterated over. We describe vectors in more detail in the afternoon. " +msgstr "" +"* Les quatre méthodes ici utilisent un récepteur de méthode différent.\n" +" * Vous pouvez indiquer comment cela change ce que la fonction peut faire avec les valeurs des variables et si/comment elle peut être réutilisée " +"dans `main`.\n" +" * Vous pouvez afficher l'erreur qui apparaît lorsque vous essayez d'appeler \"finish\" deux fois.\n" +"* Notez que bien que les récepteurs de méthode soient différents, les fonctions non statiques sont appelées de la même manière dans le corps " +"principal. Rust permet le référencement et le déréférencement automatique lors de l'appel de méthodes. Rust ajoute automatiquement les `&`, `*`, " +"`muts` afin que cet objet corresponde à la signature de la méthode.\n" +"* Vous pourriez remarquer que `print_laps` utilise un vecteur qui est itéré. Nous décrivons les vecteurs plus en détail dans l'après-midi." + +#: src/pattern-matching.md:1 +#, fuzzy +msgid "# Pattern Matching" +msgstr "# Correspondance de modèle" + +#: src/pattern-matching.md:3 +#, fuzzy +msgid "" +"The `match` keyword let you match a value against one or more _patterns_. The\n" +"comparisons are done from top to bottom and the first match wins." +msgstr "" +"Le mot clé `match` vous permet de faire correspondre une valeur à un ou plusieurs _patterns_. Le\n" +"les comparaisons se font de haut en bas et le premier match l'emporte." + +#: src/pattern-matching.md:6 +#, fuzzy +msgid "The patterns can be simple values, similarly to `switch` in C and C++:" +msgstr "Les modèles peuvent être des valeurs simples, de la même manière que `switch` en C et C++ :" + +#: src/pattern-matching.md:8 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let input = 'x';\n" +"\n" +" match input {\n" +" 'q' => println!(\"Quitting\"),\n" +" 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" +" '0'..='9' => println!(\"Number input\"),\n" +" _ => println!(\"Something else\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching.md:21 +#, fuzzy +msgid "The `_` pattern is a wildcard pattern which matches any value." +msgstr "Le modèle `_` est un modèle générique qui correspond à n'importe quelle valeur." + +#: src/pattern-matching.md:26 +#, fuzzy +msgid "" +"* You might point out how some specific characters are being used when in a pattern\n" +" * `|` as an `or`\n" +" * `..` can expand as much as it needs to be\n" +" * `1..=5` represents an inclusive range\n" +" * `_` is a wild card\n" +"* It can be useful to show how binding works, by for instance replacing a wildcard character with a variable, or removing the quotes around `q`.\n" +"* You can demonstrate matching on a reference.\n" +"* This might be a good time to bring up the concept of irrefutable patterns, as the term can show up in error messages.\n" +" " +msgstr "" +"* Vous pouvez indiquer comment certains caractères spécifiques sont utilisés dans un modèle\n" +" * `|` comme un `ou`\n" +" * `..` peut s'étendre autant que nécessaire\n" +" * `1..=5` représente une plage inclusive\n" +" * `_` est un joker\n" +"* Il peut être utile de montrer comment fonctionne la liaison, par exemple en remplaçant un caractère générique par une variable ou en supprimant " +"les guillemets autour de `q`.\n" +"* Vous pouvez démontrer la correspondance sur une référence.\n" +"* C'est peut-être le bon moment pour évoquer le concept de modèles irréfutables, car le terme peut apparaître dans les messages d'erreur.\n" +" " + +#: src/pattern-matching/destructuring-enums.md:1 +#, fuzzy +msgid "# Destructuring Enums" +msgstr "# déstructuration des énumérations" + +#: src/pattern-matching/destructuring-enums.md:3 +#, fuzzy +msgid "" +"Patterns can also be used to bind variables to parts of your values. This is how\n" +"you inspect the structure of your types. Let us start with a simple `enum` type:" +msgstr "" +"Les modèles peuvent également être utilisés pour lier des variables à des parties de vos valeurs. C'est ainsi\n" +"vous inspectez la structure de vos types. Commençons par un simple type `enum` :" + +#: src/pattern-matching/destructuring-enums.md:6 +msgid "" +"```rust,editable\n" +"enum Result {\n" +" Ok(i32),\n" +" Err(String),\n" +"}\n" +"\n" +"fn divide_in_two(n: i32) -> Result {\n" +" if n % 2 == 0 {\n" +" Result::Ok(n / 2)\n" +" } else {\n" +" Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let n = 100;\n" +" match divide_in_two(n) {\n" +" Result::Ok(half) => println!(\"{n} divided in two is {half}\"),\n" +" Result::Err(msg) => println!(\"sorry, an error happened: {msg}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:29 +#, fuzzy +msgid "" +"Here we have used the arms to _destructure_ the `Result` value. In the first\n" +"arm, `half` is bound to the value inside the `Ok` variant. In the second arm,\n" +"`msg` is bound to the error message." +msgstr "" +"Ici, nous avons utilisé les bras pour _déstructurer_ la valeur `Result`. En premier\n" +"arm, `half` est lié à la valeur à l'intérieur de la variante `Ok`. Dans le deuxième bras,\n" +"`msg` est lié au message d'erreur." + +#: src/pattern-matching/destructuring-enums.md:36 +#, fuzzy +msgid "" +"* The `if`/`else` expression is returning an enum that is later unpacked with a `match`.\n" +"* You can try adding a third variant to the enum definition and displaying the errors when running the code. Point out the places where your code is " +"now inexhaustive and how the compiler tries to give you hints." +msgstr "" +"* L'expression `if`/`else` renvoie une énumération qui est ensuite décompressée avec une `match`.\n" +"* Vous pouvez essayer d'ajouter une troisième variante à la définition enum et d'afficher les erreurs lors de l'exécution du code. Indiquez les " +"endroits où votre code est maintenant inexhaustif et comment le compilateur essaie de vous donner des indices." + +#: src/pattern-matching/destructuring-structs.md:1 +#, fuzzy +msgid "# Destructuring Structs" +msgstr "# Structures déstructurantes" + +#: src/pattern-matching/destructuring-structs.md:3 +#, fuzzy +msgid "You can also destructure `structs`:" +msgstr "Vous pouvez également déstructurer les `structs` :" + +#: src/pattern-matching/destructuring-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Foo {\n" +" x: (u32, u32),\n" +" y: u32,\n" +"}\n" +"\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let foo = Foo { x: (1, 2), y: 3 };\n" +" match foo {\n" +" Foo { x: (1, b), y } => println!(\"x.0 = 1, b = {b}, y = {y}\"),\n" +" Foo { y: 2, x: i } => println!(\"y = 2, x = {i:?}\"),\n" +" Foo { y, .. } => println!(\"y = {y}, other fields were ignored\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md:23 +#, fuzzy +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." +msgstr "" +"* Modifiez les valeurs littérales dans `foo` pour qu'elles correspondent aux autres modèles.\n" +"* Ajoutez un nouveau champ à `Foo` et modifiez le modèle si nécessaire." + +#: src/pattern-matching/destructuring-arrays.md:1 +#, fuzzy +msgid "# Destructuring Arrays" +msgstr "# Tableaux déstructurants" + +#: src/pattern-matching/destructuring-arrays.md:3 +#, fuzzy +msgid "You can destructure arrays, tuples, and slices by matching on their elements:" +msgstr "Vous pouvez déstructurer des tableaux, des tuples et des tranches en faisant correspondre leurs éléments :" + +#: src/pattern-matching/destructuring-arrays.md:5 +msgid "" +"```rust,editable\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let triple = [0, -2, 3];\n" +" println!(\"Tell me about {triple:?}\");\n" +" match triple {\n" +" [0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" [1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:21 +msgid "" +"* Destructuring of slices of unknown length also works with patterns of fixed length.\n" +"\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" inspect(&[0, -2, 3]);\n" +" inspect(&[0, -2, 3, 4]);\n" +" }\n" +"\n" +" #[rustfmt::skip]\n" +" fn inspect(slice: &[i32]) {\n" +" println!(\"Tell me about {slice:?}\");\n" +" match slice {\n" +" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +" }\n" +" ```\n" +" \n" +"* Create a new pattern using `_` to represent an element. \n" +"* Add more values to the array.\n" +"* Point out that how `..` will expand to account for different number of elements.\n" +"* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`" +msgstr "" + +#: src/pattern-matching/match-guards.md:1 +#, fuzzy +msgid "# Match Guards" +msgstr "# Match Guards" + +#: src/pattern-matching/match-guards.md:3 +#, fuzzy +msgid "" +"When matching, you can add a _guard_ to a pattern. This is an arbitrary Boolean\n" +"expression which will be executed if the pattern matches:" +msgstr "" +"Lors de la correspondance, vous pouvez ajouter un _guard_ à un motif. Ceci est un booléen arbitraire\n" +"expression qui sera exécutée si le motif correspond à :" + +#: src/pattern-matching/match-guards.md:6 +msgid "" +"```rust,editable\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let pair = (2, -2);\n" +" println!(\"Tell me about {pair:?}\");\n" +" match pair {\n" +" (x, y) if x == y => println!(\"These are twins\"),\n" +" (x, y) if x + y == 0 => println!(\"Antimatter, kaboom!\"),\n" +" (x, _) if x % 2 == 1 => println!(\"The first one is odd\"),\n" +" _ => println!(\"No correlation...\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/match-guards.md:23 +#, fuzzy +msgid "" +"* Match guards as a separate syntax feature are important and necessary when we wish to concisely express more complex ideas than patterns alone " +"would allow.\n" +"* They are not the same as separate `if` expression inside of the match arm. An `if` expression inside of the branch block (after `=>`) happens " +"after the match arm is selected. Failing the `if` condition inside of that block won't result in other arms\n" +"of the original `match` expression being considered. \n" +"* You can use the variables defined in the pattern in your if expression.\n" +"* The condition defined in the guard applies to every expression in a pattern with an `|`." +msgstr "" +"* Les gardes de correspondance en tant que fonctionnalité de syntaxe distincte sont importants et nécessaires lorsque nous souhaitons exprimer de " +"manière concise des idées plus complexes que ne le permettraient les modèles seuls.\n" +"* Ils ne sont pas identiques à une expression \"if\" séparée à l'intérieur du bras de match. Une expression `if` à l'intérieur du bloc de branche " +"(après `=>`) se produit après la sélection du bras de correspondance. L'échec de la condition \"si\" à l'intérieur de ce bloc n'entraînera pas " +"d'autres bras\n" +"de l'expression \"match\" d'origine considérée.\n" +"* Vous pouvez utiliser les variables définies dans le modèle dans votre expression if.\n" +"* La condition définie dans la garde s'applique à chaque expression dans un modèle avec un `|`." + +#: src/exercises/day-2/morning.md:1 +#, fuzzy +msgid "# Day 2: Morning Exercises" +msgstr "# Jour 2 : Exercices du matin" + +#: src/exercises/day-2/morning.md:3 +#, fuzzy +msgid "We will look at implementing methods in two contexts:" +msgstr "Nous nous intéresserons à la mise en œuvre des méthodes dans deux contextes :" + +#: src/exercises/day-2/morning.md:5 +#, fuzzy +msgid "" +"* Simple struct which tracks health statistics.\n" +"\n" +"* Multiple structs and enums for a drawing library." +msgstr "" +"* Structure simple qui suit les statistiques de santé.\n" +"\n" +"* Plusieurs structures et énumérations pour une bibliothèque de dessins." + +#: src/exercises/day-2/health-statistics.md:1 +#, fuzzy +msgid "# Health Statistics" +msgstr "# Statistiques de santé" + +#: src/exercises/day-2/health-statistics.md:3 +#, fuzzy +msgid "" +"You're working on implementing a health-monitoring system. As part of that, you\n" +"need to keep track of users' health statistics." +msgstr "" +"Vous travaillez à la mise en place d'un système de surveillance de la santé. Dans le cadre de cela, vous\n" +"besoin de suivre les statistiques de santé des utilisateurs." + +#: src/exercises/day-2/health-statistics.md:6 +#, fuzzy +msgid "" +"You'll start with some stubbed functions in an `impl` block as well as a `User`\n" +"struct definition. Your goal is to implement the stubbed out methods on the\n" +"`User` `struct` defined in the `impl` block." +msgstr "" +"Vous commencerez avec quelques fonctions stub dans un bloc `impl` ainsi qu'un `User`\n" +"définition de structure. Votre objectif est d'implémenter les méthodes tronquées sur le\n" +"`User` `struct` défini dans le bloc `impl`." + +#: src/exercises/day-2/health-statistics.md:10 +#, fuzzy +msgid "" +"Copy the code below to and fill in the missing\n" +"methods:" +msgstr "" +"Copiez le code ci-dessous sur et remplissez les champs manquants\n" +"méthodes :" + +#: src/exercises/day-2/health-statistics.md:13 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"struct User {\n" +" name: String,\n" +" age: u32,\n" +" weight: f32,\n" +"}\n" +"\n" +"impl User {\n" +" pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn name(&self) -> &str {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn age(&self) -> u32 {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn weight(&self) -> f32 {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn set_age(&mut self, new_age: u32) {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn set_weight(&mut self, new_weight: f32) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_weight() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.weight(), 155.2);\n" +"}\n" +"\n" +"#[test]\n" +"fn test_set_age() {\n" +" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.age(), 32);\n" +" bob.set_age(33);\n" +" assert_eq!(bob.age(), 33);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:1 +#, fuzzy +msgid "# Polygon Struct" +msgstr "# Structure Polygone" + +#: src/exercises/day-2/points-polygons.md:3 +#, fuzzy +msgid "" +"We will create a `Polygon` struct which contain some points. Copy the code below\n" +"to and fill in the missing methods to make the\n" +"tests pass:" +msgstr "" +"Nous allons créer une structure `Polygon` contenant des points. Copiez le code ci-dessous\n" +"à et remplissez les méthodes manquantes pour faire le\n" +"les tests passent :" + +#: src/exercises/day-2/points-polygons.md:7 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub struct Point {\n" +" // add fields\n" +"}\n" +"\n" +"impl Point {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Polygon {\n" +" // add fields\n" +"}\n" +"\n" +"impl Polygon {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Circle {\n" +" // add fields\n" +"}\n" +"\n" +"impl Circle {\n" +" // add methods\n" +"}\n" +"\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:117 +#, fuzzy +msgid "" +"Since the method signatures are missing from the problem statements, the key part\n" +"of the exercise is to specify those correctly. You don't have to modify the tests." +msgstr "" +"Étant donné que les signatures de méthode manquent dans les énoncés de problème, la partie clé\n" +"de l'exercice consiste à les spécifier correctement. Vous n'avez pas à modifier les tests." + +#: src/exercises/day-2/points-polygons.md:120 +#, fuzzy +msgid "Other interesting parts of the exercise:" +msgstr "Autres parties intéressantes de l'exercice :" + +#: src/exercises/day-2/points-polygons.md:122 +#, fuzzy +msgid "" +"* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their arguments.\n" +"* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". Note that we do not discuss generics until Day 3." +msgstr "" +"* Dérivez un trait `Copy` pour certaines structures, car dans les tests, les méthodes n'empruntent parfois pas leurs arguments.\n" +"* Découvrez que le trait `Add` doit être implémenté pour que deux objets puissent être ajoutés via \"+\". Notez que nous ne discutons pas des " +"génériques avant le Jour 3." + +#: src/control-flow.md:1 +#, fuzzy +msgid "# Control Flow" +msgstr "# Flux de contrôle" + +#: src/control-flow.md:3 +#, fuzzy +msgid "" +"As we have seen, `if` is an expression in Rust. It is used to conditionally\n" +"evaluate one of two blocks, but the blocks can have a value which then becomes\n" +"the value of the `if` expression. Other control flow expressions work similarly\n" +"in Rust." +msgstr "" +"Comme nous l'avons vu, `if` est une expression en Rust. Il est utilisé pour conditionnellement\n" +"évaluer l'un des deux blocs, mais les blocs peuvent avoir une valeur qui devient alors\n" +"la valeur de l'expression \"if\". D'autres expressions de flux de contrôle fonctionnent de manière similaire\n" +"à Rust." + +#: src/control-flow/blocks.md:1 +#, fuzzy +msgid "# Blocks" +msgstr "# Blocs" + +#: src/control-flow/blocks.md:3 +#, fuzzy +msgid "" +"A block in Rust has a value and a type: the value is the last expression of the\n" +"block:" +msgstr "" +"Un bloc en Rust a une valeur et un type : la valeur est la dernière expression du\n" +"bloc:" + +#: src/control-flow/blocks.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = {\n" +" let y = 10;\n" +" println!(\"y: {y}\");\n" +" let z = {\n" +" let w = {\n" +" 3 + 4\n" +" };\n" +" println!(\"w: {w}\");\n" +" y * w\n" +" };\n" +" println!(\"z: {z}\");\n" +" z - y\n" +" };\n" +" println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:25 +#, fuzzy +msgid "" +"The same rule is used for functions: the value of the function body is the\n" +"return value:" +msgstr "" +"La même règle est utilisée pour les fonctions : la valeur du corps de la fonction est le\n" +"valeur de retour :" + +#: src/control-flow/blocks.md:28 +msgid "" +"```rust,editable\n" +"fn double(x: i32) -> i32 {\n" +" x + x\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"doubled: {}\", double(7));\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:38 +msgid "However if the last expression ends with `;`, then the resulting value and type is `()`." +msgstr "" + +#: src/control-flow/blocks.md:43 +#, fuzzy +msgid "" +"* The point of this slide is to show that blocks have a type and value in Rust. \n" +"* You can show how the value of the block changes by changing the last line in the block. For instance, adding/removing a semicolon or using a " +"`return`.\n" +" " +msgstr "" +"* Le but de cette diapositive est de montrer que les blocs ont un type et une valeur dans Rust.\n" +"* Vous pouvez montrer comment la valeur du bloc change en modifiant la dernière ligne du bloc. Par exemple, ajouter/supprimer un point-virgule ou " +"utiliser un \"retour\".\n" +" " + +#: src/control-flow/if-expressions.md:1 +#, fuzzy +msgid "# `if` expressions" +msgstr "# expressions \"si\"" + +#: src/control-flow/if-expressions.md:3 +#, fuzzy +msgid "You use `if` very similarly to how you would in other languages:" +msgstr "Vous utilisez `if` de manière très similaire à la façon dont vous le feriez dans d'autres langues :" + +#: src/control-flow/if-expressions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" if x % 2 == 0 {\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:16 +#, fuzzy +msgid "In addition, you can use it as an expression. This does the same as above:" +msgstr "De plus, vous pouvez l'utiliser comme expression. Cela fait la même chose que ci-dessus:" + +#: src/control-flow/if-expressions.md:18 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:31 +msgid "" +"Because `if` is an expression and must have a particular type, both of its branch blocks must have the same type. Consider showing what happens if " +"you add `;` after `x / 2` in the second example." +msgstr "" + +#: src/control-flow/if-let-expressions.md:1 +#, fuzzy +msgid "# `if let` expressions" +msgstr "# expressions `si nous allons`" + +#: 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 "Si vous voulez faire correspondre une valeur à un modèle, vous pouvez utiliser `if let` :" + +#: src/control-flow/if-let-expressions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let arg = std::env::args().next();\n" +" if let Some(value) = arg {\n" +" println!(\"Program name: {value}\");\n" +" } else {\n" +" println!(\"Missing name?\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-let-expressions.md:16 src/control-flow/while-let-expressions.md:21 src/control-flow/match-expressions.md:22 +#, fuzzy +msgid "" +"See [pattern matching](../pattern-matching.md) for more details on patterns in\n" +"Rust." +msgstr "" +"Voir [pattern matching](../pattern-matching.md) pour plus de détails sur les modèles dans\n" +"Rouiller." + +#: src/control-flow/if-let-expressions.md:21 +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" +"* A common usage is handling `Some` values when working with `Option`.\n" +"* Unlike `match`, `if let` does not support guard clauses for pattern matching.\n" +"* Since 1.65, a similar [let-else](https://doc.rust-lang.org/rust-by-example/flow_control/let_else.html) construct allows to do a destructuring " +"assignment, or if it fails, have a non-returning block branch (panic/return/break/continue):\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" println!(\"{:?}\", second_word_to_upper(\"foo bar\"));\n" +" }\n" +" \n" +" fn second_word_to_upper(s: &str) -> Option {\n" +" let mut it = s.split(' ');\n" +" let (Some(_), Some(item)) = (it.next(), it.next()) else {\n" +" return None;\n" +" };\n" +" Some(item.to_uppercase())\n" +" }" +msgstr "" + +#: src/control-flow/while-expressions.md:1 +#, fuzzy +msgid "# `while` expressions" +msgstr "# Expressions `while`" + +#: src/control-flow/while-expressions.md:3 +#, fuzzy +msgid "The `while` keyword works very similar to other languages:" +msgstr "Le mot-clé `while` fonctionne de manière très similaire aux autres langages :" + +#: src/control-flow/while-expressions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" while x != 1 {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/while-let-expressions.md:1 +#, fuzzy +msgid "# `while let` expressions" +msgstr "# expressions `while let`" + +#: 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:" +msgstr "" +"Comme avec `if`, il existe une variante `while let` qui teste à plusieurs reprises une valeur\n" +"contre un modèle :" + +#: src/control-flow/while-let-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +"\n" +" while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/while-let-expressions.md:17 +#, fuzzy +msgid "" +"Here the iterator returned by `v.iter()` will return a `Option` on every\n" +"call to `next()`. It returns `Some(x)` until it is done, after which it will\n" +"return `None`. The `while let` lets us keep iterating through all items." +msgstr "" +"Ici, l'itérateur renvoyé par `v.iter()` renverra une `Option` à chaque\n" +"appel à `next()`. Il renvoie `Some(x)` jusqu'à ce qu'il soit terminé, après quoi il\n" +"renvoie \"Aucun\". Le `while let` nous permet de continuer à parcourir tous les éléments." + +#: src/control-flow/while-let-expressions.md:27 +#, fuzzy +msgid "" +"* Point out that the `while let` loop will keep going as long as the value matches the pattern.\n" +"* You could rewrite the `while let` loop as an infinite loop with an if statement that breaks when there is no value to unwrap for `iter.next()`. " +"The `while let` provides syntactic sugar for the above scenario.\n" +" " +msgstr "" +"* Soulignez que la boucle `while let` continuera tant que la valeur correspond au modèle.\n" +"* Vous pouvez réécrire la boucle `while let` comme une boucle infinie avec une instruction if qui s'interrompt lorsqu'il n'y a pas de valeur à " +"déballer pour `iter.next()`. Le `while let` fournit du sucre syntaxique pour le scénario ci-dessus.\n" +" " + +#: src/control-flow/for-expressions.md:1 +#, fuzzy +msgid "# `for` expressions" +msgstr "# expressions `pour`" + +#: src/control-flow/for-expressions.md:3 +#, fuzzy +msgid "" +"The `for` expression is closely related to the `while let` expression. It will\n" +"automatically call `into_iter()` on the expression and then iterate over it:" +msgstr "" +"L'expression `for` est étroitement liée à l'expression `while let`. Ce sera\n" +"appelez automatiquement `into_iter()` sur l'expression, puis parcourez-la :" + +#: src/control-flow/for-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +"\n" +" for x in v {\n" +" println!(\"x: {x}\");\n" +" }\n" +" \n" +" for i in (0..10).step_by(2) {\n" +" println!(\"i: {i}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/for-expressions.md:20 +#, fuzzy +msgid "You can use `break` and `continue` here as usual." +msgstr "Vous pouvez utiliser `break` et `continue` ici comme d'habitude." + +#: src/control-flow/for-expressions.md:24 +#, fuzzy +msgid "" +"* Index iteration is not a special syntax in Rust for just that case.\n" +"* `(0..10)` is a range that implements an `Iterator` trait. \n" +"* `step_by` is a method that returns another `Iterator` that skips every other element. \n" +"* Modify the elements in the vector and explain the compiler errors. Change vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." +msgstr "" +"* L'itération d'index n'est pas une syntaxe spéciale dans Rust pour ce cas précis.\n" +"* `(0..10)` est une plage qui implémente un trait `Iterator`.\n" +"* `step_by` est une méthode qui renvoie un autre `Iterator` qui saute tous les autres éléments.\n" +"* Modifier les éléments du vecteur et expliquer les erreurs du compilateur. Modifiez le vecteur `v` pour qu'il soit modifiable et la boucle for en " +"`for x in v.iter_mut()`." + +#: src/control-flow/loop-expressions.md:1 +#, fuzzy +msgid "# `loop` expressions" +msgstr "# expressions de \"boucle\"" + +#: 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:" +msgstr "" +"Enfin, il existe un mot-clé `loop` qui crée une boucle sans fin. Ici, vous devez\n" +"soit `break` ou `return` pour arrêter la boucle :" + +#: src/control-flow/loop-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" loop {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" if x == 1 {\n" +" break;\n" +" }\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/loop-expressions.md:25 +#, fuzzy +msgid "* Break the `loop` with a value (e.g. `break 8`) and print it out." +msgstr "* Cassez la `boucle` avec une valeur (par exemple `break 8`) et imprimez-la." + +#: src/control-flow/match-expressions.md:1 +#, fuzzy +msgid "# `match` expressions" +msgstr "# expressions \"correspondantes\"" + +#: 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:" +msgstr "" +"Le mot clé `match` est utilisé pour faire correspondre une valeur à un ou plusieurs modèles. Dans\n" +"en ce sens, cela fonctionne comme une série d'expressions \"if let\":" + +#: src/control-flow/match-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" match std::env::args().next().as_deref() {\n" +" Some(\"cat\") => println!(\"Will do cat things\"),\n" +" Some(\"ls\") => println!(\"Will ls some files\"),\n" +" Some(\"mv\") => println!(\"Let's move some files\"),\n" +" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" +" None => println!(\"Hmm, no program name?\"),\n" +" _ => println!(\"Unknown program name!\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/match-expressions.md:19 +#, fuzzy +msgid "" +"Like `if let`, each match arm must have the same type. The type is the last\n" +"expression of the block, if any. In the example above, the type is `()`." +msgstr "" +"Comme `if let`, chaque bras de correspondance doit avoir le même type. Le type est le dernier\n" +"expression du bloc, le cas échéant. Dans l'exemple ci-dessus, le type est `()`." + +#: src/control-flow/match-expressions.md:27 +#, fuzzy +msgid "" +"* Save the match expression to a variable and print it out.\n" +"* Remove `.as_deref()` and explain the error.\n" +" * `std::env::args().next()` returns an `Option`, but we cannot match against `String`.\n" +" * `as_deref()` transforms an `Option` to `Option<&T::Target>`. In our case, this turns `Option` into `Option<&str>`.\n" +" * We can now use pattern matching to match against the `&str` inside `Option`." +msgstr "" +"* Enregistrez l'expression de correspondance dans une variable et imprimez-la.\n" +"* Supprimez `.as_deref()` et expliquez l'erreur.\n" +" * `std::env::args().next()` renvoie une `Option`, mais nous ne pouvons pas comparer `String`.\n" +" * `as_deref()` transforme une `Option` en `Option<&T::Target>`. Dans notre cas, cela transforme `Option` en `Option<&str>`.\n" +" * Nous pouvons maintenant utiliser le pattern matching pour faire correspondre le `&str` à l'intérieur de `Option`." + +#: src/control-flow/break-continue.md:1 +#, fuzzy +msgid "# `break` and `continue`" +msgstr "# `pause` et `continue`" + +#: src/control-flow/break-continue.md:3 +#, 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:" +msgstr "" +"Si vous voulez quitter une boucle plus tôt, utilisez `break`, si vous voulez commencer immédiatement\n" +"la prochaine itération utilise `continue`. `continue` et `break` peuvent éventuellement\n" +"prenez un argument d'étiquette qui est utilisé pour sortir des boucles imbriquées :" + +#: src/control-flow/break-continue.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +" 'outer: while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" let mut i = 0;\n" +" while i < x {\n" +" println!(\"x: {x}, i: {i}\");\n" +" i += 1;\n" +" if i == 3 {\n" +" break 'outer;\n" +" }\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/break-continue.md:25 +#, fuzzy +msgid "In this case we break the outer loop after 3 iterations of the inner loop." +msgstr "Dans ce cas, nous cassons la boucle externe après 3 itérations de la boucle interne." + +#: src/std.md:1 +#, fuzzy +msgid "# Standard Library" +msgstr "# Bibliothèque standard" + +#: src/std.md:3 +#, fuzzy +msgid "" +"Rust comes with a standard library which helps establish a set of common types\n" +"used by Rust library and programs. This way, two libraries can work together\n" +"smoothly because they both use the same `String` type." +msgstr "" +"Rust est livré avec une bibliothèque standard qui permet d'établir un ensemble de types communs\n" +"utilisé par la bibliothèque et les programmes Rust. De cette façon, deux bibliothèques peuvent travailler ensemble\n" +"en douceur car ils utilisent tous les deux le même type `String`." + +#: src/std.md:7 +#, fuzzy +msgid "The common vocabulary types include:" +msgstr "Les types de vocabulaire courants comprennent :" + +#: src/std.md:9 +#, fuzzy +msgid "" +"* [`Option` and `Result`](std/option-result.md) types: used for optional values\n" +" and [error handling](error-handling.md).\n" +"\n" +"* [`String`](std/string.md): the default string type used for owned data.\n" +"\n" +"* [`Vec`](std/vec.md): a standard extensible vector.\n" +"\n" +"* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" +" algorithm.\n" +"\n" +"* [`Box`](std/box.md): an owned pointer for heap-allocated data.\n" +"\n" +"* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated data." +msgstr "" +"* Types [`Option` et `Result`](std/option-result.md) : utilisés pour les valeurs facultatives\n" +" et [gestion des erreurs] (error-handling.md).\n" +"\n" +"* [`String`](std/string.md) : le type de chaîne par défaut utilisé pour les données détenues.\n" +"\n" +"* [`Vec`](std/vec.md) : un vecteur extensible standard.\n" +"\n" +"* [`HashMap`](std/hashmap.md) : un type de carte de hachage avec un hachage configurable\n" +" algorithme.\n" +"\n" +"* [`Box`](std/box.md) : un pointeur propriétaire pour les données allouées par tas.\n" +"\n" +"* [`Rc`](std/rc.md) : un pointeur partagé compté par référence pour les données allouées par tas." + +#: src/std.md:25 +#, fuzzy +msgid "" +" * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. \n" +" * `core` includes the most basic types and functions that don't depend on `libc`, allocator or\n" +" even the presence of an operating system. \n" +" * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`.\n" +" * Embedded Rust applications often only use `core`, and sometimes `alloc`." +msgstr "" +" * En fait, Rust contient plusieurs couches de la bibliothèque standard : `core`, `alloc` et `std`.\n" +" * `core` inclut les types et fonctions les plus basiques qui ne dépendent pas de `libc`, de l'allocateur ou\n" +" même la présence d'un système d'exploitation.\n" +" * `alloc` inclut les types qui nécessitent un allocateur de tas global, tels que `Vec`, `Box` et `Arc`.\n" +" * Les applications Embedded Rust n'utilisent souvent que \"core\" et parfois \"alloc\"." + +#: src/std/option-result.md:1 +#, fuzzy +msgid "# `Option` and `Result`" +msgstr "# `Option` et `Résultat`" + +#: src/std/option-result.md:3 +#, fuzzy +msgid "The types represent optional data:" +msgstr "Les types représentent des données facultatives :" + +#: src/std/option-result.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let numbers = vec![10, 20, 30];\n" +" let first: Option<&i8> = numbers.first();\n" +" println!(\"first: {first:?}\");\n" +"\n" +" let idx: Result = numbers.binary_search(&10);\n" +" println!(\"idx: {idx:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/option-result.md:18 +#, fuzzy +msgid "" +"* `Option` and `Result` are widely used not just in the standard library.\n" +"* `Option<&T>` has zero space overhead compared to `&T`.\n" +"* `Result` is the standard type to implement error handling as we will see on Day 3.\n" +"* `binary_search` returns `Result`.\n" +" * If found, `Result::Ok` holds the index where the element is found.\n" +" * Otherwise, `Result::Err` contains the index where such an element should be inserted." +msgstr "" +"* `Option` et `Result` sont largement utilisés, pas seulement dans la bibliothèque standard.\n" +"* `Option<&T>` n'a aucune surcharge d'espace par rapport à `&T`.\n" +"* `Result` est le type standard pour implémenter la gestion des erreurs, comme nous le verrons le jour 3.\n" +"* `binary_search` renvoie `Result`.\n" +" * Si trouvé, `Result::Ok` contient l'index où se trouve l'élément.\n" +" * Sinon, `Result::Err` contient l'index où un tel élément doit être inséré." + +#: src/std/string.md:1 +#, fuzzy +msgid "# String" +msgstr "# Chaîne" + +#: src/std/string.md:3 +#, fuzzy +msgid "[`String`][1] is the standard heap-allocated growable UTF-8 string buffer:" +msgstr "[`String`][1] est le tampon de chaîne UTF-8 évolutif standard alloué par tas :" + +#: src/std/string.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut s1 = String::new();\n" +" s1.push_str(\"Hello\");\n" +" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());\n" +"\n" +" let mut s2 = String::with_capacity(s1.len() + 1);\n" +" s2.push_str(&s1);\n" +" s2.push('!');\n" +" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());\n" +"\n" +" let s3 = String::from(\"🇨🇭\");\n" +" println!(\"s3: len = {}, number of chars = {}\", s3.len(),\n" +" s3.chars().count());\n" +"}\n" +"```" +msgstr "" + +#: src/std/string.md:22 +#, fuzzy +msgid "" +"`String` implements [`Deref`][2], which means that you can call all\n" +"`str` methods on a `String`." +msgstr "" +"`String` implémente [`Deref`][2], ce qui signifie que vous pouvez appeler tous\n" +"Méthodes `str` sur une `String`." + +#: src/std/string.md:30 +msgid "" +"* `String::new` returns a new empty string, use `String::with_capacity` when you know how much data you want to push to the string.\n" +"* `String::len` returns the size of the `String` in bytes (which can be different from its length in characters).\n" +"* `String::chars` returns an iterator over the actual characters. Note that a `char` can be different from what a human will consider a \"character" +"\" due to [grapheme clusters](https://docs.rs/unicode-segmentation/latest/unicode_segmentation/struct.Graphemes.html).\n" +"* When people refer to strings they could either be talking about `&str` or `String`. \n" +"* When a type implements `Deref`, the compiler will let you transparently call methods from `T`.\n" +" * `String` implements `Deref` which transparently gives it access to `str`'s methods.\n" +" * 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." +msgstr "" + +#: src/std/vec.md:1 +#, fuzzy +msgid "# `Vec`" +msgstr "# `Vec`" + +#: src/std/vec.md:3 +#, fuzzy +msgid "[`Vec`][1] is the standard resizable heap-allocated buffer:" +msgstr "[`Vec`][1] est le tampon standard redimensionnable alloué au tas :" + +#: src/std/vec.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut v1 = Vec::new();\n" +" v1.push(42);\n" +" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());\n" +"\n" +" let mut v2 = Vec::with_capacity(v1.len() + 1);\n" +" v2.extend(v1.iter());\n" +" v2.push(9999);\n" +" println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());\n" +"\n" +" // Canonical macro to initialize a vector with elements.\n" +" let mut v3 = vec![0, 0, 1, 2, 3, 4];\n" +"\n" +" // Retain only the even elements.\n" +" v3.retain(|x| x % 2 == 0);\n" +" println!(\"{v3:?}\");\n" +"\n" +" // Remove consecutive duplicates.\n" +" v3.dedup();\n" +" println!(\"{v3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/vec.md:29 +#, fuzzy +msgid "" +"`Vec` implements [`Deref`][2], which means that you can call slice\n" +"methods on a `Vec`." +msgstr "" +"`Vec` implémente [`Deref`][2], ce qui signifie que vous pouvez appeler slice\n" +"méthodes sur un `Vec`." + +#: src/std/vec.md:37 +msgid "" +"* `Vec` is a type of collection, along with `String` and `HashMap`. The data it contains is stored\n" +" on the heap. This means the amount of data doesn't need to be known at compile time. It can grow\n" +" or shrink at runtime.\n" +"* Notice how `Vec` is a generic type too, but you don't have to specify `T` explicitly. As always\n" +" with Rust type inference, the `T` was established during the first `push` call.\n" +"* `vec![...]` is a canonical macro to use instead of `Vec::new()` and it supports adding initial\n" +" elements to the vector.\n" +"* To index the vector you use `[` `]`, but they will panic if out of bounds. Alternatively, using\n" +" `get` will return an `Option`. The `pop` function will remove the last element.\n" +"* Show iterating over a vector and mutating the value:\n" +" `for e in &mut v { *e += 50; }`" +msgstr "" + +#: src/std/hashmap.md:1 +#, fuzzy +msgid "# `HashMap`" +msgstr "# `HashMap`" + +#: src/std/hashmap.md:3 +#, fuzzy +msgid "Standard hash map with protection against HashDoS attacks:" +msgstr "Carte de hachage standard avec protection contre les attaques HashDoS :" + +#: src/std/hashmap.md:5 +msgid "" +"```rust,editable\n" +"use std::collections::HashMap;\n" +"\n" +"fn main() {\n" +" let mut page_counts = HashMap::new();\n" +" page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), 207);\n" +" page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" +" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);\n" +"\n" +" if !page_counts.contains_key(\"Les Misérables\") {\n" +" println!(\"We know about {} books, but not Les Misérables.\",\n" +" page_counts.len());\n" +" }\n" +"\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" +" match page_counts.get(book) {\n" +" Some(count) => println!(\"{book}: {count} pages\"),\n" +" None => println!(\"{book} is unknown.\")\n" +" }\n" +" }\n" +"\n" +" // Use the .entry() method to insert a value if nothing is found.\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" +" let page_count: &mut i32 = page_counts.entry(book.to_string()).or_insert(0);\n" +" *page_count += 1;\n" +" }\n" +"\n" +" println!(\"{page_counts:#?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/hashmap.md:38 +msgid "" +"* `HashMap` is not defined in the prelude and needs to be brought into scope.\n" +"* Try the following lines of code. The first line will see if a book is in the hashmap and if not return an alternative value. The second line will " +"insert the alternative value in the hashmap if the book is not found.\n" +"\n" +" ```rust,ignore\n" +" let pc1 = page_counts\n" +" .get(\"Harry Potter and the Sorcerer's Stone \")\n" +" .unwrap_or(&336);\n" +" let pc2 = page_counts\n" +" .entry(\"The Hunger Games\".to_string())\n" +" .or_insert(374);\n" +" ```\n" +"* Unlike `vec!`, there is unfortunately no standard `hashmap!` macro.\n" +" * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], which allows us to easily initialize a hash map from a literal array:\n" +"\n" +" ```rust,ignore\n" +" let page_counts = HashMap::from([\n" +" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" +" (\"The Hunger Games\".to_string(), 374),\n" +" ]);\n" +" ```\n" +"\n" +" * Alternatively HashMap can be built from any `Iterator` which yields key-value tuples.\n" +"* We are showing `HashMap`, and avoid using `&str` as key to make examples easier. Using references in collections can, of course, be " +"done,\n" +" but it can lead into complications with the borrow checker.\n" +" * Try removing `to_string()` from the example above and see if it still compiles. Where do you think we might run into issues?" +msgstr "" + +#: src/std/box.md:1 +#, fuzzy +msgid "# `Box`" +msgstr "# `Boîte`" + +#: src/std/box.md:3 +#, fuzzy +msgid "[`Box`][1] is an owned pointer to data on the heap:" +msgstr "[`Box`][1] est un pointeur propriétaire vers des données sur le tas :" + +#: src/std/box.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let five = Box::new(5);\n" +" println!(\"five: {}\", *five);\n" +"}\n" +"```" +msgstr "" + +#: src/std/box.md:13 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - -. .- - - - - - -.\n" +": : : :\n" +": five : : :\n" +": +-----+ : : +-----+ :\n" +": | o---|---+-----+-->| 5 | :\n" +": +-----+ : : +-----+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - -' `- - - - - - -'\n" +"```" +msgstr "" + +#: src/std/box.md:26 +#, fuzzy +msgid "" +"`Box` implements `Deref`, which means that you can [call methods\n" +"from `T` directly on a `Box`][2]." +msgstr "" +"`Box` implémente `Deref`, ce qui signifie que vous pouvez [appeler des méthodes\n" +"depuis `T` directement sur une `Box`][2]." + +#: src/std/box.md:34 +#, fuzzy +msgid "" +"* `Box` is like `std::unique_ptr` in C++, except that it's guaranteed to be not null. \n" +"* In the above example, you can even leave out the `*` in the `println!` statement thanks to `Deref`. \n" +"* A `Box` can be useful when you:\n" +" * have a type whose size that can't be known at compile time, but the Rust compiler wants to know an exact size.\n" +" * want to transfer ownership of a large amount of data. To avoid copying large amounts of data on the stack, instead store the data on the heap " +"in a `Box` so only the pointer is moved." +msgstr "" +"* `Box` est comme `std::unique_ptr` en C++, sauf qu'il est garanti qu'il n'est pas nul.\n" +"* Dans l'exemple ci-dessus, vous pouvez même omettre le `*` dans l'instruction `println!` grâce à `Deref`.\n" +"* Une `Box` peut être utile lorsque vous :\n" +" * avoir un type dont la taille ne peut pas être connue au moment de la compilation, mais le compilateur Rust veut connaître une taille exacte.\n" +" * souhaitez transférer la propriété d'une grande quantité de données. Pour éviter de copier de grandes quantités de données sur la pile, stockez " +"plutôt les données sur le tas dans une `Box` afin que seul le pointeur soit déplacé." + +#: src/std/box-recursive.md:1 +#, fuzzy +msgid "# Box with Recursive Data Structures" +msgstr "# Boîte avec des structures de données récursives" + +#: src/std/box-recursive.md:3 +#, fuzzy +msgid "Recursive data types or data types with dynamic sizes need to use a `Box`:" +msgstr "Les types de données récursifs ou les types de données avec des tailles dynamiques doivent utiliser une `Box` :" + +#: src/std/box-recursive.md:5 src/std/box-niche.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"enum List {\n" +" Cons(T, Box>),\n" +" Nil,\n" +"}\n" +"\n" +"fn main() {\n" +" let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));\n" +" println!(\"{list:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/box-recursive.md:18 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": list : : :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----+ :\n" +": | Cons | 1 | o--+----+-----+--->| Cons | 2 | o--+--->| Nil | // | // | :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----+ :\n" +": : : :\n" +": : : :\n" +"'- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/std/box-recursive.md:33 +#, fuzzy +msgid "" +"* If the `Box` was not used here and we attempted to embed a `List` directly into the `List`,\n" +"the compiler would not compute a fixed size of the struct in memory, it would look infinite.\n" +"\n" +"* `Box` solves this problem as it has the same size as a regular pointer and just points at the next\n" +"element of the `List` in the heap.\n" +"\n" +"* Remove the `Box` in the List definition and show the compiler error. \"Recursive with indirection\" is a hint you might want to use a Box or " +"reference of some kind, instead of storing a value directly. \n" +" " +msgstr "" +"* Si la `Box` n'a pas été utilisée ici et que nous avons essayé d'intégrer une `List` directement dans la `List`,\n" +"le compilateur ne calculerait pas une taille fixe de la structure en mémoire, elle semblerait infinie.\n" +"\n" +"* `Box` résout ce problème car il a la même taille qu'un pointeur normal et pointe simplement vers le prochain\n" +"élément de la `Liste` dans le tas.\n" +"\n" +"* Supprimez la `Box` dans la définition de la liste et affichez l'erreur du compilateur. \"Récursif avec indirection\" est un indice que vous " +"voudrez peut-être utiliser une boîte ou une référence quelconque, au lieu de stocker une valeur directement.\n" +" " + +#: src/std/box-niche.md:1 +#, fuzzy +msgid "# Niche Optimization" +msgstr "# Optimisation de niche" + +#: src/std/box-niche.md:16 +#, fuzzy +msgid "" +"A `Box` cannot be empty, so the pointer is always valid and non-`null`. This\n" +"allows the compiler to optimize the memory layout:" +msgstr "" +"Une `Box` ne peut pas être vide, donc le pointeur est toujours valide et non `null`. Ce\n" +"permet au compilateur d'optimiser la disposition de la mémoire :" + +#: src/std/box-niche.md:19 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": list : : :\n" +": +----+----+ : : +----+----+ +----+------+ :\n" +": | 1 | o--+-----------+-----+--->| 2 | o--+--->| // | null | :\n" +": +----+----+ : : +----+----+ +----+------+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/std/rc.md:1 +#, fuzzy +msgid "# `Rc`" +msgstr "# `Rc`" + +#: src/std/rc.md:3 +#, fuzzy +msgid "" +"[`Rc`][1] is a reference-counted shared pointer. Use this when you need to refer\n" +"to the same data from multiple places:" +msgstr "" +"[`Rc`][1] est un pointeur partagé compté par référence. Utilisez-le lorsque vous avez besoin de vous référer\n" +"aux mêmes données depuis plusieurs endroits :" + +#: src/std/rc.md:6 +msgid "" +"```rust,editable\n" +"use std::rc::Rc;\n" +"\n" +"fn main() {\n" +" let mut a = Rc::new(10);\n" +" let mut b = a.clone();\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/rc.md:18 +#, fuzzy +msgid "" +"* If you need to mutate the data inside an `Rc`, you will need to wrap the data in\n" +" a type such as [`Cell` or `RefCell`][2].\n" +"* See [`Arc`][3] if you are in a multi-threaded context.\n" +"* You can *downgrade* a shared pointer into a [`Weak`][4] pointer to create cycles\n" +" that will get dropped." +msgstr "" +"* Si vous avez besoin de muter les données à l'intérieur d'un `Rc`, vous devrez envelopper les données dans\n" +" un type tel que [`Cell` ou `RefCell`][2].\n" +"* Voir [`Arc`][3] si vous êtes dans un contexte multi-thread.\n" +"* Vous pouvez *rétrograder* un pointeur partagé en un pointeur [`Weak`][4] pour créer des cycles\n" +" qui va tomber." + +#: src/std/rc.md:31 +#, fuzzy +msgid "" +"* `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" +"* `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" +" create cycles that will be dropped properly (likely in combination with\n" +" `RefCell`)." +msgstr "" +"* Le comptage de `Rc` garantit que sa valeur contenue est valide tant qu'il y a des références.\n" +"* Comme `std::shared_ptr` de C++.\n" +"* `clone` est bon marché : il crée un pointeur vers la même allocation et augmente le nombre de références. Ne crée pas de clone profond et peut " +"généralement être ignoré lors de la recherche de problèmes de performances dans le code.\n" +"* `make_mut` clone en fait la valeur interne si nécessaire (\"clone-on-write\") et renvoie une référence mutable.\n" +"* Utilisez `Rc::strong_count` pour vérifier le nombre de références.\n" +"* Comparez les différents types de données mentionnés. `Box` active les emprunts (im)mutables qui sont appliqués au moment de la compilation. " +"`RefCell` active les emprunts (im)mutables qui sont appliqués au moment de l'exécution et paniqueront s'ils échouent au moment de l'exécution.\n" +"* Vous pouvez `downgrader()` un `Rc` en un objet *faiblement compté en référence* pour\n" +" créer des cycles qui seront supprimés correctement (probablement en combinaison avec\n" +" `RefCell`)." + +#: src/std/rc.md:41 +msgid "" +"```rust,editable\n" +"use std::rc::{Rc, Weak};\n" +"use std::cell::RefCell;\n" +"\n" +"#[derive(Debug)]\n" +"struct Node {\n" +" value: i64,\n" +" parent: Option>>,\n" +" children: Vec>>,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut root = Rc::new(RefCell::new(Node {\n" +" value: 42,\n" +" parent: None,\n" +" children: vec![],\n" +" }));\n" +" let child = Rc::new(RefCell::new(Node {\n" +" value: 43,\n" +" children: vec![],\n" +" parent: Some(Rc::downgrade(&root))\n" +" }));\n" +" root.borrow_mut().children.push(child);\n" +"\n" +" println!(\"graph: {root:#?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/modules.md:1 +#, fuzzy +msgid "# Modules" +msgstr "# Modules" + +#: src/modules.md:3 +#, fuzzy +msgid "We have seen how `impl` blocks let us namespace functions to a type." +msgstr "Nous avons vu comment les blocs `impl` nous permettent de faire fonctionner l'espace de noms sur un type." + +#: src/modules.md:5 +#, fuzzy +msgid "Similarly, `mod` lets us namespace types and functions:" +msgstr "De même, `mod` nous permet d'utiliser des types et des fonctions d'espace de noms :" + +#: src/modules.md:7 +msgid "" +"```rust,editable\n" +"mod foo {\n" +" pub fn do_something() {\n" +" println!(\"In the foo module\");\n" +" }\n" +"}\n" +"\n" +"mod bar {\n" +" pub fn do_something() {\n" +" println!(\"In the bar module\");\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" foo::do_something();\n" +" bar::do_something();\n" +"}\n" +"```" +msgstr "" + +#: src/modules.md:28 +#, fuzzy +msgid "" +"* Packages provide functionality and include a `Cargo.toml` file that describes how to build a bundle of 1+ crates.\n" +"* Crates are a tree of modules, where a binary crate creates an executable and a library crate compiles to a library.\n" +"* Modules define organization, scope, and are the focus of this section." +msgstr "" +"* Les packages fournissent des fonctionnalités et incluent un fichier `Cargo.toml` qui décrit comment créer un ensemble de 1+ caisses.\n" +"* Les caisses sont un arbre de modules, où une caisse binaire crée un exécutable et une caisse de bibliothèque se compile en une bibliothèque.\n" +"* Les modules définissent l'organisation, la portée et sont au centre de cette section." + +#: src/modules/visibility.md:1 +#, fuzzy +msgid "# Visibility" +msgstr "# Visibilité" + +#: src/modules/visibility.md:3 +#, fuzzy +msgid "Modules are a privacy boundary:" +msgstr "Les modules sont une limite de confidentialité :" + +#: src/modules/visibility.md:5 +#, fuzzy +msgid "" +"* Module items are private by default (hides implementation details).\n" +"* Parent and sibling items are always visible.\n" +"* In other words, if an item is visible in module `foo`, it's visible in all the\n" +" descendants of `foo`." +msgstr "" +"* Les éléments du module sont privés par défaut (cache les détails d'implémentation).\n" +"* Les éléments parents et frères sont toujours visibles.\n" +"* En d'autres termes, si un élément est visible dans le module `foo`, il est visible dans tous les\n" +" descendants de `foo`." + +#: src/modules/visibility.md:10 +msgid "" +"```rust,editable\n" +"mod outer {\n" +" fn private() {\n" +" println!(\"outer::private\");\n" +" }\n" +"\n" +" pub fn public() {\n" +" println!(\"outer::public\");\n" +" }\n" +"\n" +" mod inner {\n" +" fn private() {\n" +" println!(\"outer::inner::private\");\n" +" }\n" +"\n" +" pub fn public() {\n" +" println!(\"outer::inner::public\");\n" +" super::private();\n" +" }\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" outer::public();\n" +"}\n" +"```" +msgstr "" + +#: src/modules/visibility.md:39 +#, fuzzy +msgid "* Use the `pub` keyword to make modules public." +msgstr "* Utilisez le mot-clé `pub` pour rendre les modules publics." + +#: src/modules/visibility.md:41 +#, fuzzy +msgid "Additionally, there are advanced `pub(...)` specifiers to restrict the scope of public visibility." +msgstr "De plus, il existe des spécificateurs avancés `pub(...)` pour restreindre la portée de la visibilité publique." + +#: src/modules/visibility.md:43 +#, fuzzy +msgid "" +"* See the [Rust Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself).\n" +"* Configuring `pub(crate)` visibility is a common pattern.\n" +"* Less commonly, you can give visibility to a specific path.\n" +"* In any case, visibility must be granted to an ancestor module (and all of its descendants)." +msgstr "" +"* Voir la [Rust Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself).\n" +"* La configuration de la visibilité de `pub(crate)` est un modèle courant.\n" +"* Plus rarement, vous pouvez donner de la visibilité à un chemin spécifique.\n" +"* Dans tous les cas, la visibilité doit être accordée à un module ancêtre (et à tous ses descendants)." + +#: src/modules/paths.md:1 +#, fuzzy +msgid "# Paths" +msgstr "# Chemins" + +#: src/modules/paths.md:3 +#, fuzzy +msgid "Paths are resolved as follows:" +msgstr "Les chemins sont résolus comme suit :" + +#: src/modules/paths.md:5 +#, fuzzy +msgid "" +"1. As a relative path:\n" +" * `foo` or `self::foo` refers to `foo` in the current module,\n" +" * `super::foo` refers to `foo` in the parent module.\n" +"\n" +"2. As an absolute path:\n" +" * `crate::foo` refers to `foo` in the root of the current crate,\n" +" * `bar::foo` refers to `foo` in the `bar` crate." +msgstr "" +"1. En tant que chemin relatif :\n" +" * `foo` ou `self::foo` fait référence à `foo` dans le module actuel,\n" +" * `super::foo` fait référence à `foo` dans le module parent.\n" +"\n" +"2. En tant que chemin absolu :\n" +" * `crate::foo` fait référence à `foo` à la racine du crate actuel,\n" +" * `bar::foo` fait référence à `foo` dans le crate `bar`." + +#: src/modules/filesystem.md:1 +#, fuzzy +msgid "# Filesystem Hierarchy" +msgstr "# Hiérarchie du système de fichiers" + +#: src/modules/filesystem.md:3 +#, fuzzy +msgid "The module content can be omitted:" +msgstr "Le contenu du module peut être omis :" + +#: src/modules/filesystem.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"mod garden;\n" +"```" +msgstr "" + +#: src/modules/filesystem.md:9 +#, fuzzy +msgid "The `garden` module content is found at:" +msgstr "Le contenu du module \"jardin\" se trouve à :" + +#: src/modules/filesystem.md:11 +#, fuzzy +msgid "" +"* `src/garden.rs` (modern Rust 2018 style)\n" +"* `src/garden/mod.rs` (older Rust 2015 style)" +msgstr "" +"* `src/garden.rs` (style Rust 2018 moderne)\n" +"* `src/garden/mod.rs` (ancien style Rust 2015)" + +#: src/modules/filesystem.md:14 +#, fuzzy +msgid "Similarly, a `garden::vegetables` module can be found at:" +msgstr "De même, un module `garden::legumes` peut être trouvé à :" + +#: src/modules/filesystem.md:16 +#, fuzzy +msgid "" +"* `src/garden/vegetables.rs` (modern Rust 2018 style)\n" +"* `src/garden/vegetables/mod.rs` (older Rust 2015 style)" +msgstr "" +"* `src/garden/vegetables.rs` (style Rust 2018 moderne)\n" +"* `src/garden/vegetables/mod.rs` (ancien style Rust 2015)" + +#: src/modules/filesystem.md:19 +#, fuzzy +msgid "The `crate` root is in:" +msgstr "La racine `crate` se trouve dans :" + +#: src/modules/filesystem.md:21 +#, fuzzy +msgid "" +"* `src/lib.rs` (for a library crate)\n" +"* `src/main.rs` (for a binary crate)" +msgstr "" +"* `src/lib.rs` (pour une caisse de bibliothèque)\n" +"* `src/main.rs` (pour un crate binaire)" + +#: src/modules/filesystem.md:24 +#, fuzzy +msgid "" +"Modules defined in files can be documented, too, using \"inner doc comments\".\n" +"These document the item that contains them -- in this case, a module." +msgstr "" +"Les modules définis dans les fichiers peuvent également être documentés à l'aide de \"commentaires de documentation internes\".\n" +"Ceux-ci documentent l'élément qui les contient -- dans ce cas, un module." + +#: src/modules/filesystem.md:27 +msgid "" +"```rust,editable,compile_fail\n" +"//! 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" +"\n" +"// Harvest the produce in the garden that is ready.\n" +"fn harvest(garden: &mut Garden) { todo!() }\n" +"```" +msgstr "" + +#: src/modules/filesystem.md:40 +msgid "" +"* The change from `module/mod.rs` to `module.rs` doesn't preclude the use of submodules in Rust 2018.\n" +" (It was mandatory in Rust 2015.)\n" +"\n" +" The following is valid:\n" +"\n" +" ```ignore\n" +" src/\n" +" ├── main.rs\n" +" ├── top_module.rs\n" +" └── top_module/\n" +" └── sub_module.rs\n" +" ```\n" +"\n" +"* The main reason for the change is to prevent many files named `mod.rs`, which can be hard\n" +" to distinguish in IDEs.\n" +"\n" +"* Rust will look for modules in `modulename/mod.rs` and `modulename.rs`, but this can be changed\n" +" with a compiler directive:\n" +"\n" +" ```rust,ignore\n" +" #[path = \"some/path.rs\"]\n" +" mod some_module { }\n" +" ```\n" +"\n" +" This is useful, for example, if you would like to place tests for a module in a file named\n" +" `some_module_test.rs`, similar to the convention in Go." +msgstr "" + +#: src/exercises/day-2/afternoon.md:1 +#, fuzzy +msgid "# Day 2: Afternoon Exercises" +msgstr "# Jour 2 : Exercices de l'après-midi" + +#: src/exercises/day-2/afternoon.md:3 +#, fuzzy +msgid "The exercises for this afternoon will focus on strings and iterators." +msgstr "Les exercices de cet après-midi porteront sur les chaînes et les itérateurs." + +#: src/exercises/day-2/luhn.md:1 +#, fuzzy +msgid "# Luhn Algorithm" +msgstr "# Algorithme de Luhn" + +#: src/exercises/day-2/luhn.md:3 +#, fuzzy +msgid "" +"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used to\n" +"validate credit card numbers. The algorithm takes a string as input and does the\n" +"following to validate the credit card number:" +msgstr "" +"L'[algorithme de Luhn](https://en.wikipedia.org/wiki/Luhn_algorithm) est utilisé pour\n" +"valider les numéros de carte de crédit. L'algorithme prend une chaîne en entrée et fait le\n" +"suivant pour valider le numéro de carte bancaire :" + +#: src/exercises/day-2/luhn.md:7 +#, fuzzy +msgid "" +"* Ignore all spaces. Reject number with less than two digits.\n" +"\n" +"* Moving from right to left, double every second digit: for the number `1234`,\n" +" we double `3` and `1`.\n" +"\n" +"* After doubling a digit, sum the digits. So doubling `7` becomes `14` which\n" +" becomes `5`.\n" +"\n" +"* Sum all the undoubled and doubled digits.\n" +"\n" +"* The credit card number is valid if the sum ends with `0`." +msgstr "" +"* Ignorer tous les espaces. Numéro de rejet comportant moins de deux chiffres.\n" +"\n" +"* En se déplaçant de droite à gauche, doubler tous les deux chiffres : pour le nombre `1234`,\n" +" on double '3' et '1'.\n" +"\n" +"* Après avoir doublé un chiffre, additionnez les chiffres. Donc doubler '7' devient '14' ce qui\n" +" devient '5'.\n" +"\n" +"* Additionnez tous les chiffres non doublés et doublés.\n" +"\n" +"* Le numéro de carte de crédit est valide si la somme se termine par '0'." + +#: src/exercises/day-2/luhn.md:19 +#, fuzzy +msgid "" +"Copy the following code to and implement the\n" +"function:" +msgstr "" +"Copiez le code suivant sur et implémentez le\n" +"fonction:" + +#: src/exercises/day-2/luhn.md:23 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:1 +#, fuzzy +msgid "# Strings and Iterators" +msgstr "# Chaînes et itérateurs" + +#: src/exercises/day-2/strings-iterators.md:3 +#, fuzzy +msgid "" +"In this exercise, you are implementing a routing component of a web server. The\n" +"server is configured with a number of _path prefixes_ which are matched against\n" +"_request paths_. The path prefixes can contain a wildcard character which\n" +"matches a full segment. See the unit tests below." +msgstr "" +"Dans cet exercice, vous implémentez un composant de routage d'un serveur Web. Le\n" +"le serveur est configuré avec un certain nombre de _préfixes de chemin_ qui sont mis en correspondance\n" +"_demander des chemins_. Les préfixes de chemin peuvent contenir un caractère générique qui\n" +"correspond à un segment complet. Voir les tests unitaires ci-dessous." + +#: src/exercises/day-2/strings-iterators.md:8 +#, fuzzy +msgid "" +"Copy the following code to and make the tests\n" +"pass. Try avoiding allocating a `Vec` for your intermediate results:" +msgstr "" +"Copiez le code suivant sur et faites les tests\n" +"passer. Essayez d'éviter d'attribuer un \"Vec\" à vos résultats intermédiaires :" + +#: src/exercises/day-2/strings-iterators.md:12 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"```" +msgstr "" + +#: src/welcome-day-3.md:1 +#, fuzzy +msgid "# Welcome to Day 3" +msgstr "# Bienvenue au jour 3" + +#: src/welcome-day-3.md:3 +#, fuzzy +msgid "Today, we will cover some more advanced topics of Rust:" +msgstr "Aujourd'hui, nous aborderons quelques sujets plus avancés de Rust :" + +#: src/welcome-day-3.md:5 +#, fuzzy +msgid "" +"* Traits: deriving traits, default methods, and important standard library\n" +" traits.\n" +"\n" +"* Generics: generic data types, generic methods, monomorphization, and trait\n" +" objects.\n" +"\n" +"* Error handling: panics, `Result`, and the try operator `?`.\n" +"\n" +"* Testing: unit tests, documentation tests, and integration tests.\n" +"\n" +"* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" +" functions." +msgstr "" +"* Traits : traits dérivés, méthodes par défaut et bibliothèque standard importante\n" +" caractéristiques.\n" +"\n" +"* Génériques : types de données génériques, méthodes génériques, monomorphisation et trait\n" +" objets.\n" +"\n" +"* Gestion des erreurs : paniques, « Résultat » et l'opérateur d'essai « ? ».\n" +"\n" +"* Tests : tests unitaires, tests de documentation et tests d'intégration.\n" +"\n" +"* Unsafe Rust : pointeurs bruts, variables statiques, fonctions non sécurisées et extern\n" +" les fonctions." + +#: src/generics.md:1 +#, fuzzy +msgid "# Generics" +msgstr "# Génériques" + +#: src/generics.md:3 +#, fuzzy +msgid "" +"Rust support generics, which lets you abstract an algorithm (such as sorting)\n" +"over the types used in the algorithm." +msgstr "" +"Rust prend en charge les génériques, ce qui vous permet d'abstraire un algorithme (comme le tri)\n" +"sur les types utilisés dans l'algorithme." + +#: src/generics/data-types.md:1 +#, fuzzy +msgid "# Generic Data Types" +msgstr "# Types de données génériques" + +#: src/generics/data-types.md:3 +#, fuzzy +msgid "You can use generics to abstract over the concrete field type:" +msgstr "Vous pouvez utiliser des génériques pour résumer le type de champ concret :" + +#: src/generics/data-types.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point {\n" +" x: T,\n" +" y: T,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Point { x: 5, y: 10 };\n" +" let float = Point { x: 1.0, y: 4.0 };\n" +" println!(\"{integer:?} and {float:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/data-types.md:21 +msgid "" +"* Try declaring a new variable `let p = Point { x: 5, y: 10.0 };`.\n" +"\n" +"* Fix the code to allow points that have elements of different types." +msgstr "" + +#: src/generics/methods.md:1 +#, fuzzy +msgid "# Generic Methods" +msgstr "# Méthodes génériques" + +#: src/generics/methods.md:3 +#, fuzzy +msgid "You can declare a generic type on your `impl` block:" +msgstr "Vous pouvez déclarer un type générique sur votre bloc `impl` :" + +#: src/generics/methods.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(T, T);\n" +"\n" +"impl Point {\n" +" fn x(&self) -> &T {\n" +" &self.0 // + 10\n" +" }\n" +"\n" +" // fn set_x(&mut self, x: T)\n" +"}\n" +"\n" +"fn main() {\n" +" let p = Point(5, 10);\n" +" println!(\"p.x = {}\", p.x());\n" +"}\n" +"```" +msgstr "" + +#: src/generics/methods.md:25 +#, fuzzy +msgid "" +"* *Q:* Why `T` is specified twice in `impl Point {}`? Isn't that redundant?\n" +" * This is because it is a generic implementation section for generic type. They are independently generic.\n" +" * It means these methods are defined for any `T`.\n" +" * It is possible to write `impl Point { .. }`. \n" +" * `Point` is still generic and you can use `Point`, but methods in this block will only be available for `Point`." +msgstr "" +"* *Q :* Pourquoi `T` est spécifié deux fois dans `impl Point {}` ? N'est-ce pas redondant ?\n" +" * C'est parce qu'il s'agit d'une section d'implémentation générique pour le type générique. Ils sont indépendamment génériques.\n" +" * Cela signifie que ces méthodes sont définies pour n'importe quel `T`.\n" +" * Il est possible d'écrire `impl Point { .. }`.\n" +" * `Point` est toujours générique et vous pouvez utiliser `Point`, mais les méthodes de ce bloc ne seront disponibles que pour " +"`Point`." + +#: src/generics/monomorphization.md:1 +#, fuzzy +msgid "# Monomorphization" +msgstr "# Monomorphisation" + +#: src/generics/monomorphization.md:3 +#, fuzzy +msgid "Generic code is turned into non-generic code based on the call sites:" +msgstr "Le code générique est transformé en code non générique basé sur les sites d'appel :" + +#: src/generics/monomorphization.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let integer = Some(5);\n" +" let float = Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:12 +#, fuzzy +msgid "behaves as if you wrote" +msgstr "se comporte comme si vous écriviez" + +#: src/generics/monomorphization.md:14 +msgid "" +"```rust,editable\n" +"enum Option_i32 {\n" +" Some(i32),\n" +" None,\n" +"}\n" +"\n" +"enum Option_f64 {\n" +" Some(f64),\n" +" None,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Option_i32::Some(5);\n" +" let float = Option_f64::Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:31 +#, fuzzy +msgid "" +"This is a zero-cost abstraction: you get exactly the same result as if you had\n" +"hand-coded the data structures without the abstraction." +msgstr "" +"Il s'agit d'une abstraction à coût nul : vous obtenez exactement le même résultat que si vous aviez\n" +"codé à la main les structures de données sans l'abstraction." + +#: src/traits.md:1 +#, fuzzy +msgid "# Traits" +msgstr "# Caractéristiques" + +#: src/traits.md:3 +#, fuzzy +msgid "Rust lets you abstract over types with traits. They're similar to interfaces:" +msgstr "Rust vous permet d'abstraire les types avec des traits. Ils sont similaires aux interfaces :" + +#: src/traits.md:5 +msgid "" +"```rust,editable\n" +"trait Pet {\n" +" fn name(&self) -> String;\n" +"}\n" +"\n" +"struct Dog {\n" +" name: String,\n" +"}\n" +"\n" +"struct Cat;\n" +"\n" +"impl Pet for Dog {\n" +" fn name(&self) -> String {\n" +" self.name.clone()\n" +" }\n" +"}\n" +"\n" +"impl Pet for Cat {\n" +" fn name(&self) -> String {\n" +" String::from(\"The cat\") // No name, cats won't respond to it anyway.\n" +" }\n" +"}\n" +"\n" +"fn greet(pet: &P) {\n" +" println!(\"Who's a cutie? {} is!\", pet.name());\n" +"}\n" +"\n" +"fn main() {\n" +" let fido = Dog { name: \"Fido\".into() };\n" +" greet(&fido);\n" +"\n" +" let captain_floof = Cat;\n" +" greet(&captain_floof);\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-objects.md:1 +#, fuzzy +msgid "# Trait Objects" +msgstr "# Objets de trait" + +#: src/traits/trait-objects.md:3 +#, fuzzy +msgid "Trait objects allow for values of different types, for instance in a collection:" +msgstr "Les objets de trait autorisent des valeurs de différents types, par exemple dans une collection :" + +#: src/traits/trait-objects.md:5 +msgid "" +"```rust\n" +"trait Pet {\n" +" fn name(&self) -> String;\n" +"}\n" +"\n" +"struct Dog {\n" +" name: String,\n" +"}\n" +"\n" +"struct Cat;\n" +"\n" +"impl Pet for Dog {\n" +" fn name(&self) -> String {\n" +" self.name.clone()\n" +" }\n" +"}\n" +"\n" +"impl Pet for Cat {\n" +" fn name(&self) -> String {\n" +" String::from(\"The cat\") // No name, cats won't respond to it anyway.\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let pets: Vec> = vec![\n" +" Box::new(Dog { name: String::from(\"Fido\") }),\n" +" Box::new(Cat),\n" +" ];\n" +" for pet in pets {\n" +" println!(\"Hello {}!\", pet.name());\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-objects.md:40 +#, fuzzy +msgid "Memory layout after allocating `pets`:" +msgstr "Disposition de la mémoire après l'allocation de `pets` :" + +#: src/traits/trait-objects.md:42 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": pets : : :\n" +": +-----------+-------+ : : +-----+-----+ :\n" +": | ptr | o---+---+-----+-->| o o | o o | :\n" +": | len | 2 | : : +-|-|-+-|-|-+ :\n" +": | capacity | 2 | : : | | | | +---------------+ :\n" +": +-----------+-------+ : : | | | '-->| name: \"Fido\" | :\n" +": : : | | | +---------------+ :\n" +"`- - - - - - - - - - - - - -' : | | | :\n" +" : | | | +----------------------+ : \n" +" : | | '---->| \"::name\" | :\n" +" : | | +----------------------+ : \n" +" : | | : \n" +" : | | +-+ : \n" +" : | '-->|\\| : \n" +" : | +-+ : \n" +" : | : \n" +" : | +----------------------+ : \n" +" : '---->| \"::name\" | : \n" +" : +----------------------+ :\n" +" : :\n" +" '- - - - - - - - - - - - - - - - - - - - - - -'\n" +"\n" +"```" +msgstr "" + +#: src/traits/trait-objects.md:72 +msgid "" +"* Types that implement a given trait may be of different sizes. This makes it impossible to have things like `Vec` in the example above.\n" +"* `dyn Pet` is a way to tell the compiler about a dynamically sized type that implements `Pet`.\n" +"* In the example, `pets` holds *fat pointers* to objects that implement `Pet`. The fat pointer consists of two components, a pointer to the actual " +"object and a pointer to the virtual method table for the `Pet` implementation of that particular object.\n" +"* Compare these outputs in the above example:\n" +" ```rust,ignore\n" +" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::());\n" +" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n" +" println!(\"{}\", std::mem::size_of::<&dyn Pet>());\n" +" println!(\"{}\", std::mem::size_of::>());\n" +" ```" +msgstr "" + +#: src/traits/deriving-traits.md:1 +#, fuzzy +msgid "# Deriving Traits" +msgstr "# Traits dérivés" + +#: src/traits/deriving-traits.md:3 +#, fuzzy +msgid "You can let the compiler derive a number of traits:" +msgstr "Vous pouvez laisser le compilateur dériver un certain nombre de traits :" + +#: src/traits/deriving-traits.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Clone, PartialEq, Eq, Default)]\n" +"struct Player {\n" +" name: String,\n" +" strength: u8,\n" +" hit_points: u8,\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Player::default();\n" +" let p2 = p1.clone();\n" +" println!(\"Is {:?}\\nequal to {:?}?\\nThe answer is {}!\", &p1, &p2,\n" +" if p1 == p2 { \"yes\" } else { \"no\" });\n" +"}\n" +"```" +msgstr "" + +#: src/traits/default-methods.md:1 +#, fuzzy +msgid "# Default Methods" +msgstr "# Méthodes par défaut" + +#: src/traits/default-methods.md:3 +#, fuzzy +msgid "Traits can implement behavior in terms of other trait methods:" +msgstr "Les traits peuvent implémenter un comportement en termes d'autres méthodes de trait :" + +#: src/traits/default-methods.md:5 +msgid "" +"```rust,editable\n" +"trait Equals {\n" +" fn equal(&self, other: &Self) -> bool;\n" +" fn not_equal(&self, other: &Self) -> bool {\n" +" !self.equal(other)\n" +" }\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"struct Centimeter(i16);\n" +"\n" +"impl Equals for Centimeter {\n" +" fn equal(&self, other: &Centimeter) -> bool {\n" +" self.0 == other.0\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let a = Centimeter(10);\n" +" let b = Centimeter(20);\n" +" println!(\"{a:?} equals {b:?}: {}\", a.equal(&b));\n" +" println!(\"{a:?} not_equals {b:?}: {}\", a.not_equal(&b));\n" +"}\n" +"```" +msgstr "" + +#: src/traits/default-methods.md:32 +#, fuzzy +msgid "" +"* Traits may specify pre-implemented (default) methods and methods that users are required to\n" +" implement themselves. Methods with default implementations can rely on required methods.\n" +"\n" +"* Move method `not_equal` to a new trait `NotEqual`.\n" +"\n" +"* Make `NotEqual` a super trait for `Equal`.\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`." +msgstr "" +"* Les caractéristiques peuvent spécifier des méthodes pré-implémentées (par défaut) et des méthodes que les utilisateurs sont tenus de suivre\n" +" mettre en œuvre eux-mêmes. Les méthodes avec des implémentations par défaut peuvent s'appuyer sur les méthodes requises.\n" +"\n" +"* Déplacez la méthode `not_equal` vers un nouveau trait `NotEqual`.\n" +"\n" +"* Faites de `NotEqual` un super trait pour `Equal`.\n" +"\n" +"* Fournir une implémentation globale de `NotEqual` pour `Equal`.\n" +" * Avec l'implémentation globale, vous n'avez plus besoin de `NotEqual` comme super trait pour `Equal`." + +#: src/traits/trait-bounds.md:1 +#, fuzzy +msgid "# Trait Bounds" +msgstr "# Limites de trait" + +#: src/traits/trait-bounds.md:3 +#, fuzzy +msgid "" +"When working with generics, you often want to require the types to implement\n" +"some trait, so that you can call this trait's methods." +msgstr "" +"Lorsque vous travaillez avec des génériques, vous souhaitez souvent exiger que les types implémentent\n" +"un trait, afin que vous puissiez appeler les méthodes de ce trait." + +#: src/traits/trait-bounds.md:6 +#, fuzzy +msgid "You can do this with `T: Trait` or `impl Trait`:" +msgstr "Vous pouvez le faire avec `T: Trait` ou `impl Trait` :" + +#: src/traits/trait-bounds.md:8 +msgid "" +"```rust,editable\n" +"fn duplicate(a: T) -> (T, T) {\n" +" (a.clone(), a.clone())\n" +"}\n" +"\n" +"// Syntactic sugar for:\n" +"// fn add_42_millions>(x: T) -> i32 {\n" +"fn add_42_millions(x: impl Into) -> i32 {\n" +" x.into() + 42_000_000\n" +"}\n" +"\n" +"// struct NotClonable;\n" +"\n" +"fn main() {\n" +" let foo = String::from(\"foo\");\n" +" let pair = duplicate(foo);\n" +" println!(\"{pair:?}\");\n" +"\n" +" let many = add_42_millions(42_i8);\n" +" println!(\"{many}\");\n" +" let many_more = add_42_millions(10_000_000);\n" +" println!(\"{many_more}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-bounds.md:35 +#, fuzzy +msgid "Show a `where` clause, students will encounter it when reading code." +msgstr "Montrez une clause \"où\", les étudiants la rencontreront lors de la lecture du code." + +#: src/traits/trait-bounds.md:37 +msgid "" +"```rust,ignore\n" +"fn duplicate(a: T) -> (T, T)\n" +"where\n" +" T: Clone,\n" +"{\n" +" (a.clone(), a.clone())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-bounds.md:46 +#, fuzzy +msgid "" +"* It declutters the function signature if you have many parameters.\n" +"* It has additional features making it more powerful.\n" +" * If someone asks, the extra feature is that the type on the left of \":\" can be arbitrary, like `Option`.\n" +" " +msgstr "" +"* Cela désencombre la signature de la fonction si vous avez beaucoup de paramètres.\n" +"* Il a des fonctionnalités supplémentaires qui le rendent plus puissant.\n" +" * Si quelqu'un demande, la fonctionnalité supplémentaire est que le type à gauche de \":\" peut être arbitraire, comme `Option`.\n" +" " + +#: src/traits/impl-trait.md:1 +#, fuzzy +msgid "# `impl Trait`" +msgstr "# `Trait d'implémentation`" + +#: src/traits/impl-trait.md:3 +#, fuzzy +msgid "" +"Similar to trait bounds, an `impl Trait` syntax can be used in function\n" +"arguments and return values:" +msgstr "" +"Semblable aux limites de trait, une syntaxe `impl Trait` peut être utilisée dans la fonction\n" +"arguments et valeurs de retour :" + +#: src/traits/impl-trait.md:6 +msgid "" +"```rust,editable\n" +"use std::fmt::Display;\n" +"\n" +"fn get_x(name: impl Display) -> impl Display {\n" +" format!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let x = get_x(\"foo\");\n" +" println!(\"{x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/impl-trait.md:19 +#, fuzzy +msgid "* `impl Trait` allows you to work with types which you cannot name." +msgstr "* `impl Trait` vous permet de travailler avec des types que vous ne pouvez pas nommer." + +#: src/traits/impl-trait.md:23 +#, fuzzy +msgid "The meaning of `impl Trait` is a bit different in the different positions." +msgstr "La signification de `impl Trait` est un peu différente dans les différentes positions." + +#: src/traits/impl-trait.md:25 +#, fuzzy +msgid "" +"* For a parameter, `impl Trait` is like an anonymous generic parameter with a trait bound.\n" +"\n" +"* For a return type, it means that the return type is some concrete type that implements the trait,\n" +" without naming the type. This can be useful when you don't want to expose the concrete type in a\n" +" public API.\n" +"\n" +" Inference is hard in return position. A function returning `impl Foo` picks\n" +" the concrete type it returns, without writing it out in the source. A function\n" +" returning a generic type like `collect() -> B` can return any type\n" +" satisfying `B`, and the caller may need to choose one, such as with `let x:\n" +" Vec<_> = foo.collect()` or with the turbofish, `foo.collect::>()`." +msgstr "" +"* Pour un paramètre, `impl Trait` est comme un paramètre générique anonyme avec un trait lié.\n" +"\n" +"* Pour un type de retour, cela signifie que le type de retour est un type concret qui implémente le trait,\n" +" sans nommer le type. Cela peut être utile lorsque vous ne souhaitez pas exposer le type concret dans un\n" +" API publique.\n" +"\n" +" L'inférence est difficile en position de retour. Une fonction renvoyant `impl Foo` sélectionne\n" +" le type concret qu'il renvoie, sans l'écrire dans la source. Une fonction\n" +" retourner un type générique comme `collect() -> B` peut retourner n'importe quel type\n" +" satisfaisant `B`, et l'appelant peut avoir besoin d'en choisir un, comme avec `let x :\n" +" Vec<_> = foo.collect()` ou avec le turbofish, `foo.collect ::>()`." + +#: src/traits/impl-trait.md:37 +#, fuzzy +msgid "" +"This example is great, because it uses `impl Display` twice. It helps to explain that\n" +"nothing here enforces that it is _the same_ `impl Display` type. If we used a single \n" +"`T: Display`, it would enforce the constraint that input `T` and return `T` type are the same type.\n" +"It would not work for this particular function, as the type we expect as input is likely not\n" +"what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two\n" +"independent generic parameters." +msgstr "" +"Cet exemple est génial, car il utilise `impl Display` deux fois. Cela aide à expliquer que\n" +"rien ici n'impose qu'il s'agisse du _même_ type `impl Display`. Si nous utilisions un seul\n" +"`T: Display`, cela imposerait la contrainte selon laquelle l'entrée `T` et le type de retour `T` sont du même type.\n" +"Cela ne fonctionnerait pas pour cette fonction particulière, car le type que nous attendons en entrée n'est probablement pas\n" +"quel `format!` renvoie. Si nous voulions faire la même chose via la syntaxe `: Display`, nous aurions besoin de deux\n" +"paramètres génériques indépendants." + +#: src/traits/important-traits.md:1 +#, fuzzy +msgid "# Important Traits" +msgstr "# Caractéristiques importantes" + +#: src/traits/important-traits.md:3 +#, fuzzy +msgid "We will now look at some of the most common traits of the Rust standard library:" +msgstr "Nous allons maintenant examiner certaines des caractéristiques les plus courantes de la bibliothèque standard Rust :" + +#: src/traits/important-traits.md:5 +#, fuzzy +msgid "" +"* [`Iterator`][1] and [`IntoIterator`][2] used in `for` loops,\n" +"* [`From`][3] and [`Into`][4] used to convert values,\n" +"* [`Read`][5] and [`Write`][6] used for IO,\n" +"* [`Add`][7], [`Mul`][8], ... used for operator overloading, and\n" +"* [`Drop`][9] used for defining destructors.\n" +"* [`Default`][10] used to construct a default instance of a type." +msgstr "" +"* [`Iterator`][1] et [`IntoIterator`][2] utilisés dans les boucles `for`,\n" +"* [`From`][3] et [`Into`][4] utilisés pour convertir les valeurs,\n" +"* [`Read`][5] et [`Write`][6] utilisés pour IO,\n" +"* [`Add`][7], [`Mul`][8], ... utilisé pour la surcharge de l'opérateur, et\n" +"* [`Drop`][9] utilisé pour définir les destructeurs.\n" +"* [`Default`][10] utilisé pour construire une instance par défaut d'un type." + +#: src/traits/iterator.md:1 +#, fuzzy +msgid "# Iterators" +msgstr "# Itérateurs" + +#: src/traits/iterator.md:3 +#, fuzzy +msgid "You can implement the [`Iterator`][1] trait on your own types:" +msgstr "Vous pouvez implémenter le trait [`Iterator`][1] sur vos propres types :" + +#: src/traits/iterator.md:5 +msgid "" +"```rust,editable\n" +"struct Fibonacci {\n" +" curr: u32,\n" +" next: u32,\n" +"}\n" +"\n" +"impl Iterator for Fibonacci {\n" +" type Item = u32;\n" +"\n" +" fn next(&mut self) -> Option {\n" +" let new_next = self.curr + self.next;\n" +" self.curr = self.next;\n" +" self.next = new_next;\n" +" Some(self.curr)\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let fib = Fibonacci { curr: 0, next: 1 };\n" +" for (i, n) in fib.enumerate().take(5) {\n" +" println!(\"fib({i}): {n}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/traits/iterator.md:32 +#, fuzzy +msgid "" +"* The `Iterator` trait implements many common functional programming operations over collections \n" +" (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can find all the documentation\n" +" about them. In Rust these functions should produce the code as efficient as equivalent imperative\n" +" implementations.\n" +" \n" +"* `IntoIterator` is the trait that makes for loops work. It is implemented by collection types such as\n" +" `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also implement it. This is why\n" +" you can iterate over a vector with `for i in some_vec { .. }` but\n" +" `some_vec.next()` doesn't exist." +msgstr "" +"* Le trait `Iterator` implémente de nombreuses opérations de programmation fonctionnelles courantes sur les collections\n" +" (par exemple, `map`, `filter`, `reduce`, etc.). C'est le trait où vous pouvez trouver toute la documentation\n" +" à propos d'eux. Dans Rust, ces fonctions devraient produire le code aussi efficace que l'impératif équivalent\n" +" implémentations.\n" +" \n" +"* `IntoIterator` est le trait qui fait fonctionner les boucles. Il est implémenté par des types de collection tels que\n" +" `Vec` et leurs références telles que `&Vec` et `&[T]`. Les gammes l'implémentent également. C'est pourquoi\n" +" vous pouvez itérer sur un vecteur avec `for i in some_vec { .. }` mais\n" +" `some_vec.next()` n'existe pas." + +#: src/traits/from-iterator.md:1 +#, fuzzy +msgid "# FromIterator" +msgstr "# FromIterator" + +#: src/traits/from-iterator.md:3 +#, fuzzy +msgid "[`FromIterator`][1] lets you build a collection from an [`Iterator`][2]." +msgstr "[`FromIterator`][1] vous permet de créer une collection à partir d'un [`Iterator`][2]." + +#: src/traits/from-iterator.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let primes = vec![2, 3, 5, 7];\n" +" let prime_squares = primes\n" +" .into_iter()\n" +" .map(|prime| prime * prime)\n" +" .collect::>();\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-iterator.md:17 +#, fuzzy +msgid "" +"`Iterator` implements\n" +"`fn collect(self) -> B\n" +"where\n" +" B: FromIterator,\n" +" Self: Sized`" +msgstr "" +"Implémente `Iterator`\n" +"`fn collect(soi) -> B\n" +"où\n" +" B : FromIterator,\n" +" Auto : dimensionné" + +#: src/traits/from-iterator.md:23 +#, fuzzy +msgid "" +"There are also implementations which let you do cool things like convert an\n" +"`Iterator>` into a `Result, E>`." +msgstr "" +"Il existe également des implémentations qui vous permettent de faire des choses sympas comme convertir un\n" +"`Iterator>` en un `Result, E>`." + +#: src/traits/from-into.md:1 +#, fuzzy +msgid "# `From` and `Into`" +msgstr "# `De` et `Dans`" + +#: src/traits/from-into.md:3 +#, fuzzy +msgid "Types implement [`From`][1] and [`Into`][2] to facilitate type conversions:" +msgstr "Les types implémentent [`From`][1] et [`Into`][2] pour faciliter les conversions de type :" + +#: src/traits/from-into.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s = String::from(\"hello\");\n" +" let addr = std::net::Ipv4Addr::from([127, 0, 0, 1]);\n" +" let one = i16::from(true);\n" +" let bigger = i32::from(123i16);\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-into.md:15 +#, fuzzy +msgid "[`Into`][2] is automatically implemented when [`From`][1] is implemented:" +msgstr "[`Into`][2] est automatiquement implémenté lorsque [`From`][1] est implémenté :" + +#: src/traits/from-into.md:17 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s: String = \"hello\".into();\n" +" let addr: std::net::Ipv4Addr = [127, 0, 0, 1].into();\n" +" let one: i16 = true.into();\n" +" let bigger: i32 = 123i16.into();\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-into.md:29 +#, fuzzy +msgid "" +"* That's why it is common to only implement `From`, as your type will get `Into` implementation too.\n" +"* When declaring a function argument input type like \"anything that can be converted into a `String`\", the rule is opposite, you should use " +"`Into`.\n" +" Your function will accept types that implement `From` and those that _only_ implement `Into`.\n" +" " +msgstr "" +"* C'est pourquoi il est courant de n'implémenter que `From`, car votre type recevra également l'implémentation `Into`.\n" +"* Lors de la déclaration d'un type d'entrée d'argument de fonction comme \"tout ce qui peut être converti en `String`\", la règle est opposée, vous " +"devez utiliser `Into`.\n" +" Votre fonction acceptera les types qui implémentent `From` et ceux qui implémentent _uniquement_ `Into`.\n" +" " + +#: src/traits/read-write.md:1 +#, fuzzy +msgid "# `Read` and `Write`" +msgstr "# `Lire` et `Ecrire`" + +#: src/traits/read-write.md:3 +#, fuzzy +msgid "Using [`Read`][1] and [`BufRead`][2], you can abstract over `u8` sources:" +msgstr "En utilisant [`Read`][1] et [`BufRead`][2], vous pouvez résumer les sources `u8` :" + +#: src/traits/read-write.md:5 +msgid "" +"```rust,editable\n" +"use std::io::{BufRead, BufReader, Read, Result};\n" +"\n" +"fn count_lines(reader: R) -> usize {\n" +" let buf_reader = BufReader::new(reader);\n" +" buf_reader.lines().count()\n" +"}\n" +"\n" +"fn main() -> Result<()> {\n" +" let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" +" println!(\"lines in slice: {}\", count_lines(slice));\n" +"\n" +" let file = std::fs::File::open(std::env::current_exe()?)?;\n" +" println!(\"lines in file: {}\", count_lines(file));\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/read-write.md:23 +#, fuzzy +msgid "Similarly, [`Write`][3] lets you abstract over `u8` sinks:" +msgstr "De même, [`Write`][3] vous permet d'abstraire les puits `u8` :" + +#: src/traits/read-write.md:25 +msgid "" +"```rust,editable\n" +"use std::io::{Result, Write};\n" +"\n" +"fn log(writer: &mut W, msg: &str) -> Result<()> {\n" +" writer.write_all(msg.as_bytes())?;\n" +" writer.write_all(\"\\n\".as_bytes())\n" +"}\n" +"\n" +"fn main() -> Result<()> {\n" +" let mut buffer = Vec::new();\n" +" log(&mut buffer, \"Hello\")?;\n" +" log(&mut buffer, \"World\")?;\n" +" println!(\"Logged: {:?}\", buffer);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/drop.md:1 +#, fuzzy +msgid "# The `Drop` Trait" +msgstr "# Le trait `Lâcher`" + +#: src/traits/drop.md:3 +#, fuzzy +msgid "Values which implement [`Drop`][1] can specify code to run when they go out of scope:" +msgstr "Les valeurs qui implémentent [`Drop`][1] peuvent spécifier le code à exécuter lorsqu'elles sortent de la portée :" + +#: src/traits/drop.md:5 +msgid "" +"```rust,editable\n" +"struct Droppable {\n" +" name: &'static str,\n" +"}\n" +"\n" +"impl Drop for Droppable {\n" +" fn drop(&mut self) {\n" +" println!(\"Dropping {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let a = Droppable { name: \"a\" };\n" +" {\n" +" let b = Droppable { name: \"b\" };\n" +" {\n" +" let c = Droppable { name: \"c\" };\n" +" let d = Droppable { name: \"d\" };\n" +" println!(\"Exiting block B\");\n" +" }\n" +" println!(\"Exiting block A\");\n" +" }\n" +" drop(a);\n" +" println!(\"Exiting main\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/drop.md:34 src/traits/operators.md:26 +#, fuzzy +msgid "Discussion points:" +msgstr "Points de discussion:" + +#: src/traits/drop.md:36 +#, fuzzy +msgid "" +"* Why doesn't `Drop::drop` take `self`?\n" +" * Short-answer: If it did, `std::mem::drop` would be called at the end of\n" +" the block, resulting in another call to `Drop::drop`, and a stack\n" +" overflow!\n" +"* Try replacing `drop(a)` with `a.drop()`." +msgstr "" +"* Pourquoi `Drop::drop` ne prend-il pas `self` ?\n" +" * Réponse courte : si c'était le cas, `std::mem::drop` serait appelé à la fin de\n" +" le bloc, résultant en un autre appel à `Drop :: drop`, et une pile\n" +" débordement!\n" +"* Essayez de remplacer `drop(a)` par `a.drop()`." + +#: src/traits/default.md:1 +#, fuzzy +msgid "# The `Default` Trait" +msgstr "# Le trait \"par défaut\"" + +#: src/traits/default.md:3 +#, fuzzy +msgid "[`Default`][1] trait provides a default implementation of a trait." +msgstr "[`Default`][1] trait fournit une implémentation par défaut d'un trait." + +#: src/traits/default.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Default)]\n" +"struct Derived {\n" +" x: u32,\n" +" y: String,\n" +" z: Implemented,\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"struct Implemented(String);\n" +"\n" +"impl Default for Implemented {\n" +" fn default() -> Self {\n" +" Self(\"John Smith\".into())\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let default_struct: Derived = Default::default();\n" +" println!(\"{default_struct:#?}\");\n" +"\n" +" let almost_default_struct = Derived {\n" +" y: \"Y is set!\".into(),\n" +" ..Default::default()\n" +" };\n" +" println!(\"{almost_default_struct:#?}\");\n" +"\n" +" let nothing: Option = None;\n" +" println!(\"{:#?}\", nothing.unwrap_or_default());\n" +"}\n" +"\n" +"```" +msgstr "" + +#: src/traits/default.md:40 +#, fuzzy +msgid "" +" * It can be implemented directly or it can be derived via `#[derive(Default)]`.\n" +" * Derived implementation will produce an instance where all fields are set to their default values.\n" +" * This means all types in the struct must implement `Default` too.\n" +" * Standard Rust types often implement `Default` with reasonable values (e.g. `0`, `\"\"`, etc).\n" +" * The partial struct copy works nicely with default.\n" +" * Rust standard library is aware that types can implement `Default` and provides convenience methods that use it." +msgstr "" +" * Il peut être implémenté directement ou il peut être dérivé via `#[derive(Default)]`.\n" +" * L'implémentation dérivée produira une instance où tous les champs sont définis sur leurs valeurs par défaut.\n" +" * Cela signifie que tous les types de la structure doivent également implémenter `Default`.\n" +" * Les types Rust standard implémentent souvent `Default` avec des valeurs raisonnables (par exemple `0`, `\"\"`, etc.).\n" +" * La copie de structure partielle fonctionne bien avec la valeur par défaut.\n" +" * La bibliothèque standard Rust est consciente que les types peuvent implémenter `Default` et fournit des méthodes pratiques qui l'utilisent." + +#: src/traits/operators.md:1 +#, fuzzy +msgid "# `Add`, `Mul`, ..." +msgstr "# `Ajouter`, `Mul`, ..." + +#: src/traits/operators.md:3 +#, fuzzy +msgid "Operator overloading is implemented via traits in [`std::ops`][1]:" +msgstr "La surcharge d'opérateur est implémentée via des traits dans [`std::ops`][1] :" + +#: src/traits/operators.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Copy, Clone)]\n" +"struct Point { x: i32, y: i32 }\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self {\n" +" Self {x: self.x + other.x, y: self.y + other.y}\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point { x: 10, y: 20 };\n" +" let p2 = Point { x: 100, y: 200 };\n" +" println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" +"}\n" +"```" +msgstr "" + +#: src/traits/operators.md:28 +#, fuzzy +msgid "" +"* You could implement `Add` for `&Point`. In which situations is that useful? \n" +" * Answer: `Add:add` consumes `self`. If type `T` for which you are\n" +" 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" +" associated types (like `Output`) are controlled by the implementor of a\n" +" trait." +msgstr "" +"* Vous pouvez implémenter `Add` pour `&Point`. Dans quelles situations est-ce utile ?\n" +" * Réponse : `Add:add` consomme `self`. Si tapez `T` pour lequel vous êtes\n" +" la surcharge de l'opérateur n'est pas `Copy`, vous devriez envisager de surcharger\n" +" l'opérateur pour `&T` également. Cela évite un clonage inutile sur le\n" +" site d'appel.\n" +"* Pourquoi `Output` est-il un type associé ? Pourrait-il en faire un paramètre de type?\n" +" * Réponse courte : les paramètres de type sont contrôlés par l'appelant, mais\n" +" les types associés (comme `Output`) sont contrôlés par l'implémenteur d'un\n" +" trait." + +#: src/traits/closures.md:1 +#, fuzzy +msgid "# Closures" +msgstr "# Fermetures" + +#: src/traits/closures.md:3 +#, fuzzy +msgid "" +"Closures or lambda expressions have types which cannot be named. However, they\n" +"implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:" +msgstr "" +"Les fermetures ou les expressions lambda ont des types qui ne peuvent pas être nommés. Cependant, ils\n" +"implémenter [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html) spécial,\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), et\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) :" + +#: src/traits/closures.md:8 +msgid "" +"```rust,editable\n" +"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" +" println!(\"Calling function on {input}\");\n" +" func(input)\n" +"}\n" +"\n" +"fn main() {\n" +" let add_3 = |x| x + 3;\n" +" let mul_5 = |x| x * 5;\n" +"\n" +" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" +" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" +"}\n" +"```" +msgstr "" + +#: src/traits/closures.md:25 +#, fuzzy +msgid "If you have an `FnOnce`, you may only call it once. It might consume captured values." +msgstr "Si vous avez un \"FnOnce\", vous ne pouvez l'appeler qu'une seule fois. Cela peut consommer des valeurs capturées." + +#: src/traits/closures.md:27 +#, fuzzy +msgid "An `FnMut` might mutate captured values, so you can call it multiple times but not concurrently." +msgstr "Un `FnMut` peut faire muter les valeurs capturées, vous pouvez donc l'appeler plusieurs fois mais pas simultanément." + +#: src/traits/closures.md:29 +#, fuzzy +msgid "" +"An `Fn` neither consumes nor mutates captured values, or perhaps captures nothing at all, so it can\n" +"be called multiple times concurrently." +msgstr "" +"Un `Fn` ne consomme ni ne modifie les valeurs capturées, ou peut-être ne capture rien du tout, il peut donc\n" +"être appelé plusieurs fois simultanément." + +#: src/traits/closures.md:32 +#, fuzzy +msgid "" +"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. I.e. you can use an\n" +"`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever an `FnMut` or `FnOnce`\n" +"is called for." +msgstr "" +"`FnMut` est un sous-type de `FnOnce`. `Fn` est un sous-type de `FnMut` et `FnOnce`. C'est à dire. vous pouvez utiliser un\n" +"`FnMut` partout où un `FnOnce` est appelé, et vous pouvez utiliser un `Fn` partout où un `FnMut` ou `FnOnce`\n" +"est réclamé." + +#: src/traits/closures.md:36 +#, fuzzy +msgid "`move` closures only implement `FnOnce`." +msgstr "Les fermetures `move` n'implémentent que `FnOnce`." + +#: src/exercises/day-3/morning.md:1 +#, fuzzy +msgid "# Day 3: Morning Exercises" +msgstr "# Jour 3 : Exercices du matin" + +#: src/exercises/day-3/morning.md:3 +#, fuzzy +msgid "We will design a classical GUI library traits and trait objects." +msgstr "Nous allons concevoir une bibliothèque de traits et d'objets de traits d'interface graphique classique." + +#: src/exercises/day-3/simple-gui.md:1 +#, fuzzy +msgid "# A Simple GUI Library" +msgstr "# Une bibliothèque d'interface graphique simple" + +#: src/exercises/day-3/simple-gui.md:3 +#, fuzzy +msgid "" +"Let us design a classical GUI library using our new knowledge of traits and\n" +"trait objects." +msgstr "" +"Concevons une bibliothèque d'interface graphique classique en utilisant nos nouvelles connaissances sur les traits et\n" +"objets trait." + +#: src/exercises/day-3/simple-gui.md:6 +#, fuzzy +msgid "We will have a number of widgets in our library:" +msgstr "Nous aurons un certain nombre de widgets dans notre bibliothèque :" + +#: src/exercises/day-3/simple-gui.md:8 +#, fuzzy +msgid "" +"* `Window`: has a `title` and contains other widgets.\n" +"* `Button`: has a `label` and a callback function which is invoked when the\n" +" button is pressed.\n" +"* `Label`: has a `label`." +msgstr "" +"* `Window` : a un `title` et contient d'autres widgets.\n" +"* `Button` : a un `label` et une fonction de rappel qui est invoquée lorsque le\n" +" bouton est enfoncé.\n" +"* `Label` : a un `label`." + +#: src/exercises/day-3/simple-gui.md:13 +#, fuzzy +msgid "The widgets will implement a `Widget` trait, see below." +msgstr "Les widgets implémenteront un trait `Widget`, voir ci-dessous." + +#: src/exercises/day-3/simple-gui.md:15 +#, fuzzy +msgid "" +"Copy the code below to , fill in the missing\n" +"`draw_into` methods so that you implement the `Widget` trait:" +msgstr "" +"Copiez le code ci-dessous sur , remplissez les champs manquants\n" +"méthodes `draw_into` afin que vous implémentiez le trait `Widget` :" + +#: src/exercises/day-3/simple-gui.md:18 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"}\n" +"\n" +"\n" +"impl Widget for Label {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Widget for Button {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:123 +#, fuzzy +msgid "The output of the above program can be something simple like this:" +msgstr "La sortie du programme ci-dessus peut être quelque chose de simple comme ceci :" + +#: src/exercises/day-3/simple-gui.md:125 +msgid "" +"```text\n" +"========\n" +"Rust GUI Demo 1.23\n" +"========\n" +"\n" +"This is a small text GUI demo.\n" +"\n" +"| Click me! |\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:135 +#, fuzzy +msgid "" +"If you want to draw aligned text, you can use the\n" +"[fill/alignment](https://doc.rust-lang.org/std/fmt/index.html#fillalignment)\n" +"formatting operators. In particular, notice how you can pad with different\n" +"characters (here a `'/'`) and how you can control alignment:" +msgstr "" +"Si vous voulez dessiner du texte aligné, vous pouvez utiliser le\n" +"[remplissage/alignement](https://doc.rust-lang.org/std/fmt/index.html#fillalignment)\n" +"opérateurs de formatage. En particulier, notez comment vous pouvez compléter avec différents\n" +"caractères (ici un `'/'`) et comment vous pouvez contrôler l'alignement :" + +#: src/exercises/day-3/simple-gui.md:140 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let width = 10;\n" +" println!(\"left aligned: |{:/width$}|\", \"foo\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:149 +#, fuzzy +msgid "Using such alignment tricks, you can for example produce output like this:" +msgstr "En utilisant de telles astuces d'alignement, vous pouvez par exemple produire une sortie comme celle-ci :" + +#: src/exercises/day-3/simple-gui.md:151 +msgid "" +"```text\n" +"+--------------------------------+\n" +"| Rust GUI Demo 1.23 |\n" +"+================================+\n" +"| This is a small text GUI demo. |\n" +"| +-----------+ |\n" +"| | Click me! | |\n" +"| +-----------+ |\n" +"+--------------------------------+\n" +"```" +msgstr "" + +#: src/error-handling.md:1 +#, fuzzy +msgid "# Error Handling" +msgstr "# La gestion des erreurs" + +#: src/error-handling.md:3 +#, fuzzy +msgid "Error handling in Rust is done using explicit control flow:" +msgstr "La gestion des erreurs dans Rust est effectuée à l'aide d'un flux de contrôle explicite :" + +#: src/error-handling.md:5 +#, fuzzy +msgid "" +"* Functions that can have errors list this in their return type,\n" +"* There are no exceptions." +msgstr "" +"* Les fonctions qui peuvent avoir des erreurs le listent dans leur type de retour,\n" +"* Il n'y a aucune exception." + +#: src/error-handling/panics.md:1 +#, fuzzy +msgid "# Panics" +msgstr "# paniques" + +#: src/error-handling/panics.md:3 +#, fuzzy +msgid "Rust will trigger a panic if a fatal error happens at runtime:" +msgstr "Rust déclenchera une panique si une erreur fatale se produit lors de l'exécution :" + +#: src/error-handling/panics.md:5 +msgid "" +"```rust,editable,should_panic\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" println!(\"v[100]: {}\", v[100]);\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/panics.md:12 +#, fuzzy +msgid "" +"* Panics are for unrecoverable and unexpected errors.\n" +" * Panics are symptoms of bugs in the program.\n" +"* Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." +msgstr "" +"* Les paniques concernent les erreurs irrécupérables et inattendues.\n" +" * Les paniques sont des symptômes de bogues dans le programme.\n" +"* Utilisez des API qui ne paniquent pas (telles que `Vec::get`) si le plantage n'est pas acceptable." + +#: src/error-handling/panic-unwind.md:1 +#, fuzzy +msgid "# Catching the Stack Unwinding" +msgstr "# Attraper la pile qui se déroule" + +#: src/error-handling/panic-unwind.md:3 +#, fuzzy +msgid "By default, a panic will cause the stack to unwind. The unwinding can be caught:" +msgstr "Par défaut, une panique entraînera le déroulement de la pile. Le déroulement peut être rattrapé :" + +#: src/error-handling/panic-unwind.md:5 +msgid "" +"```rust\n" +"use std::panic;\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" println!(\"hello!\");\n" +"});\n" +"assert!(result.is_ok());\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" panic!(\"oh no!\");\n" +"});\n" +"assert!(result.is_err());\n" +"```" +msgstr "" + +#: src/error-handling/panic-unwind.md:19 +#, fuzzy +msgid "" +"* This can be useful in servers which should keep running even if a single\n" +" request crashes.\n" +"* This does not work if `panic = 'abort'` is set in your `Cargo.toml`." +msgstr "" +"* Cela peut être utile dans les serveurs qui doivent continuer à fonctionner même si un seul\n" +" la demande se bloque.\n" +"* Cela ne fonctionne pas si `panic = 'abort'` est défini dans votre `Cargo.toml`." + +#: src/error-handling/result.md:1 +#, fuzzy +msgid "# Structured Error Handling with `Result`" +msgstr "# Gestion structurée des erreurs avec `Result`" + +#: src/error-handling/result.md:3 +#, fuzzy +msgid "" +"We have already seen the `Result` enum. This is used pervasively when errors are\n" +"expected as part of normal operation:" +msgstr "" +"Nous avons déjà vu l'énumération `Result`. Ceci est utilisé partout lorsque des erreurs sont\n" +"prévu dans le cadre d'un fonctionnement normal :" + +#: src/error-handling/result.md:6 +msgid "" +"```rust\n" +"use std::fs::File;\n" +"use std::io::Read;\n" +"\n" +"fn main() {\n" +" let file = File::open(\"diary.txt\");\n" +" match file {\n" +" Ok(mut file) => {\n" +" let mut contents = String::new();\n" +" file.read_to_string(&mut contents);\n" +" println!(\"Dear diary: {contents}\");\n" +" },\n" +" Err(err) => {\n" +" println!(\"The diary could not be opened: {err}\");\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/result.md:27 +#, fuzzy +msgid "" +" * As with `Option`, the successful value sits inside of `Result`, forcing the developer to\n" +" explicitly extract it. This encourages error checking. In the case where an error should never happen,\n" +" `unwrap()` or `expect()` can be called, and this is a signal of the developer intent too. \n" +" * `Result` documentation is a recommended read. Not during the course, but it is worth mentioning. \n" +" It contains a lot of convenience methods and functions that help functional-style programming. \n" +" " +msgstr "" +" * Comme pour `Option`, la valeur réussie se trouve à l'intérieur de `Result`, obligeant le développeur à\n" +" l'extraire explicitement. Cela encourage la vérification des erreurs. Dans le cas où une erreur ne devrait jamais se produire,\n" +" `unwrap()` ou `expect()` peut être appelé, et c'est aussi un signal de l'intention du développeur.\n" +" * La documentation `Result` est une lecture recommandée. Pas pendant le cours, mais cela vaut la peine d'être mentionné.\n" +" Il contient de nombreuses méthodes et fonctions pratiques qui facilitent la programmation de style fonctionnel.\n" +" " + +#: src/error-handling/try-operator.md:1 +#, fuzzy +msgid "# Propagating Errors with `?`" +msgstr "# Propagation des erreurs avec `?`" + +#: src/error-handling/try-operator.md:3 +#, fuzzy +msgid "" +"The try-operator `?` is used to return errors to the caller. It lets you turn\n" +"the common" +msgstr "" +"L'opérateur try `?` est utilisé pour renvoyer des erreurs à l'appelant. Il vous permet de tourner\n" +"le commun" + +#: src/error-handling/try-operator.md:6 +msgid "" +"```rust,ignore\n" +"match some_expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(err),\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:13 +#, fuzzy +msgid "into the much simpler" +msgstr "dans le plus simple" + +#: src/error-handling/try-operator.md:15 +msgid "" +"```rust,ignore\n" +"some_expression?\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:19 +#, fuzzy +msgid "We can use this to simplify our error handing code:" +msgstr "Nous pouvons l'utiliser pour simplifier notre code de gestion des erreurs :" + +#: src/error-handling/try-operator.md:21 +msgid "" +"```rust,editable\n" +"use std::fs;\n" +"use std::io::{self, Read};\n" +"\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" +" };\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" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"alice\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:52 src/error-handling/converting-error-types-example.md:52 +#, fuzzy +msgid "" +"* The `username` variable can be either `Ok(string)` or `Err(error)`.\n" +"* Use the `fs::write` call to test out the different scenarios: no file, empty file, file with username." +msgstr "" +"* La variable `username` peut être soit `Ok(string)` soit `Err(error)`.\n" +"* Utilisez l'appel `fs::write` pour tester les différents scénarios : pas de fichier, fichier vide, fichier avec nom d'utilisateur." + +#: src/error-handling/converting-error-types.md:1 src/error-handling/converting-error-types-example.md:1 +#, fuzzy +msgid "# Converting Error Types" +msgstr "# Conversion des types d'erreurs" + +#: src/error-handling/converting-error-types.md:3 +#, fuzzy +msgid "The effective expansion of `?` is a little more complicated than previously indicated:" +msgstr "L'expansion effective de `?` est un peu plus compliquée qu'indiqué précédemment :" + +#: src/error-handling/converting-error-types.md:5 +msgid "" +"```rust,ignore\n" +"expression?\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types.md:9 +#, fuzzy +msgid "works the same as" +msgstr "fonctionne de la même manière que" + +#: src/error-handling/converting-error-types.md:11 +msgid "" +"```rust,ignore\n" +"match expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(From::from(err)),\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types.md:18 +#, fuzzy +msgid "" +"The `From::from` call here means we attempt to convert the error type to the\n" +"type returned by the function:" +msgstr "" +"L'appel `From::from` ici signifie que nous essayons de convertir le type d'erreur en\n" +"type renvoyé par la fonction :" + +#: src/error-handling/converting-error-types-example.md:3 +msgid "" +"```rust,editable\n" +"use std::error::Error;\n" +"use std::fmt::{self, Display, Formatter};\n" +"use std::fs::{self, File};\n" +"use std::io::{self, Read};\n" +"\n" +"#[derive(Debug)]\n" +"enum ReadUsernameError {\n" +" IoError(io::Error),\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"impl Error for ReadUsernameError {}\n" +"\n" +"impl Display for ReadUsernameError {\n" +" fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" +" match self {\n" +" Self::IoError(e) => write!(f, \"IO error: {e}\"),\n" +" Self::EmptyUsername(filename) => write!(f, \"Found no username in {filename}\"),\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl From for ReadUsernameError {\n" +" fn from(err: io::Error) -> ReadUsernameError {\n" +" ReadUsernameError::IoError(err)\n" +" }\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:55 +#, fuzzy +msgid "" +"It is good practice for all error types to implement `std::error::Error`, which requires `Debug` and\n" +"`Display`. It's generally helpful for them to implement `Clone` and `Eq` too where possible, to make\n" +"life easier for tests and consumers of your library. In this case we can't easily do so, because\n" +"`io::Error` doesn't implement them." +msgstr "" +"C'est une bonne pratique pour tous les types d'erreurs d'implémenter `std::error::Error`, qui nécessite `Debug` et\n" +"'Affichage'. Il est généralement utile pour eux d'implémenter `Clone` et `Eq` aussi lorsque cela est possible, pour faire\n" +"la vie plus facile pour les testeurs et les consommateurs de votre bibliothèque. Dans ce cas, nous ne pouvons pas le faire facilement, car\n" +"`io::Error` ne les implémente pas." + +#: src/error-handling/deriving-error-enums.md:1 +#, fuzzy +msgid "# Deriving Error Enums" +msgstr "# Dérivation des énumérations d'erreur" + +#: src/error-handling/deriving-error-enums.md:3 +#, fuzzy +msgid "" +"The [thiserror](https://docs.rs/thiserror/) crate is a popular way to create an\n" +"error enum like we did on the previous page:" +msgstr "" +"La caisse [thiserror](https://docs.rs/thiserror/) est un moyen populaire de créer un\n" +"error enum comme nous l'avons fait sur la page précédente :" + +#: src/error-handling/deriving-error-enums.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"\n" +"#[derive(Debug, Error)]\n" +"enum ReadUsernameError {\n" +" #[error(\"Could not read: {0}\")]\n" +" IoError(#[from] io::Error),\n" +" #[error(\"Found no username in {0}\")]\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:39 +#, fuzzy +msgid "" +"`thiserror`'s derive macro automatically implements `std::error::Error`, and optionally `Display`\n" +"(if the `#[error(...)]` attributes are provided) and `From` (if the `#[from]` attribute is added).\n" +"It also works for structs." +msgstr "" +"La macro de dérivation de `thiserror` implémente automatiquement `std::error::Error` et éventuellement `Display`\n" +"(si les attributs `#[error(...)]` sont fournis) et `From` (si l'attribut `#[from]` est ajouté).\n" +"Cela fonctionne également pour les structures." + +#: src/error-handling/deriving-error-enums.md:43 +#, fuzzy +msgid "It doesn't affect your public API, which makes it good for libraries." +msgstr "Cela n'affecte pas votre API publique, ce qui le rend bon pour les bibliothèques." + +#: src/error-handling/dynamic-errors.md:1 +#, fuzzy +msgid "# Dynamic Error Types" +msgstr "# Types d'erreurs dynamiques" + +#: src/error-handling/dynamic-errors.md:3 +#, fuzzy +msgid "" +"Sometimes we want to allow any type of error to be returned without writing our own enum covering\n" +"all the different possibilities. `std::error::Error` makes this easy." +msgstr "" +"Parfois, nous voulons permettre à tout type d'erreur d'être renvoyé sans écrire notre propre énumération couvrant\n" +"toutes les différentes possibilités. `std::error::Error` rend cela facile." + +#: src/error-handling/dynamic-errors.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use std::fs::{self, File};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"use std::error::Error;\n" +"\n" +"#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" +"#[error(\"Found no username in {0}\")]\n" +"struct EmptyUsernameError(String);\n" +"\n" +"fn read_username(path: &str) -> Result> {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(EmptyUsernameError(String::from(path)).into());\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/dynamic-errors.md:36 +#, fuzzy +msgid "" +"This saves on code, but gives up the ability to cleanly handle different error cases differently in\n" +"the program. As such it's generally not a good idea to use `Box` in the public API of a\n" +"library, but it can be a good option in a program where you just want to display the error message\n" +"somewhere." +msgstr "" +"Cela permet d'économiser du code, mais abandonne la possibilité de gérer proprement différents cas d'erreur différemment dans\n" +"le programme. En tant que tel, ce n'est généralement pas une bonne idée d'utiliser `Box` dans l'API publique d'un\n" +"bibliothèque, mais cela peut être une bonne option dans un programme où vous voulez juste afficher le message d'erreur\n" +"quelque part." + +#: src/error-handling/error-contexts.md:1 +#, fuzzy +msgid "# Adding Context to Errors" +msgstr "# Ajouter du contexte aux erreurs" + +#: src/error-handling/error-contexts.md:3 +#, fuzzy +msgid "" +"The widely used [anyhow](https://docs.rs/anyhow/) crate can help you add\n" +"contextual information to your errors and allows you to have fewer\n" +"custom error types:" +msgstr "" +"La caisse [anyhow](https://docs.rs/anyhow/) largement utilisée peut vous aider à ajouter\n" +"des informations contextuelles à vos erreurs et vous permet d'avoir moins\n" +"types d'erreur personnalisés :" + +#: src/error-handling/error-contexts.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use anyhow::{Context, Result, bail};\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)\n" +" .with_context(|| format!(\"Failed to open {path}\"))?\n" +" .read_to_string(&mut username)\n" +" .context(\"Failed to read\")?;\n" +" if username.is_empty() {\n" +" bail!(\"Found no username in {path}\");\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err:?}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/error-contexts.md:35 +#, fuzzy +msgid "" +"* `anyhow::Result` is a type alias for `Result`.\n" +"* `anyhow::Error` is essentially a wrapper around `Box`. As such it's again generally not\n" +" a good choice for the public API of a library, but is widely used in applications.\n" +"* Actual error type inside of it can be extracted for examination if necessary.\n" +"* Functionality provided by `anyhow::Result` may be familiar to Go developers, as it provides\n" +" similar usage patterns and ergonomics to `(T, error)` from Go." +msgstr "" +"* `anyhow::Result` est un alias de type pour `Result`.\n" +"* `anyhow::Error` est essentiellement un wrapper autour de `Box`. En tant que tel, ce n'est généralement pas\n" +" un bon choix pour l'API publique d'une bibliothèque, mais il est largement utilisé dans les applications.\n" +"* Le type d'erreur réel à l'intérieur peut être extrait pour examen si nécessaire.\n" +"* La fonctionnalité fournie par `anyhow::Result` peut être familière aux développeurs Go, car elle fournit\n" +" modèles d'utilisation et ergonomie similaires à `(T, erreur)` de Go." + +#: src/testing.md:1 +#, fuzzy +msgid "# Testing" +msgstr "# Test" + +#: src/testing.md:3 +#, fuzzy +msgid "Rust and Cargo come with a simple unit test framework:" +msgstr "Rust et Cargo sont livrés avec un cadre de test unitaire simple :" + +#: src/testing.md:5 +#, fuzzy +msgid "" +"* Unit tests are supported throughout your code.\n" +"\n" +"* Integration tests are supported via the `tests/` directory." +msgstr "" +"* Les tests unitaires sont pris en charge dans tout votre code.\n" +"\n" +"* Les tests d'intégration sont pris en charge via le répertoire `tests/`." + +#: src/testing/unit-tests.md:1 +#, fuzzy +msgid "# Unit Tests" +msgstr "# Tests unitaires" + +#: src/testing/unit-tests.md:3 +#, fuzzy +msgid "Mark unit tests with `#[test]`:" +msgstr "Marquez les tests unitaires avec `#[test]` :" + +#: src/testing/unit-tests.md:5 +msgid "" +"```rust,ignore\n" +"fn first_word(text: &str) -> &str {\n" +" match text.find(' ') {\n" +" Some(idx) => &text[..idx],\n" +" None => &text,\n" +" }\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty() {\n" +" assert_eq!(first_word(\"\"), \"\");\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_word() {\n" +" assert_eq!(first_word(\"Hello\"), \"Hello\");\n" +"}\n" +"\n" +"#[test]\n" +"fn test_multiple_words() {\n" +" assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/testing/unit-tests.md:29 +#, fuzzy +msgid "Use `cargo test` to find and run the unit tests." +msgstr "Utilisez `cargo test` pour rechercher et exécuter les tests unitaires." + +#: src/testing/test-modules.md:1 +#, fuzzy +msgid "# Test Modules" +msgstr "# Modules d'essai" + +#: src/testing/test-modules.md:3 +#, fuzzy +msgid "" +"Unit tests are often put in a nested module (run tests on the\n" +"[Playground](https://play.rust-lang.org/)):" +msgstr "" +"Les tests unitaires sont souvent placés dans un module imbriqué (exécuter des tests sur le\n" +"[Terrain de jeu](https://play.rust-lang.org/)) :" + +#: src/testing/test-modules.md:6 +msgid "" +"```rust,editable\n" +"fn helper(a: &str, b: &str) -> String {\n" +" format!(\"{a} {b}\")\n" +"}\n" +"\n" +"pub fn main() {\n" +" println!(\"{}\", helper(\"Hello\", \"World\"));\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" #[test]\n" +" fn test_helper() {\n" +" assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/testing/test-modules.md:26 +#, fuzzy +msgid "" +"* This lets you unit test private helpers.\n" +"* The `#[cfg(test)]` attribute is only active when you run `cargo test`." +msgstr "" +"* Cela vous permet de tester unitairement les helpers privés.\n" +"* L'attribut `#[cfg(test)]` n'est actif que lorsque vous lancez `cargo test`." + +#: src/testing/doc-tests.md:1 +#, fuzzy +msgid "# Documentation Tests" +msgstr "# Essais documentaires" + +#: src/testing/doc-tests.md:3 +#, fuzzy +msgid "Rust has built-in support for documentation tests:" +msgstr "Rust a un support intégré pour les tests de documentation :" + +#: src/testing/doc-tests.md:5 +msgid "" +"```rust\n" +"/// Shortens a string to the given length.\n" +"///\n" +"/// ```\n" +"/// use playground::shorten_string;\n" +"/// assert_eq!(shorten_string(\"Hello World\", 5), \"Hello\");\n" +"/// assert_eq!(shorten_string(\"Hello World\", 20), \"Hello World\");\n" +"/// ```\n" +"pub fn shorten_string(s: &str, length: usize) -> &str {\n" +" &s[..std::cmp::min(length, s.len())]\n" +"}\n" +"```" +msgstr "" + +#: src/testing/doc-tests.md:18 +#, fuzzy +msgid "" +"* Code blocks in `///` comments are automatically seen as Rust code.\n" +"* The code will be compiled and executed as part of `cargo test`.\n" +"* Test the above code on the [Rust Playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." +msgstr "" +"* Les blocs de code dans les commentaires `///` sont automatiquement considérés comme du code Rust.\n" +"* Le code sera compilé et exécuté dans le cadre du `cargo test`.\n" +"* Testez le code ci-dessus sur [Rust Playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." + +#: src/testing/integration-tests.md:1 +#, fuzzy +msgid "# Integration Tests" +msgstr "# Tests d'intégration" + +#: src/testing/integration-tests.md:3 +#, fuzzy +msgid "If you want to test your library as a client, use an integration test." +msgstr "Si vous souhaitez tester votre bibliothèque en tant que client, utilisez un test d'intégration." + +#: src/testing/integration-tests.md:5 +#, fuzzy +msgid "Create a `.rs` file under `tests/`:" +msgstr "Créez un fichier `.rs` sous `tests/` :" + +#: src/testing/integration-tests.md:7 +msgid "" +"```rust,ignore\n" +"use my_library::init;\n" +"\n" +"#[test]\n" +"fn test_init() {\n" +" assert!(init().is_ok());\n" +"}\n" +"```" +msgstr "" + +#: src/testing/integration-tests.md:16 +#, fuzzy +msgid "These tests only have access to the public API of your crate." +msgstr "Ces tests n'ont accès qu'à l'API publique de votre crate." + +#: src/unsafe.md:1 +#, fuzzy +msgid "# Unsafe Rust" +msgstr "# Rouille dangereuse" + +#: src/unsafe.md:3 +#, fuzzy +msgid "The Rust language has two parts:" +msgstr "Le langage Rust comporte deux parties :" + +#: src/unsafe.md:5 +#, fuzzy +msgid "" +"* **Safe Rust:** memory safe, no undefined behavior possible.\n" +"* **Unsafe Rust:** can trigger undefined behavior if preconditions are violated." +msgstr "" +"* **Safe Rust :** mémoire sécurisée, aucun comportement indéfini possible.\n" +"* **Unsafe Rust :** peut déclencher un comportement indéfini si les conditions préalables ne sont pas respectées." + +#: src/unsafe.md:8 +#, fuzzy +msgid "" +"We will be seeing mostly safe Rust in this course, but it's important to know\n" +"what Unsafe Rust is." +msgstr "" +"Nous verrons principalement Rust sûr dans ce cours, mais il est important de savoir\n" +"ce qu'est la rouille dangereuse." + +#: src/unsafe.md:11 +#, fuzzy +msgid "" +"Unsafe code is usually small and isolated, and its correctness should be carefully\n" +"documented. It is usually wrapped in a safe abstraction layer." +msgstr "" +"Le code dangereux est généralement petit et isolé, et son exactitude doit être soigneusement\n" +"documenté. Il est généralement enveloppé dans une couche d'abstraction sûre." + +#: src/unsafe.md:14 +#, fuzzy +msgid "Unsafe Rust gives you access to five new capabilities:" +msgstr "Unsafe Rust vous donne accès à cinq nouvelles fonctionnalités :" + +#: src/unsafe.md:16 +#, fuzzy +msgid "" +"* Dereference raw pointers.\n" +"* Access or modify mutable static variables.\n" +"* Access `union` fields.\n" +"* Call `unsafe` functions, including `extern` functions.\n" +"* Implement `unsafe` traits." +msgstr "" +"* Déréférencer les pointeurs bruts.\n" +"* Accéder ou modifier des variables statiques mutables.\n" +"* Accéder aux champs \"union\".\n" +"* Appelez les fonctions `unsafe`, y compris les fonctions `extern`.\n" +"* Mettre en œuvre les traits \" non sécurisés \"." + +#: src/unsafe.md:22 +#, fuzzy +msgid "" +"We will briefly cover unsafe capabilities next. For full details, please see\n" +"[Chapter 19.1 in the Rust Book](https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html)\n" +"and the [Rustonomicon](https://doc.rust-lang.org/nomicon/)." +msgstr "" +"Nous aborderons ensuite brièvement les capacités dangereuses. Pour plus de détails, veuillez consulter\n" +"[Chapitre 19.1 du Rust Book](https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html)\n" +"et le [Rustonomicon](https://doc.rust-lang.org/nomicon/)." + +#: src/unsafe.md:28 +#, fuzzy +msgid "" +"Unsafe Rust does not mean the code is incorrect. It means that developers have\n" +"turned off the compiler safety features and have to write correct code by\n" +"themselves. It means the compiler no longer enforces Rust's memory-safety rules." +msgstr "" +"Unsafe Rust ne signifie pas que le code est incorrect. Cela signifie que les développeurs ont\n" +"désactivé les fonctionnalités de sécurité du compilateur et doit écrire le code correct en\n" +"eux-mêmes. Cela signifie que le compilateur n'applique plus les règles de sécurité de la mémoire de Rust." + +#: src/unsafe/raw-pointers.md:1 +#, fuzzy +msgid "# Dereferencing Raw Pointers" +msgstr "# Déréférencement des pointeurs bruts" + +#: src/unsafe/raw-pointers.md:3 +#, fuzzy +msgid "Creating pointers is safe, but dereferencing them requires `unsafe`:" +msgstr "La création de pointeurs est sûre, mais leur déréférencement nécessite `unsafe` :" + +#: src/unsafe/raw-pointers.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut num = 5;\n" +"\n" +" 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" +" // references or concurrently through any other pointers.\n" +" unsafe {\n" +" println!(\"r1 is: {}\", *r1);\n" +" *r1 = 10;\n" +" println!(\"r2 is: {}\", *r2);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/raw-pointers.md:26 +#, fuzzy +msgid "" +"It is good practice (and required by the Android Rust style guide) to write a comment for each\n" +"`unsafe` block explaining how the code inside it satisfies the safety requirements of the unsafe\n" +"operations it is doing." +msgstr "" +"Il est recommandé (et requis par le guide de style Android Rust) d'écrire un commentaire pour chaque\n" +"Bloc `unsafe` expliquant comment le code à l'intérieur satisfait aux exigences de sécurité de l'unsafe\n" +"opérations qu'il effectue." + +#: src/unsafe/raw-pointers.md:30 +#, fuzzy +msgid "" +"In the case of pointer dereferences, this means that the pointers must be\n" +"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), i.e.:" +msgstr "" +"Dans le cas des déréférencements de pointeurs, cela signifie que les pointeurs doivent être\n" +"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), c'est-à-dire :" + +#: src/unsafe/raw-pointers.md:33 +#, fuzzy +msgid "" +" * The pointer must be non-null.\n" +" * The pointer must be _dereferenceable_ (within the bounds of a single allocated object).\n" +" * The object must not have been deallocated.\n" +" * There must not be concurrent accesses to the same location.\n" +" * If the pointer was obtained by casting a reference, the underlying object must be live and no\n" +" reference may be used to access the memory." +msgstr "" +" * Le pointeur doit être non nul.\n" +" * Le pointeur doit être _dereferenceable_ (dans les limites d'un seul objet alloué).\n" +" * L'objet ne doit pas avoir été désalloué.\n" +" * Il ne doit pas y avoir d'accès simultanés au même endroit.\n" +" * Si le pointeur a été obtenu en transtypant une référence, l'objet sous-jacent doit être actif et non\n" +" référence peut être utilisée pour accéder à la mémoire." + +#: src/unsafe/raw-pointers.md:40 +#, fuzzy +msgid "In most cases the pointer must also be properly aligned." +msgstr "Dans la plupart des cas, le pointeur doit également être correctement aligné." + +#: src/unsafe/mutable-static-variables.md:1 +#, fuzzy +msgid "# Mutable Static Variables" +msgstr "# Variables statiques mutables" + +#: src/unsafe/mutable-static-variables.md:3 +#, fuzzy +msgid "It is safe to read an immutable static variable:" +msgstr "Il est sûr de lire une variable statique immuable :" + +#: src/unsafe/mutable-static-variables.md:5 +msgid "" +"```rust,editable\n" +"static HELLO_WORLD: &str = \"Hello, world!\";\n" +"\n" +"fn main() {\n" +" println!(\"HELLO_WORLD: {HELLO_WORLD}\");\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:13 +#, fuzzy +msgid "" +"However, since data races can occur, it is unsafe to read and write mutable\n" +"static variables:" +msgstr "" +"Cependant, étant donné que des courses de données peuvent se produire, il n'est pas sûr de lire et d'écrire mutable\n" +"variables statiques :" + +#: src/unsafe/mutable-static-variables.md:16 +msgid "" +"```rust,editable\n" +"static mut COUNTER: u32 = 0;\n" +"\n" +"fn add_to_counter(inc: u32) {\n" +" unsafe { COUNTER += inc; } // Potential data race!\n" +"}\n" +"\n" +"fn main() {\n" +" add_to_counter(42);\n" +"\n" +" unsafe { println!(\"COUNTER: {COUNTER}\"); } // Potential data race!\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:32 +#, fuzzy +msgid "" +"Using a mutable static is generally a bad idea, but there are some cases where it might make sense\n" +"in low-level `no_std` code, such as implementing a heap allocator or working with some C APIs." +msgstr "" +"L'utilisation d'une statique mutable est généralement une mauvaise idée, mais il y a des cas où cela peut avoir du sens\n" +"dans le code `no_std` de bas niveau, comme l'implémentation d'un allocation de tas ou l'utilisation de certaines API C." + +#: src/unsafe/unions.md:1 +#, fuzzy +msgid "# Unions" +msgstr "# syndicats" + +#: src/unsafe/unions.md:3 +#, fuzzy +msgid "Unions are like enums, but you need to track the active field yourself:" +msgstr "Les unions sont comme des énumérations, mais vous devez suivre vous-même le champ actif :" + +#: src/unsafe/unions.md:5 +msgid "" +"```rust,editable\n" +"#[repr(C)]\n" +"union MyUnion {\n" +" i: u8,\n" +" b: bool,\n" +"}\n" +"\n" +"fn main() {\n" +" let u = MyUnion { i: 42 };\n" +" println!(\"int: {}\", unsafe { u.i });\n" +" println!(\"bool: {}\", unsafe { u.b }); // Undefined behavior!\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/unions.md:21 +#, fuzzy +msgid "" +"Unions are very rarely needed in Rust as you can usually use an enum. They are occasionally needed\n" +"for interacting with C library APIs." +msgstr "" +"Les unions sont très rarement nécessaires dans Rust car vous pouvez généralement utiliser une énumération. Ils sont parfois nécessaires\n" +"pour interagir avec les API de la bibliothèque C." + +#: src/unsafe/unions.md:24 +#, fuzzy +msgid "" +"If you just want to reinterpret bytes as a different type, you probably want\n" +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn.transmute.html) or a safe\n" +"wrapper such as the [`zerocopy`](https://crates.io/crates/zerocopy) crate." +msgstr "" +"Si vous voulez simplement réinterpréter les octets comme un type différent, vous voudrez probablement\n" +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn.transmute.html) ou un coffre-fort\n" +"wrapper tel que la caisse [`zerocopy`](https://crates.io/crates/zerocopy)." + +#: src/unsafe/calling-unsafe-functions.md:1 +#, fuzzy +msgid "# Calling Unsafe Functions" +msgstr "# Appel de fonctions non sûres" + +#: src/unsafe/calling-unsafe-functions.md:3 +#, fuzzy +msgid "" +"A function or method can be marked `unsafe` if it has extra preconditions you\n" +"must uphold to avoid undefined behaviour:" +msgstr "" +"Une fonction ou une méthode peut être marquée \"unsafe\" si elle a des conditions préalables supplémentaires que vous\n" +"doit respecter pour éviter un comportement indéfini :" + +#: src/unsafe/calling-unsafe-functions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let emojis = \"🗻∈🌏\";\n" +"\n" +" // Safe because the indices are in the correct order, within the bounds of\n" +" // the string slice, and lie on UTF-8 sequence boundaries.\n" +" unsafe {\n" +" println!(\"emoji: {}\", emojis.get_unchecked(0..4));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(4..7));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(7..11));\n" +" }\n" +"\n" +" println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..7) }));\n" +"\n" +" // Not upholding the UTF-8 encoding requirement breaks memory safety!\n" +" // println!(\"emoji: {}\", unsafe { emojis.get_unchecked(0..3) });\n" +" // println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..3) }));\n" +"}\n" +"\n" +"fn count_chars(s: &str) -> usize {\n" +" s.chars().map(|_| 1).sum()\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:1 +#, fuzzy +msgid "# Writing Unsafe Functions" +msgstr "# Écrire des fonctions non sécurisées" + +#: src/unsafe/writing-unsafe-functions.md:3 +#, fuzzy +msgid "" +"You can mark your own functions as `unsafe` if they require particular conditions to avoid undefined\n" +"behaviour." +msgstr "" +"Vous pouvez marquer vos propres fonctions comme \"non sécurisées\" si elles nécessitent des conditions particulières pour éviter undefined\n" +"comportement." + +#: src/unsafe/writing-unsafe-functions.md:6 +msgid "" +"```rust,editable\n" +"/// Swaps the values pointed to by the given pointers.\n" +"///\n" +"/// # Safety\n" +"///\n" +"/// The pointers must be valid and properly aligned.\n" +"unsafe fn swap(a: *mut u8, b: *mut u8) {\n" +" let temp = *a;\n" +" *a = *b;\n" +" *b = temp;\n" +"}\n" +"\n" +"fn main() {\n" +" let mut a = 42;\n" +" let mut b = 66;\n" +"\n" +" // Safe because ...\n" +" unsafe {\n" +" swap(&mut a, &mut b);\n" +" }\n" +"\n" +" println!(\"a = {}, b = {}\", a, b);\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:33 +#, fuzzy +msgid "We wouldn't actually use pointers for this because it can be done safely with references." +msgstr "Nous n'utiliserions pas de pointeurs pour cela car cela peut être fait en toute sécurité avec des références." + +#: src/unsafe/writing-unsafe-functions.md:35 +#, fuzzy +msgid "" +"Note that unsafe code is allowed within an unsafe function without an `unsafe` block. We can\n" +"prohibit this with `#[deny(unsafe_op_in_unsafe_fn)]`. Try adding it and see what happens." +msgstr "" +"Notez que le code non sécurisé est autorisé dans une fonction non sécurisée sans bloc « non sécurisé ». Nous pouvons\n" +"interdisez cela avec `#[deny(unsafe_op_in_unsafe_fn)]`. Essayez de l'ajouter et voyez ce qui se passe." + +#: src/unsafe/extern-functions.md:1 +#, fuzzy +msgid "# Calling External Code" +msgstr "# Appeler le code externe" + +#: src/unsafe/extern-functions.md:3 +#, fuzzy +msgid "" +"Functions from other languages might violate the guarantees of Rust. Calling\n" +"them is thus unsafe:" +msgstr "" +"Les fonctions d'autres langages peuvent violer les garanties de Rust. Appel\n" +"eux est donc dangereux :" + +#: src/unsafe/extern-functions.md:6 +msgid "" +"```rust,editable\n" +"extern \"C\" {\n" +" fn abs(input: i32) -> i32;\n" +"}\n" +"\n" +"fn main() {\n" +" unsafe {\n" +" // Undefined behavior if abs misbehaves.\n" +" println!(\"Absolute value of -3 according to C: {}\", abs(-3));\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/extern-functions.md:21 +#, fuzzy +msgid "" +"This is usually only a problem for extern functions which do things with pointers which might\n" +"violate Rust's memory model, but in general any C function might have undefined behaviour under any\n" +"arbitrary circumstances." +msgstr "" +"Ce n'est généralement un problème que pour les fonctions externes qui font des choses avec des pointeurs qui pourraient\n" +"violer le modèle de mémoire de Rust, mais en général, toute fonction C peut avoir un comportement indéfini sous n'importe quel\n" +"circonstances arbitraires." + +#: src/unsafe/extern-functions.md:25 +msgid "" +"The `\"C\"` in this example is the ABI;\n" +"[other ABIs are available too](https://doc.rust-lang.org/reference/items/external-blocks.html)." +msgstr "" + +#: src/unsafe/unsafe-traits.md:1 +#, fuzzy +msgid "# Implementing Unsafe Traits" +msgstr "# Implémenter des traits dangereux" + +#: src/unsafe/unsafe-traits.md:3 +#, fuzzy +msgid "" +"Like with functions, you can mark a trait as `unsafe` if the implementation must guarantee\n" +"particular conditions to avoid undefined behaviour." +msgstr "" +"Comme avec les fonctions, vous pouvez marquer un trait comme \"non sécurisé\" si l'implémentation doit garantir\n" +"conditions particulières pour éviter un comportement indéfini." + +#: src/unsafe/unsafe-traits.md:6 +#, fuzzy +msgid "" +"For example, the `zerocopy` crate has an unsafe trait that looks\n" +"[something like this](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" +msgstr "" +"Par exemple, la caisse \"zérocopie\" a un trait dangereux qui semble\n" +"[quelque chose comme ça](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" + +#: src/unsafe/unsafe-traits.md:9 +msgid "" +"```rust,editable\n" +"use std::mem::size_of_val;\n" +"use std::slice;\n" +"\n" +"/// ...\n" +"/// # Safety\n" +"/// The type must have a defined representation and no padding.\n" +"pub unsafe trait AsBytes {\n" +" fn as_bytes(&self) -> &[u8] {\n" +" unsafe {\n" +" slice::from_raw_parts(self as *const Self as *const u8, size_of_val(self))\n" +" }\n" +" }\n" +"}\n" +"\n" +"// Safe because u32 has a defined representation and no padding.\n" +"unsafe impl AsBytes for u32 {}\n" +"```" +msgstr "" + +#: src/unsafe/unsafe-traits.md:30 +#, fuzzy +msgid "" +"There should be a `# Safety` section on the Rustdoc for the trait explaining the requirements for\n" +"the trait to be safely implemented." +msgstr "" +"Il devrait y avoir une section `# Sécurité` sur le Rustdoc pour le trait expliquant les exigences pour\n" +"le trait à mettre en œuvre en toute sécurité." + +#: src/unsafe/unsafe-traits.md:33 +#, fuzzy +msgid "The actual safety section for `AsBytes` is rather longer and more complicated." +msgstr "La section de sécurité actuelle pour `AsBytes` est plutôt plus longue et plus compliquée." + +#: src/unsafe/unsafe-traits.md:35 +#, fuzzy +msgid "The built-in `Send` and `Sync` traits are unsafe." +msgstr "Les traits intégrés \"Envoyer\" et \"Synchroniser\" ne sont pas sûrs." + +#: src/exercises/day-3/afternoon.md:1 +#, fuzzy +msgid "# Day 3: Afternoon Exercises" +msgstr "# Jour 3 : Exercices de l'après-midi" + +#: src/exercises/day-3/afternoon.md:3 +#, fuzzy +msgid "Let us build a safe wrapper for reading directory content!" +msgstr "Construisons un wrapper sûr pour lire le contenu du répertoire !" + +#: src/exercises/day-3/afternoon.md:7 +#, fuzzy +msgid "After looking at the exercise, you can look at the [solution] provided." +msgstr "Après avoir regardé l'exercice, vous pouvez regarder la [solution] fournie." + +#: src/exercises/day-3/safe-ffi-wrapper.md:1 +#, fuzzy +msgid "# Safe FFI Wrapper" +msgstr "# Enveloppe FFI sécurisée" + +#: src/exercises/day-3/safe-ffi-wrapper.md:3 +#, fuzzy +msgid "" +"Rust has great support for calling functions through a _foreign function\n" +"interface_ (FFI). We will use this to build a safe wrapper for the `libc`\n" +"functions you would use from C to read the filenames of a directory." +msgstr "" +"Rust a un excellent support pour appeler des fonctions via une fonction _foreign\n" +"interface_ (FFI). Nous allons l'utiliser pour construire un wrapper sûr pour la `libc`\n" +"fonctions que vous utiliseriez à partir de C pour lire les noms de fichiers d'un répertoire." + +#: src/exercises/day-3/safe-ffi-wrapper.md:7 +#, fuzzy +msgid "You will want to consult the manual pages:" +msgstr "Vous voudrez consulter les pages de manuel :" + +#: src/exercises/day-3/safe-ffi-wrapper.md:9 +#, fuzzy +msgid "" +"* [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)\n" +"* [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)\n" +"* [`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)" +msgstr "" +"* [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)\n" +"* [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)\n" +"* [`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." +msgstr "" +"Vous voudrez également parcourir le module [`std :: ffi`], en particulier pour [`CStr`]\n" +"et [`CString`] qui sont utilisés pour contenir des chaînes terminées par NUL provenant de\n" +"C. Le [Nomicon] a également un chapitre très utile sur FFI." + +#: src/exercises/day-3/safe-ffi-wrapper.md:22 +#, fuzzy +msgid "" +"Copy the code below to and fill in the missing\n" +"functions and methods:" +msgstr "" +"Copiez le code ci-dessous sur et remplissez les champs manquants\n" +"fonctions et méthodes :" + +#: src/exercises/day-3/safe-ffi-wrapper.md:25 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}\n" +"\n" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/welcome-day-4.md:1 +#, fuzzy +msgid "# Welcome to Day 4" +msgstr "# Bienvenue au jour 4" + +#: src/welcome-day-4.md:3 +#, fuzzy +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 "" +"Ce matin, nous nous concentrerons sur la simultanéité : les threads, les canaux, l'état partagé, `Send` et `Sync`.\n" +"Dans l'après-midi, nous aurons la chance de voir Rust en action." + +#: src/welcome-day-4.md:8 +#, fuzzy +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 "" +"C'est le bon moment pour donner un aperçu de ce que vous couvrirez dans l'après-midi\n" +"section, tel qu'annoncé dans l'offre de cours." + +#: src/concurrency.md:1 +#, fuzzy +msgid "# Fearless Concurrency" +msgstr "# Concurrence intrépide" + +#: src/concurrency.md:3 +#, fuzzy +msgid "" +"Rust has full support for concurrency using OS threads with mutexes and\n" +"channels." +msgstr "" +"Rust prend entièrement en charge la concurrence en utilisant des threads de système d'exploitation avec des mutex et\n" +"canaux." + +#: 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 "" +"Le système de type Rust joue un rôle important dans la création de nombreux bugs de concurrence\n" +"bogues de temps de compilation. Ceci est souvent appelé _concurrence sans peur_ puisque vous\n" +"peut compter sur le compilateur pour assurer l'exactitude au moment de l'exécution." + +#: src/concurrency/threads.md:1 +#, fuzzy +msgid "# Threads" +msgstr "# fils" + +#: src/concurrency/threads.md:3 +#, fuzzy +msgid "Rust threads work similarly to threads in other languages:" +msgstr "Les threads Rust fonctionnent de la même manière que les threads dans d'autres langages :" + +#: 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 "" +"* Les threads sont tous des threads démons, le thread principal ne les attend pas.\n" +"* Les thread panics sont indépendants les uns des autres.\n" +" * Les paniques peuvent transporter une charge utile, qui peut être décompressée avec `downcast_ref`." + +#: src/concurrency/threads.md:32 +#, fuzzy +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 "" +"* Notez que le thread est arrêté avant d'atteindre 10 — le thread principal est\n" +" pas attendre.\n" +"\n" +"* Utilisez `let handle = thread::spawn(...)` et plus tard `handle.join()` pour attendre\n" +" le fil pour finir.\n" +"\n" +"* Déclenchez une panique dans le fil, notez que cela n'affecte pas `main`.\n" +"\n" +"* Utilisez la valeur de retour `Result` de `handle.join()` pour accéder à la panique\n" +" charge utile. C'est le bon moment pour parler de [`Tous`]." + +#: src/concurrency/scoped-threads.md:1 +#, fuzzy +msgid "# Scoped Threads" +msgstr "# Threads délimités" + +#: src/concurrency/scoped-threads.md:3 +#, fuzzy +msgid "Normal threads cannot borrow from their environment:" +msgstr "Les threads normaux ne peuvent pas emprunter à leur environnement :" + +#: 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 "Cependant, vous pouvez utiliser un [fil de discussion de portée][1] pour cela :" + +#: 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 "" +"* La raison en est que lorsque la fonction `thread::scope` se termine, tous les threads sont garantis d'être joints, afin qu'ils puissent renvoyer " +"des données empruntées.\n" +"* Les règles d'emprunt normales de Rust s'appliquent : vous pouvez soit emprunter de manière mutable par un thread, soit de manière immuable par " +"n'importe quel nombre de threads.\n" +" " + +#: src/concurrency/channels.md:1 +#, fuzzy +msgid "# Channels" +msgstr "# Chaînes" + +#: 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 "" +"Les canaux Rust ont deux parties : un `Sender` et un `Receiver`. Les deux parties\n" +"sont connectés via le canal, mais vous ne voyez que les extrémités." + +#: 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` signifie Multi-Producer, Single-Consumer. `Sender` et `SyncSender` implémentent `Clone` (donc\n" +" vous pouvez créer plusieurs producteurs) mais `Receiver` ne le fait pas.\n" +"* `send()` et `recv()` renvoient `Result`. S'ils renvoient `Err`, cela signifie que la contrepartie `Sender` ou\n" +" `Receiver` est supprimé et le canal est fermé." + +#: src/concurrency/channels/unbounded.md:1 +#, fuzzy +msgid "# Unbounded Channels" +msgstr "# Canaux illimités" + +#: src/concurrency/channels/unbounded.md:3 +#, fuzzy +msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" +msgstr "Vous obtenez un canal illimité et asynchrone avec `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 "# Canaux limités" + +#: src/concurrency/channels/bounded.md:3 +#, fuzzy +msgid "Bounded and synchronous channels make `send` block the current thread:" +msgstr "Les canaux bornés et synchrones font que \"send\" bloque le thread actuel :" + +#: 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 "# État partagé" + +#: 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 utilise le système de type pour appliquer la synchronisation des données partagées. C'est\n" +"se fait principalement via deux types:" + +#: 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], référence atomique comptée `T` : gère le partage entre les threads et\n" +" prend soin de désallouer 'T' lorsque la dernière référence est supprimée,\n" +"* [`Mutex`][2] : garantit un accès mutuellement exclusif à la valeur `T`." + +#: src/concurrency/shared_state/arc.md:1 +#, fuzzy +msgid "# `Arc`" +msgstr "# `Arc`" + +#: src/concurrency/shared_state/arc.md:3 +#, fuzzy +msgid "[`Arc`][1] allows shared read-only access via its `clone` method:" +msgstr "[`Arc`][1] permet un accès partagé en lecture seule via sa méthode `clone` :" + +#: 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` signifie \"Atomic Reference Counted\", une version thread-safe de `Rc` qui utilise\n" +" opérations.\n" +"* `Arc` implémente `Clone` que `T` le fasse ou non. Il implémente `Send` et `Sync` ssi `T`\n" +" les met en œuvre tous les deux.\n" +"* `Arc::clone()` a le coût des opérations atomiques qui sont exécutées, mais après cela, l'utilisation du\n" +" 'T' est libre.\n" +"* Méfiez-vous des cycles de référence, `Arc` n'utilise pas de ramasse-miettes pour les détecter.\n" +" * `std::sync::Weak` peut aider." + +#: 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] garantit l'exclusion mutuelle _et_ permet un accès mutable à `T`\n" +"derrière une interface en lecture seule :" + +#: 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 "" +"Remarquez comment nous avons une couverture [`impl Sync for Mutex`][2]\n" +"mise en œuvre." + +#: 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` dans Rust ressemble à une collection avec un seul élément - les données protégées.\n" +" * Il n'est pas possible d'oublier d'acquérir le mutex avant d'accéder aux données protégées.\n" +"* Vous pouvez obtenir un `&mut T` à partir d'un `&Mutex` en prenant le verrou. Le `MutexGuard` garantit que le\n" +" `&mut T` ne survit pas au verrouillage en cours.\n" +"* `Mutex` implémente à la fois `Send` et `Sync` ssi `T` implémente `Send`.\n" +"* Un homologue de verrouillage en lecture-écriture - `RwLock`.\n" +"* Pourquoi `lock()` renvoie-t-il un `Result` ?\n" +" * Si le thread qui contenait le `Mutex` a paniqué, le `Mutex` devient \"empoisonné\" pour signaler que\n" +" les données qu'il protège peuvent être dans un état incohérent. Appel de `lock()` sur un mutex empoisonné\n" +" échoue avec une [`PoisonError`]. Vous pouvez appeler `into_inner()` sur l'erreur pour récupérer les données\n" +" indépendamment de." + +#: src/concurrency/shared_state/example.md:3 +#, fuzzy +msgid "Let us see `Arc` and `Mutex` in action:" +msgstr "Voyons `Arc` et `Mutex` en action :" + +#: 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 +#, fuzzy +msgid "Possible solution:" +msgstr "Solution possible:" + +#: 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 +#, fuzzy +msgid "Notable parts:" +msgstr "Parties notables :" + +#: 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` est enveloppé à la fois dans `Arc` et `Mutex`, car leurs préoccupations sont orthogonales.\n" +" * Envelopper un `Mutex` dans un `Arc` est un modèle courant pour partager un état mutable entre les threads.\n" +"* `v: Arc<_>` doit être cloné en tant que `v2` avant de pouvoir être déplacé dans un autre thread. Remarque \"move\" a été ajouté à la signature " +"lambda.\n" +"* Des blocs sont introduits pour réduire autant que possible la portée du \"LockGuard\"." + +#: src/concurrency/send-sync.md:1 +#, fuzzy +msgid "# `Send` and `Sync`" +msgstr "# `Envoyer` et `Synchroniser`" + +#: 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 "Comment Rust sait-il interdire l'accès partagé à travers le thread? La réponse est en deux traits :" + +#: 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] : un type `T` est `Send` s'il est sûr de déplacer un `T` à travers un thread\n" +" frontière.\n" +"* [`Sync`][2] : un type `T` est `Sync` s'il est sûr de déplacer un `&T` à travers un thread\n" +" frontière." + +#: 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 "" +"`Send` et `Sync` sont des [caractéristiques non sécurisées] [3]. Le compilateur les dérivera automatiquement pour vos types\n" +"tant qu'ils ne contiennent que les types `Send` et `Sync`. Vous pouvez également les implémenter manuellement lorsque vous\n" +"sachez qu'il est valide." + +#: 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 "" +"* On peut considérer ces traits comme des marqueurs indiquant que le type possède certaines propriétés de sécurité des threads.\n" +"* Ils peuvent être utilisés dans les contraintes génériques comme des traits normaux.\n" +" " + +#: src/concurrency/send-sync/send.md:1 +#, fuzzy +msgid "# `Send`" +msgstr "# `Envoyer`" + +#: 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 "> Un type `T` est [`Send`][1] s'il est sûr de déplacer une valeur `T` vers un autre thread." + +#: 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 "" +"L'effet du déplacement de la propriété vers un autre thread est que _destructors_ s'exécutera\n" +"dans ce fil. La question est donc de savoir quand vous pouvez allouer une valeur dans un thread\n" +"et le désallouer dans un autre." + +#: src/concurrency/send-sync/sync.md:1 +#, fuzzy +msgid "# `Sync`" +msgstr "# `Synchroniser`" + +#: 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 "" +"> Un type `T` est [`Sync`][1] s'il est sûr d'accéder à une valeur `T` à partir de plusieurs\n" +"> fils en même temps." + +#: src/concurrency/send-sync/sync.md:6 +#, fuzzy +msgid "More precisely, the definition is:" +msgstr "Plus précisément, la définition est :" + +#: src/concurrency/send-sync/sync.md:8 +#, fuzzy +msgid "> `T` is `Sync` if and only if `&T` is `Send`" +msgstr "> `T` est `Sync` si et seulement si `&T` est `Envoyer`" + +#: 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 "" +"Cette déclaration est essentiellement une manière abrégée de dire que si un type est thread-safe pour une utilisation partagée, il est également " +"thread-safe pour en passer des références à travers les threads." + +#: 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 "" +"En effet, si un type est Sync, cela signifie qu'il peut être partagé sur plusieurs threads sans risque de courses de données ou d'autres problèmes " +"de synchronisation, il est donc sûr de le déplacer vers un autre thread. Une référence au type peut également être déplacée en toute sécurité vers " +"un autre thread, car les données auxquelles elle fait référence sont accessibles à partir de n'importe quel thread en toute sécurité." + +#: src/concurrency/send-sync/examples.md:1 +#, fuzzy +msgid "# Examples" +msgstr "# Exemples" + +#: src/concurrency/send-sync/examples.md:3 +#, fuzzy +msgid "## `Send + Sync`" +msgstr "## `Envoyer + Synchroniser`" + +#: src/concurrency/send-sync/examples.md:5 +#, fuzzy +msgid "Most types you come across are `Send + Sync`:" +msgstr "La plupart des types que vous rencontrez sont `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 "" +"Les types génériques sont généralement \"Send + Sync\" lorsque les paramètres de type sont\n" +"`Envoyer + Synchroniser`." + +#: src/concurrency/send-sync/examples.md:17 +#, fuzzy +msgid "## `Send + !Sync`" +msgstr "## `Envoyer + !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 "" +"Ces types peuvent être déplacés vers d'autres threads, mais ils ne sont pas thread-safe.\n" +"Typiquement à cause de la mutabilité intérieure :" + +#: src/concurrency/send-sync/examples.md:22 +#, fuzzy +msgid "" +"* `mpsc::Sender`\n" +"* `mpsc::Receiver`\n" +"* `Cell`\n" +"* `RefCell`" +msgstr "" +"* `mpsc::Expéditeur`\n" +"* `mpsc::Récepteur`\n" +"* `Cellule`\n" +"* `RefCell`" + +#: src/concurrency/send-sync/examples.md:27 +#, fuzzy +msgid "## `!Send + Sync`" +msgstr "## ` !Envoyer + Synchroniser`" + +#: src/concurrency/send-sync/examples.md:29 +#, fuzzy +msgid "These types are thread-safe, but they cannot be moved to another thread:" +msgstr "Ces types sont thread-safe, mais ils ne peuvent pas être déplacés vers un autre thread :" + +#: 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` : utilise des primitives au niveau du système d'exploitation qui doivent être désallouées sur le\n" +" fil qui les a créés." + +#: src/concurrency/send-sync/examples.md:34 +#, fuzzy +msgid "## `!Send + !Sync`" +msgstr "## `!Envoyer + !Synchroniser`" + +#: src/concurrency/send-sync/examples.md:36 +#, fuzzy +msgid "These types are not thread-safe and cannot be moved to other threads:" +msgstr "Ces types ne sont pas thread-safe et ne peuvent pas être déplacés vers d'autres threads :" + +#: 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` : chaque `Rc` a une référence à un `RcBox`, qui contient un\n" +" comptage de référence non atomique.\n" +"* `*const T`, `*mut T` : Rust suppose que les pointeurs bruts peuvent avoir des\n" +" considérations de concurrence." + +#: 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 "# Des exercices" + +#: src/exercises/day-4/morning.md:3 +#, fuzzy +msgid "Let us practice our new concurrency skills with" +msgstr "Mettons en pratique nos nouvelles compétences en matière de concurrence avec" + +#: 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 "" +"* Dîner philosophes : un problème classique de la concurrence.\n" +"\n" +"* Vérificateur de liens multithread : un projet plus vaste dans lequel vous utiliserez Cargo pour\n" +" télécharger les dépendances puis vérifier les liens en parallèle." + +#: src/exercises/day-4/dining-philosophers.md:1 +#, fuzzy +msgid "# Dining Philosophers" +msgstr "# Philosophes de la restauration" + +#: src/exercises/day-4/dining-philosophers.md:3 +#, fuzzy +msgid "The dining philosophers problem is a classic problem in concurrency:" +msgstr "Le problème des philosophes de la restauration est un problème classique en concurrence :" + +#: 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 "" +"> Cinq philosophes dînent ensemble à la même table. Chaque philosophe a son\n" +"> propre place à table. Il y a une fourchette entre chaque assiette. Le plat servi est\n" +"> une sorte de spaghetti qui se mange avec deux fourchettes. Chaque philosophe peut\n" +"> seulement penser et manger alternativement. De plus, un philosophe ne peut que manger leur\n" +"> des spaghettis lorsqu'ils ont à la fois une fourchette gauche et droite. Ainsi deux fourches ne feront que\n" +"> être disponible lorsque ses deux voisins les plus proches pensent, ne mangent pas. Après\n" +"> un philosophe individuel finit de manger, ils poseront les deux fourchettes." + +#: 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 "" +"Vous aurez besoin d'une [installation Cargo](../../cargo/running-locally.md) locale pour\n" +"cet exercice. Copiez le code ci-dessous dans un fichier appelé `src/main.rs`, remplissez le\n" +"vides, et testez que `cargo run` ne se bloque pas :" + +#: src/exercises/day-4/dining-philosophers.md:17 src/exercises/day-4/link-checker.md:55 src/exercises/bare-metal/compass.md:28 +#: src/exercises/bare-metal/rtc.md:12 +#, fuzzy +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 +#, fuzzy +msgid "You can use the following `Cargo.toml`:" +msgstr "Vous pouvez utiliser le fichier `Cargo.toml` suivant :" + +#: src/exercises/day-4/dining-philosophers.md:63 src/exercises/day-4/link-checker.md:35 src/exercises/bare-metal/compass.md:66 +#: src/exercises/bare-metal/rtc.md:361 +#, fuzzy +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 "# Vérificateur de lien multithread" + +#: 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 "" +"Utilisons nos nouvelles connaissances pour créer un vérificateur de liens multi-thread. Cela devrait\n" +"commencez par une page Web et vérifiez que les liens sur la page sont valides. Cela devrait\n" +"vérifier récursivement d'autres pages sur le même domaine et continuer à le faire jusqu'à ce que tous\n" +"les pages ont été validées." + +#: 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 "" +"Pour cela, vous aurez besoin d'un client HTTP tel que [`reqwest`][1]. Créer un nouveau\n" +"Projet Cargo et `reqwest` comme dépendance avec :" + +#: 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 "" +"> Si `cargo add` échoue avec `error: no such subcommand`, veuillez modifier le\n" +"> Fichier `Cargo.toml` à la main. Ajoutez les dépendances répertoriées ci-dessous." + +#: 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 "Vous aurez également besoin d'un moyen de trouver des liens. Nous pouvons utiliser [`scraper`][2] pour cela :" + +#: 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 "" +"Enfin, nous aurons besoin d'un moyen de gérer les erreurs. Nous utilisons [`thiserror`][3] pour\n" +"ce:" + +#: 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 "Les appels `cargo add` mettront à jour le fichier `Cargo.toml` pour qu'il ressemble à ceci :" + +#: 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 "" +"Vous pouvez maintenant télécharger la page de démarrage. Essayez avec un petit site comme\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 "Votre fichier `src/main.rs` devrait ressembler à ceci :" + +#: 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 "Exécutez le code dans `src/main.rs` avec" + +#: 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 "## Tâches" + +#: 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 "" +"* Utilisez des threads pour vérifier les liens en parallèle : envoyez les URL à vérifier à un\n" +" channel et laissez quelques threads vérifier les URL en parallèle.\n" +"* Étendez ceci pour extraire de manière récursive les liens de toutes les pages du\n" +" domaine \"www.google.org\". Fixez une limite supérieure de 100 pages environ afin que vous\n" +" ne finissez pas par être bloqué par le site." + +#: src/android.md:1 src/bare-metal/android.md:1 +#, fuzzy +msgid "# Android" +msgstr "# Android" + +#: src/android.md:3 +#, fuzzy +msgid "" +"Rust is supported for native platform development on Android. This means that\n" +"you can write new operating system services in Rust, as well as extending\n" +"existing services." +msgstr "" +"Rust est pris en charge pour le développement de plates-formes natives sur Android. Cela signifie que\n" +"vous pouvez écrire de nouveaux services de système d'exploitation dans Rust, ainsi que l'extension\n" +"prestations existantes." + +#: src/android.md:7 +#, fuzzy +msgid "" +"> We will attempt to call Rust from one of your own projects today. So try to\n" +"> find a little corner of your code base where we can move some lines of code to\n" +"> Rust. The fewer dependencies and \"exotic\" types the better. Something that\n" +"> parses some raw bytes would be ideal." +msgstr "" +"> Nous allons essayer d'appeler Rust depuis l'un de vos propres projets aujourd'hui. Alors essayez de\n" +"> trouvez un petit coin de votre base de code où nous pouvons déplacer quelques lignes de code vers\n" +"> Rouille. Moins il y a de dépendances et de types \"exotiques\", mieux c'est. Quelque chose que\n" +"> analyser quelques octets bruts serait idéal." + +#: src/android/setup.md:1 +#, fuzzy +msgid "# Setup" +msgstr "# Installation" + +#: src/android/setup.md:3 +#, fuzzy +msgid "" +"We will be using an Android Virtual Device to test our code. Make sure you have\n" +"access to one or create a new one with:" +msgstr "" +"Nous utiliserons un appareil virtuel Android pour tester notre code. Assurez-vous que vous avez\n" +"accéder à un ou en créer un nouveau avec :" + +#: src/android/setup.md:6 +msgid "" +"```shell\n" +"$ source build/envsetup.sh\n" +"$ lunch aosp_cf_x86_64_phone-userdebug\n" +"$ acloud create\n" +"```" +msgstr "" + +#: src/android/setup.md:12 +#, fuzzy +msgid "" +"Please see the [Android Developer\n" +"Codelab](https://source.android.com/docs/setup/start) for details." +msgstr "" +"Veuillez consulter le [Développeur Android\n" +"Codelab] (https://source.android.com/docs/setup/start) pour plus de détails." + +#: src/android/build-rules.md:1 +#, fuzzy +msgid "# Build Rules" +msgstr "# Règles de construction" + +#: src/android/build-rules.md:3 +#, fuzzy +msgid "The Android build system (Soong) supports Rust via a number of modules:" +msgstr "Le système de construction Android (Soong) prend en charge Rust via un certain nombre de modules :" + +#: src/android/build-rules.md:5 +#, fuzzy +msgid "" +"| Module Type | Description |\n" +"|-------------------|----------------------------------------------------------------------------------------------------|\n" +"| `rust_binary` | Produces a Rust binary. |\n" +"| `rust_library` | Produces a Rust library, and provides both `rlib` and `dylib` variants. |\n" +"| `rust_ffi` | Produces a Rust C library usable by `cc` modules, and provides both static and shared variants. |\n" +"| `rust_proc_macro` | Produces a `proc-macro` Rust library. These are analogous to compiler plugins. |\n" +"| `rust_test` | Produces a Rust test binary that uses the standard Rust test harness. |\n" +"| `rust_fuzz` | Produces a Rust fuzz binary leveraging `libfuzzer`. |\n" +"| `rust_protobuf` | Generates source and produces a Rust library that provides an interface for a particular protobuf. |\n" +"| `rust_bindgen` | Generates source and produces a Rust library containing Rust bindings to C libraries. |" +msgstr "" +"| Type de module | Descriptif |\n" +"|------------------|-------------------------------------- -------------------------------------------------- ---------------------|\n" +"| `rust_binaire` | Produit un binaire Rust. |\n" +"| `rust_library` | Produit une bibliothèque Rust et fournit les variantes `rlib` et `dylib`. |\n" +"| `rust_ffi` | Produit une bibliothèque Rust C utilisable par les modules `cc` et fournit des variantes statiques et partagées. |\n" +"| `rust_proc_macro` | Produit une bibliothèque Rust `proc-macro`. Ceux-ci sont analogues aux plugins du compilateur. |\n" +"| `test_rouille` | Produit un binaire de test Rust qui utilise le harnais de test Rust standard. |\n" +"| `rust_fuzz` | Produit un exécutable Rust fuzz utilisant `libfuzzer`. |\n" +"| `rust_protobuf` | Génère la source et produit une bibliothèque Rust qui fournit une interface pour un protobuf particulier. |\n" +"| `rust_bindgen` | Génère la source et produit une bibliothèque Rust contenant des liaisons Rust aux bibliothèques C. |" + +#: src/android/build-rules.md:16 +#, fuzzy +msgid "We will look at `rust_binary` and `rust_library` next." +msgstr "Nous examinerons ensuite `rust_binary` et `rust_library`." + +#: src/android/build-rules/binary.md:1 +#, fuzzy +msgid "# Rust Binaries" +msgstr "# Binaires de rouille" + +#: src/android/build-rules/binary.md:3 +#, fuzzy +msgid "" +"Let us start with a simple application. At the root of an AOSP checkout, create\n" +"the following files:" +msgstr "" +"Commençons par une application simple. A la racine d'une caisse AOSP, créez\n" +"les fichiers suivants :" + +#: src/android/build-rules/binary.md:6 src/android/build-rules/library.md:13 +#, fuzzy +msgid "_hello_rust/Android.bp_:" +msgstr "_hello_rust/Android.bp_ :" + +#: src/android/build-rules/binary.md:8 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust\",\n" +" crate_name: \"hello_rust\",\n" +" srcs: [\"src/main.rs\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md:16 src/android/build-rules/library.md:34 +#, fuzzy +msgid "_hello_rust/src/main.rs_:" +msgstr "_hello_rust/src/main.rs_ :" + +#: src/android/build-rules/binary.md:18 +msgid "" +"```rust\n" +"//! Rust demo.\n" +"\n" +"/// Prints a greeting to standard output.\n" +"fn main() {\n" +" println!(\"Hello from Rust!\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md:27 +#, fuzzy +msgid "You can now build, push, and run the binary:" +msgstr "Vous pouvez maintenant compiler, envoyer et exécuter le binaire :" + +#: src/android/build-rules/binary.md:29 +msgid "" +"```shell\n" +"$ m hello_rust\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust\n" +"Hello from Rust!\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:1 +#, fuzzy +msgid "# Rust Libraries" +msgstr "# Bibliothèques de rouille" + +#: src/android/build-rules/library.md:3 +#, fuzzy +msgid "You use `rust_library` to create a new Rust library for Android." +msgstr "Vous utilisez `rust_library` pour créer une nouvelle bibliothèque Rust pour Android." + +#: src/android/build-rules/library.md:5 +#, fuzzy +msgid "Here we declare a dependency on two libraries:" +msgstr "Ici, nous déclarons une dépendance sur deux bibliothèques :" + +#: src/android/build-rules/library.md:7 +#, fuzzy +msgid "" +"* `libgreeting`, which we define below,\n" +"* `libtextwrap`, which is a crate already vendored in\n" +" [`external/rust/crates/`][crates]." +msgstr "" +"* `libgreeting`, que nous définissons ci-dessous,\n" +"* `libtextwrap`, qui est une caisse déjà vendue dans\n" +" [`externe/rouille/caisses/`][caisses]." + +#: src/android/build-rules/library.md:15 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_with_dep\",\n" +" crate_name: \"hello_rust_with_dep\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libgreetings\",\n" +" \"libtextwrap\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"\n" +"rust_library {\n" +" name: \"libgreetings\",\n" +" crate_name: \"greetings\",\n" +" srcs: [\"src/lib.rs\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:36 +msgid "" +"```rust,ignore\n" +"//! Rust demo.\n" +"\n" +"use greetings::greeting;\n" +"use textwrap::fill;\n" +"\n" +"/// Prints a greeting to standard output.\n" +"fn main() {\n" +" println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:48 +#, fuzzy +msgid "_hello_rust/src/lib.rs_:" +msgstr "_hello_rust/src/lib.rs_ :" + +#: src/android/build-rules/library.md:50 +msgid "" +"```rust,ignore\n" +"//! Greeting library.\n" +"\n" +"/// Greet `name`.\n" +"pub fn greeting(name: &str) -> String {\n" +" format!(\"Hello {name}, it is very nice to meet you!\")\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:59 +#, fuzzy +msgid "You build, push, and run the binary like before:" +msgstr "Vous construisez, poussez et exécutez le binaire comme avant :" + +#: src/android/build-rules/library.md:61 +msgid "" +"```shell\n" +"$ m hello_rust_with_dep\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust_with_dep\n" +"Hello Bob, it is very\n" +"nice to meet you!\n" +"```" +msgstr "" + +#: src/android/aidl.md:1 +#, fuzzy +msgid "# AIDL" +msgstr "#AIDL" + +#: src/android/aidl.md:3 +#, fuzzy +msgid "" +"The [Android Interface Definition Language\n" +"(AIDL)](https://developer.android.com/guide/components/aidl) is supported in Rust:" +msgstr "" +"Le [langage de définition d'interface Android\n" +"(AIDL)](https://developer.android.com/guide/components/aidl) est pris en charge dans Rust :" + +#: src/android/aidl.md:6 +#, fuzzy +msgid "" +"* Rust code can call existing AIDL servers,\n" +"* You can create new AIDL servers in Rust." +msgstr "" +"* Le code Rust peut appeler des serveurs AIDL existants,\n" +"* Vous pouvez créer de nouveaux serveurs AIDL dans Rust." + +#: src/android/aidl/interface.md:1 +#, fuzzy +msgid "# AIDL Interfaces" +msgstr "# Interfaces AIDL" + +#: src/android/aidl/interface.md:3 +#, fuzzy +msgid "You declare the API of your service using an AIDL interface:" +msgstr "Vous déclarez l'API de votre service à l'aide d'une interface AIDL :" + +#: src/android/aidl/interface.md:5 +#, fuzzy +msgid "*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" +msgstr "*service_anniversaire/aidl/com/exemple/serviceanniversaire/IBirthdayService.aidl* :" + +#: src/android/aidl/interface.md:7 +msgid "" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years);\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/interface.md:17 +#, fuzzy +msgid "*birthday_service/aidl/Android.bp*:" +msgstr "*service_anniversaire/aidl/Android.bp* :" + +#: src/android/aidl/interface.md:19 +msgid "" +"```javascript\n" +"aidl_interface {\n" +" name: \"com.example.birthdayservice\",\n" +" srcs: [\"com/example/birthdayservice/*.aidl\"],\n" +" unstable: true,\n" +" backend: {\n" +" rust: { // Rust is not enabled by default\n" +" enabled: true,\n" +" },\n" +" },\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/interface.md:32 +#, fuzzy +msgid "" +"Add `vendor_available: true` if your AIDL file is used by a binary in the vendor\n" +"partition." +msgstr "" +"Ajoutez `vendor_available : true` si votre fichier AIDL est utilisé par un binaire dans le fournisseur\n" +"cloison." + +#: src/android/aidl/implementation.md:1 +#, fuzzy +msgid "# Service Implementation" +msgstr "# Mise en œuvre des services" + +#: src/android/aidl/implementation.md:3 +#, fuzzy +msgid "We can now implement the AIDL service:" +msgstr "Nous pouvons maintenant implémenter le service AIDL :" + +#: src/android/aidl/implementation.md:5 +#, fuzzy +msgid "*birthday_service/src/lib.rs*:" +msgstr "*service_anniversaire/src/lib.rs* :" + +#: src/android/aidl/implementation.md:7 +msgid "" +"```rust,ignore\n" +"//! Implementation of the `IBirthdayService` AIDL interface.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"/// The `IBirthdayService` implementation.\n" +"pub struct BirthdayService;\n" +"\n" +"impl binder::Interface for BirthdayService {}\n" +"\n" +"impl IBirthdayService for BirthdayService {\n" +" fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result {\n" +" Ok(format!(\n" +" \"Happy Birthday {name}, congratulations with the {years} years!\"\n" +" ))\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/implementation.md:26 src/android/aidl/server.md:28 src/android/aidl/client.md:37 +#, fuzzy +msgid "*birthday_service/Android.bp*:" +msgstr "*service_anniversaire/Android.bp* :" + +#: src/android/aidl/implementation.md:28 +msgid "" +"```javascript\n" +"rust_library {\n" +" name: \"libbirthdayservice\",\n" +" srcs: [\"src/lib.rs\"],\n" +" crate_name: \"birthdayservice\",\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/server.md:1 +#, fuzzy +msgid "# AIDL Server" +msgstr "# Serveur AIDL" + +#: src/android/aidl/server.md:3 +#, fuzzy +msgid "Finally, we can create a server which exposes the service:" +msgstr "Enfin, nous pouvons créer un serveur qui expose le service :" + +#: src/android/aidl/server.md:5 +#, fuzzy +msgid "*birthday_service/src/server.rs*:" +msgstr "*service_anniversaire/src/server.rs* :" + +#: src/android/aidl/server.md:7 +msgid "" +"```rust,ignore\n" +"//! Birthday service.\n" +"use birthdayservice::BirthdayService;\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::BnBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" +"/// Entry point for birthday service.\n" +"fn main() {\n" +" let birthday_service = BirthdayService;\n" +" let birthday_service_binder = BnBirthdayService::new_binder(\n" +" birthday_service,\n" +" binder::BinderFeatures::default(),\n" +" );\n" +" binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder.as_binder())\n" +" .expect(\"Failed to register service\");\n" +" binder::ProcessState::join_thread_pool()\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/server.md:30 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_server\",\n" +" crate_name: \"birthday_server\",\n" +" srcs: [\"src/server.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" \"libbirthdayservice\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:1 +#, fuzzy +msgid "# Deploy" +msgstr "# Déployer" + +#: src/android/aidl/deploy.md:3 +#, fuzzy +msgid "We can now build, push, and start the service:" +msgstr "Nous pouvons maintenant créer, pousser et démarrer le service :" + +#: src/android/aidl/deploy.md:5 +msgid "" +"```shell\n" +"$ m birthday_server\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_server\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:11 +#, fuzzy +msgid "In another terminal, check that the service runs:" +msgstr "Dans un autre terminal, vérifiez que le service s'exécute :" + +#: src/android/aidl/deploy.md:13 +msgid "" +"```shell\n" +"$ adb shell service check birthdayservice\n" +"Service birthdayservice: found\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:18 +#, fuzzy +msgid "You can also call the service with `service call`:" +msgstr "Vous pouvez également appeler le service avec `service call` :" + +#: src/android/aidl/deploy.md:20 +msgid "" +"```shell\n" +"$ $ adb shell service call birthdayservice 1 s16 Bob i32 24\n" +"Result: Parcel(\n" +" 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" +" 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" +" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'\n" +" 0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'\n" +" 0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'\n" +" 0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'\n" +" 0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'\n" +" 0x00000070: 00210073 00000000 's.!..... ')\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:1 +#, fuzzy +msgid "# AIDL Client" +msgstr "# Client AIDL" + +#: src/android/aidl/client.md:3 +#, fuzzy +msgid "Finally, we can create a Rust client for our new service." +msgstr "Enfin, nous pouvons créer un client Rust pour notre nouveau service." + +#: src/android/aidl/client.md:5 +#, fuzzy +msgid "*birthday_service/src/client.rs*:" +msgstr "*service_anniversaire/src/client.rs* :" + +#: src/android/aidl/client.md:7 +msgid "" +"```rust,ignore\n" +"//! Birthday service.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" +"/// Connect to the BirthdayService.\n" +"pub fn connect() -> Result, binder::StatusCode> {\n" +" binder::get_interface(SERVICE_IDENTIFIER)\n" +"}\n" +"\n" +"/// Call the birthday service.\n" +"fn main() -> Result<(), binder::Status> {\n" +" let name = std::env::args()\n" +" .nth(1)\n" +" .unwrap_or_else(|| String::from(\"Bob\"));\n" +" let years = std::env::args()\n" +" .nth(2)\n" +" .and_then(|arg| arg.parse::().ok())\n" +" .unwrap_or(42);\n" +"\n" +" binder::ProcessState::start_thread_pool();\n" +" let service = connect().expect(\"Failed to connect to BirthdayService\");\n" +" let msg = service.wishHappyBirthday(&name, years)?;\n" +" println!(\"{msg}\");\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:39 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_client\",\n" +" crate_name: \"birthday_client\",\n" +" srcs: [\"src/client.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:52 +#, fuzzy +msgid "Notice that the client does not depend on `libbirthdayservice`." +msgstr "Notez que le client ne dépend pas de `libbirthdayservice`." + +#: src/android/aidl/client.md:54 +#, fuzzy +msgid "Build, push, and run the client on your device:" +msgstr "Créez, transférez et exécutez le client sur votre appareil :" + +#: src/android/aidl/client.md:56 +msgid "" +"```shell\n" +"$ m birthday_client\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_client Charlie 60\n" +"Happy Birthday Charlie, congratulations with the 60 years!\n" +"```" +msgstr "" + +#: src/android/aidl/changing.md:1 +#, fuzzy +msgid "# Changing API" +msgstr "# Modification de l'API" + +#: src/android/aidl/changing.md:3 +#, fuzzy +msgid "" +"Let us extend the API with more functionality: we want to let clients specify a\n" +"list of lines for the birthday card:" +msgstr "" +"Étendons l'API avec plus de fonctionnalités : nous voulons laisser les clients spécifier un\n" +"liste des lignes pour la carte d'anniversaire :" + +#: src/android/aidl/changing.md:6 +msgid "" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years, in String[] text);\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:1 src/bare-metal/aps/logging.md:1 +#, fuzzy +msgid "# Logging" +msgstr "# Journalisation" + +#: src/android/logging.md:3 +#, fuzzy +msgid "" +"You should use the `log` crate to automatically log to `logcat` (on-device) or\n" +"`stdout` (on-host):" +msgstr "" +"Vous devez utiliser la caisse `log` pour vous connecter automatiquement à `logcat` (sur l'appareil) ou\n" +"`stdout` (sur l'hôte) :" + +#: src/android/logging.md:6 +#, fuzzy +msgid "_hello_rust_logs/Android.bp_:" +msgstr "_hello_rust_logs/Android.bp_ :" + +#: src/android/logging.md:8 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_logs\",\n" +" crate_name: \"hello_rust_logs\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"liblog_rust\",\n" +" \"liblogger\",\n" +" ],\n" +" prefer_rlib: true,\n" +" host_supported: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:22 +#, fuzzy +msgid "_hello_rust_logs/src/main.rs_:" +msgstr "_hello_rust_logs/src/main.rs_ :" + +#: src/android/logging.md:24 +msgid "" +"```rust,ignore\n" +"//! Rust logging demo.\n" +"\n" +"use log::{debug, error, info};\n" +"\n" +"/// Logs a greeting.\n" +"fn main() {\n" +" logger::init(\n" +" logger::Config::default()\n" +" .with_tag_on_device(\"rust\")\n" +" .with_min_level(log::Level::Trace),\n" +" );\n" +" debug!(\"Starting program.\");\n" +" info!(\"Things are going fine.\");\n" +" error!(\"Something went wrong!\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:42 src/android/interoperability/with-c/bindgen.md:98 src/android/interoperability/with-c/rust.md:73 +#, fuzzy +msgid "Build, push, and run the binary on your device:" +msgstr "Compilez, transférez et exécutez le binaire sur votre appareil :" + +#: src/android/logging.md:44 +msgid "" +"```shell\n" +"$ m hello_rust_logs\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust_logs\n" +"```" +msgstr "" + +#: src/android/logging.md:50 +#, fuzzy +msgid "The logs show up in `adb logcat`:" +msgstr "Les journaux s'affichent dans `adb logcat` :" + +#: src/android/logging.md:52 +msgid "" +"```shell\n" +"$ adb logcat -s rust\n" +"09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.\n" +"09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going fine.\n" +"09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went wrong!\n" +"```" +msgstr "" + +#: src/android/interoperability.md:1 +#, fuzzy +msgid "# Interoperability" +msgstr "# Interopérabilité" + +#: src/android/interoperability.md:3 +#, fuzzy +msgid "" +"Rust has excellent support for interoperability with other languages. This means\n" +"that you can:" +msgstr "" +"Rust a un excellent support pour l'interopérabilité avec d'autres langages. Ça signifie\n" +"Que tu peux:" + +#: src/android/interoperability.md:6 +#, fuzzy +msgid "" +"* Call Rust functions from other languages.\n" +"* Call functions written in other languages from Rust." +msgstr "" +"* Appelez les fonctions Rust à partir d'autres langues.\n" +"* Fonctions d'appel écrites dans d'autres langages depuis Rust." + +#: src/android/interoperability.md:9 +#, fuzzy +msgid "" +"When you call functions in a foreign language we say that you're using a\n" +"_foreign function interface_, also known as FFI." +msgstr "" +"Lorsque vous appelez des fonctions dans une langue étrangère, nous disons que vous utilisez un\n" +"_interface de fonction étrangère_, également connue sous le nom de FFI." + +#: src/android/interoperability/with-c.md:1 +#, fuzzy +msgid "# Interoperability with C" +msgstr "# Interopérabilité avec C" + +#: src/android/interoperability/with-c.md:3 +#, fuzzy +msgid "" +"Rust has full support for linking object files with a C calling convention.\n" +"Similarly, you can export Rust functions and call them from C." +msgstr "" +"Rust prend entièrement en charge la liaison de fichiers objets avec une convention d'appel C.\n" +"De même, vous pouvez exporter des fonctions Rust et les appeler depuis C." + +#: src/android/interoperability/with-c.md:6 +#, fuzzy +msgid "You can do it by hand if you want:" +msgstr "Vous pouvez le faire à la main si vous le souhaitez :" + +#: src/android/interoperability/with-c.md:8 +msgid "" +"```rust\n" +"extern \"C\" {\n" +" fn abs(x: i32) -> i32;\n" +"}\n" +"\n" +"fn main() {\n" +" let x = -42;\n" +" let abs_x = unsafe { abs(x) };\n" +" println!(\"{x}, {abs_x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c.md:20 +#, fuzzy +msgid "" +"We already saw this in the [Safe FFI Wrapper\n" +"exercise](../../exercises/day-3/safe-ffi-wrapper.md)." +msgstr "" +"Nous avons déjà vu cela dans le [Safe FFI Wrapper\n" +"exercice](../../exercises/day-3/safe-ffi-wrapper.md)." + +#: src/android/interoperability/with-c.md:23 +#, fuzzy +msgid "" +"> This assumes full knowledge of the target platform. Not recommended for\n" +"> production." +msgstr "" +"> Cela suppose une parfaite connaissance de la plateforme cible. Non recommandé pour\n" +"> fabrication." + +#: src/android/interoperability/with-c.md:26 +#, fuzzy +msgid "We will look at better options next." +msgstr "Nous examinerons ensuite de meilleures options." + +#: src/android/interoperability/with-c/bindgen.md:1 +#, fuzzy +msgid "# Using Bindgen" +msgstr "# Utiliser Bindgen" + +#: src/android/interoperability/with-c/bindgen.md:3 +#, fuzzy +msgid "" +"The [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html) tool\n" +"can auto-generate bindings from a C header file." +msgstr "" +"L'outil [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html)\n" +"peut générer automatiquement des liaisons à partir d'un fichier d'en-tête C." + +#: src/android/interoperability/with-c/bindgen.md:6 +#, fuzzy +msgid "First create a small C library:" +msgstr "Créez d'abord une petite bibliothèque C :" + +#: src/android/interoperability/with-c/bindgen.md:8 +#, fuzzy +msgid "_interoperability/bindgen/libbirthday.h_:" +msgstr "_interoperability/bindgen/libbirthday.h_ :" + +#: src/android/interoperability/with-c/bindgen.md:10 +msgid "" +"```c\n" +"typedef struct card {\n" +" const char* name;\n" +" int years;\n" +"} card;\n" +"\n" +"void print_card(const card* card);\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:19 +#, fuzzy +msgid "_interoperability/bindgen/libbirthday.c_:" +msgstr "_interoperability/bindgen/libbirthday.c_ :" + +#: src/android/interoperability/with-c/bindgen.md:21 +msgid "" +"```c\n" +"#include \n" +"#include \"libbirthday.h\"\n" +"\n" +"void print_card(const card* card) {\n" +" printf(\"+--------------\\n\");\n" +" printf(\"| Happy Birthday %s!\\n\", card->name);\n" +" printf(\"| Congratulations with the %i years!\\n\", card->years);\n" +" printf(\"+--------------\\n\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:33 +#, fuzzy +msgid "Add this to your `Android.bp` file:" +msgstr "Ajoutez ceci à votre fichier `Android.bp` :" + +#: src/android/interoperability/with-c/bindgen.md:35 src/android/interoperability/with-c/bindgen.md:55 +#: src/android/interoperability/with-c/bindgen.md:69 src/android/interoperability/with-c/bindgen.md:108 +#, fuzzy +msgid "_interoperability/bindgen/Android.bp_:" +msgstr "_interopérabilité/bindgen/Android.bp_ :" + +#: src/android/interoperability/with-c/bindgen.md:37 +msgid "" +"```javascript\n" +"cc_library {\n" +" name: \"libbirthday\",\n" +" srcs: [\"libbirthday.c\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:44 +#, fuzzy +msgid "" +"Create a wrapper header file for the library (not strictly needed in this\n" +"example):" +msgstr "" +"Créez un fichier d'en-tête wrapper pour la bibliothèque (pas strictement nécessaire dans ce\n" +"exemple):" + +#: src/android/interoperability/with-c/bindgen.md:47 +#, fuzzy +msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" +msgstr "_interoperability/bindgen/libbirthday_wrapper.h_ :" + +#: src/android/interoperability/with-c/bindgen.md:49 +msgid "" +"```c\n" +"#include \"libbirthday.h\"\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:53 +#, fuzzy +msgid "You can now auto-generate the bindings:" +msgstr "Vous pouvez maintenant générer automatiquement les liaisons :" + +#: src/android/interoperability/with-c/bindgen.md:57 +msgid "" +"```javascript\n" +"rust_bindgen {\n" +" name: \"libbirthday_bindgen\",\n" +" crate_name: \"birthday_bindgen\",\n" +" wrapper_src: \"libbirthday_wrapper.h\",\n" +" source_stem: \"bindings\",\n" +" static_libs: [\"libbirthday\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:67 +#, fuzzy +msgid "Finally, we can use the bindings in our Rust program:" +msgstr "Enfin, nous pouvons utiliser les liaisons dans notre programme Rust :" + +#: src/android/interoperability/with-c/bindgen.md:71 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"print_birthday_card\",\n" +" srcs: [\"main.rs\"],\n" +" rustlibs: [\"libbirthday_bindgen\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:79 +#, fuzzy +msgid "_interoperability/bindgen/main.rs_:" +msgstr "_interopérabilité/bindgen/main.rs_ :" + +#: src/android/interoperability/with-c/bindgen.md:81 +msgid "" +"```rust,compile_fail\n" +"//! Bindgen demo.\n" +"\n" +"use birthday_bindgen::{card, print_card};\n" +"\n" +"fn main() {\n" +" let name = std::ffi::CString::new(\"Peter\").unwrap();\n" +" let card = card {\n" +" name: name.as_ptr(),\n" +" years: 42,\n" +" };\n" +" unsafe {\n" +" print_card(&card as *const card);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:100 +msgid "" +"```shell\n" +"$ m print_birthday_card\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/tmp\n" +"$ adb shell /data/local/tmp/print_birthday_card\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:106 +#, fuzzy +msgid "Finally, we can run auto-generated tests to ensure the bindings work:" +msgstr "Enfin, nous pouvons exécuter des tests générés automatiquement pour nous assurer que les liaisons fonctionnent :" + +#: src/android/interoperability/with-c/bindgen.md:110 +msgid "" +"```javascript\n" +"rust_test {\n" +" name: \"libbirthday_bindgen_test\",\n" +" srcs: [\":libbirthday_bindgen\"],\n" +" crate_name: \"libbirthday_bindgen_test\",\n" +" test_suites: [\"general-tests\"],\n" +" auto_gen_config: true,\n" +" clippy_lints: \"none\", // Generated file, skip linting\n" +" lints: \"none\",\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:122 +msgid "" +"```shell\n" +"$ atest libbirthday_bindgen_test\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:1 +#, fuzzy +msgid "# Calling Rust" +msgstr "# Appeler Rust" + +#: src/android/interoperability/with-c/rust.md:3 +#, fuzzy +msgid "Exporting Rust functions and types to C is easy:" +msgstr "Exporter des fonctions et des types Rust vers C est simple :" + +#: src/android/interoperability/with-c/rust.md:5 +#, fuzzy +msgid "_interoperability/rust/libanalyze/analyze.rs_" +msgstr "_interopérabilité/rust/libanalyze/analyze.rs_" + +#: src/android/interoperability/with-c/rust.md:7 +msgid "" +"```rust,editable\n" +"//! Rust FFI demo.\n" +"#![deny(improper_ctypes_definitions)]\n" +"\n" +"use std::os::raw::c_int;\n" +"\n" +"/// Analyze the numbers.\n" +"#[no_mangle]\n" +"pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" +" if x < y {\n" +" println!(\"x ({x}) is smallest!\");\n" +" } else {\n" +" println!(\"y ({y}) is probably larger than x ({x})\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:24 +#, fuzzy +msgid "_interoperability/rust/libanalyze/analyze.h_" +msgstr "_interopérabilité/rust/libanalyze/analyze.h_" + +#: src/android/interoperability/with-c/rust.md:26 +msgid "" +"```c\n" +"#ifndef ANALYSE_H\n" +"#define ANALYSE_H\n" +"\n" +"extern \"C\" {\n" +"void analyze_numbers(int x, int y);\n" +"}\n" +"\n" +"#endif\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:37 +#, fuzzy +msgid "_interoperability/rust/libanalyze/Android.bp_" +msgstr "_interopérabilité/rust/libanalyze/Android.bp_" + +#: src/android/interoperability/with-c/rust.md:39 +msgid "" +"```javascript\n" +"rust_ffi {\n" +" name: \"libanalyze_ffi\",\n" +" crate_name: \"analyze_ffi\",\n" +" srcs: [\"analyze.rs\"],\n" +" include_dirs: [\".\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:48 +#, fuzzy +msgid "We can now call this from a C binary:" +msgstr "Nous pouvons maintenant appeler cela à partir d'un binaire C :" + +#: src/android/interoperability/with-c/rust.md:50 +#, fuzzy +msgid "_interoperability/rust/analyze/main.c_" +msgstr "_interoperability/rust/analyze/main.c_" + +#: src/android/interoperability/with-c/rust.md:52 +msgid "" +"```c\n" +"#include \"analyze.h\"\n" +"\n" +"int main() {\n" +" analyze_numbers(10, 20);\n" +" analyze_numbers(123, 123);\n" +" return 0;\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:62 +#, fuzzy +msgid "_interoperability/rust/analyze/Android.bp_" +msgstr "_interopérabilité/rouille/analyse/Android.bp_" + +#: src/android/interoperability/with-c/rust.md:64 +msgid "" +"```javascript\n" +"cc_binary {\n" +" name: \"analyze_numbers\",\n" +" srcs: [\"main.c\"],\n" +" static_libs: [\"libanalyze_ffi\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:75 +msgid "" +"```shell\n" +"$ m analyze_numbers\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp\n" +"$ adb shell /data/local/tmp/analyze_numbers\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:83 +#, fuzzy +msgid "" +"`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol will just be the name of\n" +"the function. You can also use `#[export_name = \"some_name\"]` to specify whatever name you want." +msgstr "" +"`#[no_mangle]` désactive la modification du nom habituel de Rust, de sorte que le symbole exporté sera simplement le nom de\n" +"la fonction. Vous pouvez également utiliser `#[export_name = \"some_name\"]` pour spécifier le nom que vous voulez." + +#: src/android/interoperability/cpp.md:1 +#, fuzzy +msgid "# With C++" +msgstr "# Avec C++" + +#: src/android/interoperability/cpp.md:3 +#, fuzzy +msgid "" +"The [CXX crate][1] makes it possible to do safe interoperability between Rust\n" +"and C++." +msgstr "" +"La [caisse CXX][1] permet de faire une interopérabilité sûre entre Rust\n" +"et C++." + +#: src/android/interoperability/cpp.md:6 +#, fuzzy +msgid "The overall approach looks like this:" +msgstr "L'approche globale ressemble à ceci:" + +#: src/android/interoperability/cpp.md:8 +#, fuzzy +msgid "" +msgstr "" + +#: src/android/interoperability/cpp.md:10 +#, fuzzy +msgid "See the [CXX tutorial][2] for an full example of using this." +msgstr "Voir le [tutoriel CXX] [2] pour un exemple complet d'utilisation." + +#: src/android/interoperability/java.md:1 +#, fuzzy +msgid "# Interoperability with Java" +msgstr "# Interopérabilité avec Java" + +#: src/android/interoperability/java.md:3 +#, fuzzy +msgid "" +"Java can load shared objects via [Java Native Interface\n" +"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). The [`jni`\n" +"crate](https://docs.rs/jni/) allows you to create a compatible library." +msgstr "" +"Java peut charger des objets partagés via [Java Native Interface\n" +"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). Le [`jni`\n" +"crate](https://docs.rs/jni/) vous permet de créer une bibliothèque compatible." + +#: src/android/interoperability/java.md:7 +#, fuzzy +msgid "First, we create a Rust function to export to Java:" +msgstr "Tout d'abord, nous créons une fonction Rust à exporter vers Java :" + +#: src/android/interoperability/java.md:9 +#, fuzzy +msgid "_interoperability/java/src/lib.rs_:" +msgstr "_interopérabilité/java/src/lib.rs_ :" + +#: src/android/interoperability/java.md:11 +msgid "" +"```rust,compile_fail\n" +"//! Rust <-> Java FFI demo.\n" +"\n" +"use jni::objects::{JClass, JString};\n" +"use jni::sys::jstring;\n" +"use jni::JNIEnv;\n" +"\n" +"/// HelloWorld::hello method implementation.\n" +"#[no_mangle]\n" +"pub extern \"system\" fn Java_HelloWorld_hello(\n" +" env: JNIEnv,\n" +" _class: JClass,\n" +" name: JString,\n" +") -> jstring {\n" +" let input: String = env.get_string(name).unwrap().into();\n" +" let greeting = format!(\"Hello, {input}!\");\n" +" let output = env.new_string(greeting).unwrap();\n" +" output.into_inner()\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:32 src/android/interoperability/java.md:62 +#, fuzzy +msgid "_interoperability/java/Android.bp_:" +msgstr "_interopérabilité/java/Android.bp_ :" + +#: src/android/interoperability/java.md:34 +msgid "" +"```javascript\n" +"rust_ffi_shared {\n" +" name: \"libhello_jni\",\n" +" crate_name: \"hello_jni\",\n" +" srcs: [\"src/lib.rs\"],\n" +" rustlibs: [\"libjni\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:43 +#, fuzzy +msgid "Finally, we can call this function from Java:" +msgstr "Enfin, nous pouvons appeler cette fonction depuis Java :" + +#: src/android/interoperability/java.md:45 +#, fuzzy +msgid "_interoperability/java/HelloWorld.java_:" +msgstr "_interopérabilité/java/HelloWorld.java_ :" + +#: src/android/interoperability/java.md:47 +msgid "" +"```java\n" +"class HelloWorld {\n" +" private static native String hello(String name);\n" +"\n" +" static {\n" +" System.loadLibrary(\"hello_jni\");\n" +" }\n" +"\n" +" public static void main(String[] args) {\n" +" String output = HelloWorld.hello(\"Alice\");\n" +" System.out.println(output);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:64 +msgid "" +"```javascript\n" +"java_binary {\n" +" name: \"helloworld_jni\",\n" +" srcs: [\"HelloWorld.java\"],\n" +" main_class: \"HelloWorld\",\n" +" required: [\"libhello_jni\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:73 +#, fuzzy +msgid "Finally, you can build, sync, and run the binary:" +msgstr "Enfin, vous pouvez créer, synchroniser et exécuter le binaire :" + +#: src/android/interoperability/java.md:75 +msgid "" +"```shell\n" +"$ m helloworld_jni\n" +"$ adb sync # requires adb root && adb remount\n" +"$ adb shell /system/bin/helloworld_jni\n" +"```" +msgstr "" + +#: src/exercises/day-4/android.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:" +msgstr "" +"Pour le dernier exercice, nous examinerons l'un des projets sur lesquels vous travaillez. Laissez-nous\n" +"regroupez-vous et faites-le ensemble. Quelques suggestions:" + +#: src/exercises/day-4/android.md:6 +#, fuzzy +msgid "" +"* Call your AIDL service with a client written in Rust.\n" +"\n" +"* Move a function from your project to Rust and call it." +msgstr "" +"* Appelez votre service AIDL avec un client écrit en Rust.\n" +"\n" +"* Déplacez une fonction de votre projet vers Rust et appelez-la." + +#: src/exercises/day-4/android.md:12 +#, fuzzy +msgid "" +"No solution is provided here since this is open-ended: it relies on someone in\n" +"the class having a piece of code which you can turn in to Rust on the fly." +msgstr "" +"Aucune solution n'est proposée ici car celle-ci est ouverte : elle repose sur quelqu'un en\n" +"la classe ayant un morceau de code que vous pouvez remettre à Rust à la volée." + +#: src/thanks.md:1 +#, fuzzy +msgid "# Thanks!" +msgstr "# Merci!" + +#: src/thanks.md:3 +msgid "" +"_Thank you for taking Comprehensive Rust 🦀!_ We hope you enjoyed it and that it\n" +"was useful." +msgstr "" +"_Merci d'avoir pris Comprehensive Rust(le guide complet de Rust) 🦀!_ Nous espérons que vous l'avez apprécié et qu'il\n" +"était utile." + +#: 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 "" +"Nous nous sommes beaucoup amusés à préparer le cours. Le cours n'est pas parfait,\n" +"donc si vous avez repéré des erreurs ou avez des idées d'améliorations, n'hésitez pas à nous contacter\n" +"[contactez-nous au\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Nous aimerions\n" +"d'avoir de tes nouvelles." + +#: src/other-resources.md:1 +#, fuzzy +msgid "# Other Rust Resources" +msgstr "# Autres ressources de rouille" + +#: src/other-resources.md:3 +#, fuzzy +msgid "" +"The Rust community has created a wealth of high-quality and free resources\n" +"online." +msgstr "" +"La communauté Rust a créé une multitude de ressources gratuites et de haute qualité\n" +"en ligne." + +#: src/other-resources.md:6 +#, fuzzy +msgid "## Official Documentation" +msgstr "## Documents officiels" + +#: src/other-resources.md:8 +#, fuzzy +msgid "The Rust project hosts many resources. These cover Rust in general:" +msgstr "Le projet Rust héberge de nombreuses ressources. Celles-ci couvrent Rust en général :" + +#: 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 "" +"* [Le langage de programmation Rust](https://doc.rust-lang.org/book/) : le\n" +" livre canonique gratuit sur Rust. Couvre la langue en détail et comprend un\n" +" peu de projets à construire.\n" +"* [Rust By Example](https://doc.rust-lang.org/rust-by-example/) : couvre la rouille\n" +" syntaxe via une série d'exemples qui présentent différentes constructions. Parfois\n" +" comprend de petits exercices où l'on vous demande de développer le code dans le\n" +" exemples.\n" +"* [Bibliothèque standard Rust](https://doc.rust-lang.org/std/) : documentation complète de\n" +" la bibliothèque standard de Rust.\n" +"* [The Rust Reference](https://doc.rust-lang.org/reference/) : un livre incomplet\n" +" qui décrit la grammaire et le modèle de mémoire de Rust." + +#: src/other-resources.md:22 +#, fuzzy +msgid "More specialized guides hosted on the official Rust site:" +msgstr "Des guides plus spécialisés hébergés sur le site officiel de Rust :" + +#: 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/) : couvre la rouille dangereuse,\n" +" y compris le travail avec des pointeurs bruts et l'interfaçage avec d'autres langages\n" +" (FFI).\n" +"* [Programmation asynchrone dans Rust](https://rust-lang.github.io/async-book/) :\n" +" couvre le nouveau modèle de programmation asynchrone qui a été introduit après la\n" +" Rust Book a été écrit.\n" +"* [The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/) : un\n" +" introduction à l'utilisation de Rust sur des appareils embarqués sans système d'exploitation." + +#: src/other-resources.md:33 +#, fuzzy +msgid "## Unofficial Learning Material" +msgstr "## Matériel d'apprentissage non officiel" + +#: src/other-resources.md:35 +#, fuzzy +msgid "A small selection of other guides and tutorial for Rust:" +msgstr "Une petite sélection d'autres guides et tutoriels pour 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/) : couvre Rust\n" +" du point de vue des programmeurs C de bas niveau.\n" +"* [Rouille pour Embedded C\n" +" Programmeurs] (https://docs.opentitan.org/doc/ug/rust_for_c/) : couvre Rust de\n" +" le point de vue des développeurs qui écrivent des firmwares en C.\n" +"* [Rust pour les professionnels](https://overexact.com/rust-for-professionals/):\n" +" couvre la syntaxe de Rust en utilisant des comparaisons côte à côte avec d'autres langages\n" +" tels que C, C++, Java, JavaScript et Python.\n" +"* [Rust on Exercism](https://exercism.org/tracks/rust) : plus de 100 exercices pour vous aider\n" +" vous apprenez Rust.\n" +"* [Enseignement ferreux\n" +" Matériel] (https://ferrous-systems.github.io/teaching-material/index.html) : un\n" +" série de petites présentations couvrant à la fois la partie de base et avancée de la\n" +" Langue de rouille. D'autres sujets tels que WebAssembly et async/wait sont également\n" +" couvert.\n" +"* [Série débutant à\n" +" Rust](https://docs.microsoft.com/en-us/shows/beginners-series-to-rust/) et\n" +" [Faites vos premiers pas avec\n" +" Rust](https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/) : deux\n" +" Guides Rust destinés aux nouveaux développeurs. Le premier est un ensemble de 35 vidéos et le\n" +" le second est un ensemble de 11 modules qui couvre la syntaxe Rust et les constructions de base.\n" +"* [Apprenez Rust avec trop de liens\n" +" Listes] (https://rust-unofficial.github.io/too-many-lists/) : en profondeur\n" +" exploration des règles de gestion de la mémoire de Rust, en implémentant quelques\n" +" différents types de structures de liste." + +#: 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 "" +"Veuillez consulter le [Little Book of Rust Books](https://lborb.github.io/book/) pour\n" +"encore plus de livres Rust." + +#: src/credits.md:1 +#, fuzzy +msgid "# Credits" +msgstr "# Crédits" + +#: 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 "" +"Le matériel ici s'appuie sur les nombreuses sources de documentation de Rust.\n" +"Voir la page sur [autres ressources] (other-resources.md) pour une liste complète des ressources utiles\n" +"ressources." + +#: src/credits.md:7 +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 "" +"Le matériel de Comprehensive Rust(le guide complet de Rust) est sous licence sous les termes de la licence d'Apache 2.0,\n" +"veuillez consulter [`LICENSE`](../LICENSE) pour plus de détails." + +#: src/credits.md:10 +#, fuzzy +msgid "## Rust by Example" +msgstr "## Rouille par exemple" + +#: 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 "" +"Quelques exemples et exercices ont été copiés et adaptés de [Rust by\n" +"Exemple](https://doc.rust-lang.org/rust-by-example/). Veuillez consulter le\n" +"Répertoire `third_party/rust-by-example/` pour plus de détails, y compris la licence\n" +"conditions." + +#: src/credits.md:17 +#, fuzzy +msgid "## Rust on Exercism" +msgstr "## Rouille sur l'exercice" + +#: 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 "" +"Certains exercices ont été copiés et adaptés de [Rust on\n" +"Exercice] (https://exercism.org/tracks/rust). Veuillez consulter le\n" +"Répertoire `third_party/rust-on-exercism/` pour plus de détails, y compris la licence\n" +"conditions." + +#: 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 "" +"La section [Interopérabilité avec C++](android/interoperability/cpp.md) utilise un\n" +"image de [CXX](https://cxx.rs/). Veuillez consulter le répertoire `third_party/cxx/`\n" +"pour plus de détails, y compris les termes de la licence." + +#: src/welcome-bare-metal.md:1 +#, fuzzy +msgid "# Welcome to Bare Metal Rust" +msgstr "# Bienvenue dans Bare Metal Rust" + +#: src/welcome-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" +"basics of Rust (perhaps from completing the Comprehensive Rust course), and ideally also have some\n" +"experience with bare-metal programming in some other language such as C." +msgstr "" +"Il s'agit d'un cours autonome d'une journée sur la bare-metal Rust, destiné aux personnes familiarisées avec le\n" +"bases de Rust (peut-être après avoir terminé le cours Comprehensive Rust(le guide complet de Rust)), et idéalement aussi avoir quelques\n" +"expérience de la programmation bare-metal dans un autre langage tel que C." + +#: src/welcome-bare-metal.md:7 +#, fuzzy +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 "" +"Aujourd'hui, nous allons parler de Rust \"bare-metal\": exécuter du code Rust sans système d'exploitation sous nous. Cette volonté\n" +"être divisé en plusieurs parties :" + +#: src/welcome-bare-metal.md:10 +#, fuzzy +msgid "" +"- What is `no_std` Rust?\n" +"- Writing firmware for microcontrollers.\n" +"- Writing bootloader / kernel code for application processors.\n" +"- Some useful crates for bare-metal Rust development." +msgstr "" +"- Qu'est-ce que `no_std` Rust ?\n" +"- Ecriture de firmware pour microcontrôleurs.\n" +"- Ecriture du bootloader / code noyau pour les processeurs d'application.\n" +"- Quelques caisses utiles pour le développement de Rust en métal nu." + +#: src/welcome-bare-metal.md:15 +#, fuzzy +msgid "" +"For the microcontroller part of the course we will use the [BBC micro:bit](https://microbit.org/) v2\n" +"as an example. It's a [development board](https://tech.microbit.org/hardware/) based on the Nordic\n" +"nRF51822 microcontroller with some LEDs and buttons, an I2C-connected accelerometer and compass, and\n" +"an on-board SWD debugger." +msgstr "" +"Pour la partie microcontrôleur du cours, nous utiliserons le [BBC micro:bit](https://microbit.org/) v2\n" +"par exemple. C'est une [carte de développement](https://tech.microbit.org/hardware/) basée sur le Nordic\n" +"Microcontrôleur nRF51822 avec quelques LED et boutons, un accéléromètre et une boussole connectés I2C, et\n" +"un débogueur SWD intégré." + +#: src/welcome-bare-metal.md:20 +#, fuzzy +msgid "To get started, install some tools we'll need later. On gLinux or Debian:" +msgstr "Pour commencer, installez quelques outils dont nous aurons besoin plus tard. Sous gLinux ou Debian :" + +#: src/welcome-bare-metal.md:22 +msgid "" +"```bash\n" +"sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom qemu-system-arm\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" +msgstr "" + +#: src/welcome-bare-metal.md:30 +#, fuzzy +msgid "And give users in the `plugdev` group access to the micro:bit programmer:" +msgstr "Et donnez aux utilisateurs du groupe `plugdev` l'accès au programmeur micro:bit :" + +#: src/welcome-bare-metal.md:32 +msgid "" +"```bash\n" +"echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", GROUP=\"plugdev\"' |\\\n" +" sudo tee /etc/udev/rules.d/50-microbit.rules\n" +"sudo udevadm control --reload-rules\n" +"```" +msgstr "" + +#: src/welcome-bare-metal.md:38 +#, fuzzy +msgid "On MacOS:" +msgstr "Sur MacOS :" + +#: src/welcome-bare-metal.md:40 +msgid "" +"```bash\n" +"xcode-select --install\n" +"brew install gdb picocom qemu\n" +"brew install --cask gcc-aarch64-embedded\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" +msgstr "" + +#: src/bare-metal/no_std.md:1 +#, fuzzy +msgid "# `no_std`" +msgstr "# `no_std`" + +#: src/bare-metal/no_std.md:3 +#, fuzzy +msgid "" +"\n" +"\n" +"\n" +"\n" +"\n" +"" + +#: src/bare-metal/no_std.md:12 +#, fuzzy +msgid "`alloc`" +msgstr "`allouer`" + +#: src/bare-metal/no_std.md:17 +#, fuzzy +msgid "`std`" +msgstr "`std`" + +#: src/bare-metal/no_std.md:19 +#, fuzzy +msgid "" +"\n" +"\n" +"\n" +"\n" +"\n" +"
" + +#: src/bare-metal/no_std.md:24 +#, fuzzy +msgid "" +"* Slices, `&str`, `CStr`\n" +"* `NonZeroU8`...\n" +"* `Option`, `Result`\n" +"* `Display`, `Debug`, `write!`...\n" +"* `Iterator`\n" +"* `panic!`, `assert_eq!`...\n" +"* `NonNull` and all the usual pointer-related functions\n" +"* `Future` and `async`/`await`\n" +"* `fence`, `AtomicBool`, `AtomicPtr`, `AtomicU32`...\n" +"* `Duration`" +msgstr "" +"* Tranches, `&str`, `CStr`\n" +"* `NonZeroU8`...\n" +"* `Option`, `Résultat`\n" +"* `Afficher`, `Déboguer`, `écrire !`...\n" +"* `Itérateur`\n" +"* `panique !`, `assert_eq !`...\n" +"* `NonNull` et toutes les fonctions habituelles liées au pointeur\n" +"* `Future` et `async`/`wait`\n" +"* `clôture`, `AtomicBool`, `AtomicPtr`, `AtomicU32`...\n" +"* `Durée`" + +#: src/bare-metal/no_std.md:35 src/bare-metal/no_std.md:42 +#, fuzzy +msgid "" +"\n" +"
\n" +"
" + +#: src/bare-metal/no_std.md:38 +#, fuzzy +msgid "" +"* `Box`, `Cow`, `Arc`, `Rc`\n" +"* `Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque`\n" +"* `String`, `CString`, `format!`" +msgstr "" +"* `Boîte`, `Vache`, `Arc`, `Rc`\n" +"* `Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque`\n" +"* `Chaîne`, `CString`, `format !`" + +#: src/bare-metal/no_std.md:45 +#, fuzzy +msgid "" +"* `Error`\n" +"* `HashMap`\n" +"* `Mutex`, `Condvar`, `Barrier`, `Once`, `RwLock`, `mpsc`\n" +"* `File` and the rest of `fs`\n" +"* `println!`, `Read`, `Write`, `Stdin`, `Stdout` and the rest of `io`\n" +"* `Path`, `OsString`\n" +"* `net`\n" +"* `Command`, `Child`, `ExitCode`\n" +"* `spawn`, `sleep` and the rest of `thread`\n" +"* `SystemTime`, `Instant`" +msgstr "" +"* \"Erreur\"\n" +"* `HashMap`\n" +"* `Mutex`, `Condvar`, `Barrière`, `Une fois`, `RwLock`, `mpsc`\n" +"* `File` et le reste de `fs`\n" +"* `println!`, `Read`, `Write`, `Stdin`, `Stdout` et le reste de `io`\n" +"* `Chemin`, `OsString`\n" +"* \"net\"\n" +"* `Commande`, `Enfant`, `Code de sortie`\n" +"* `spawn`, `sleep` et le reste de `thread`\n" +"* `SystemTime`, `Instantané`" + +#: src/bare-metal/no_std.md:56 +#, fuzzy +msgid "" +"\n" +"
\n" +"
" +msgstr "" +"\n" +"
" + +#: src/bare-metal/no_std.md:7 +#, fuzzy +msgid "`core`" +msgstr "`noyau`" + +#: src/bare-metal/no_std.md:9 src/bare-metal/no_std.md:14 +#, fuzzy +msgid "" +"" +msgstr "" +"
" +msgstr "" +"\n" +"
" +msgstr "" +"
\n" +"\n" +"
" +msgstr "" +"\n" +"\n" +"\n" +"\n" +"" + +#: src/bare-metal/no_std.md:62 +#, fuzzy +msgid "" +"* `HashMap` depends on RNG.\n" +"* `std` re-exports the contents of both `core` and `alloc`." +msgstr "" +"* `HashMap` dépend de RNG.\n" +"* `std` réexporte le contenu de `core` et `alloc`." + +#: src/bare-metal/minimal.md:1 +#, fuzzy +msgid "# A minimal `no_std` program" +msgstr "# Un programme minimal `no_std`" + +#: src/bare-metal/minimal.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::panic::PanicInfo;\n" +"\n" +"#[panic_handler]\n" +"fn panic(_panic: &PanicInfo) -> ! {\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/minimal.md:17 +msgid "" +"* This will compile to an empty binary.\n" +"* `std` provides a panic handler; without it we must provide our own.\n" +"* It can also be provided by another crate, such as `panic-halt`.\n" +"* Depending on the target, you may need to compile with `panic = \"abort\"` to avoid an error about\n" +" `eh_personality`.\n" +"* Note that there is no `main` or any other entry point; it's up to you to define your own entry\n" +" point. This will typically involve a linker script and some assembly code to set things up ready\n" +" for Rust code to run." +msgstr "" + +#: src/bare-metal/alloc.md:1 +#, fuzzy +msgid "# `alloc`" +msgstr "# `allouer`" + +#: src/bare-metal/alloc.md:3 +#, fuzzy +msgid "" +"To use `alloc` you must implement a\n" +"[global (heap) allocator](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html)." +msgstr "" +"Pour utiliser `alloc` vous devez implémenter un\n" +"[allocateur global (de tas)](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html)." + +#: src/bare-metal/alloc.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate alloc;\n" +"extern crate panic_halt as _;\n" +"\n" +"use alloc::{string::ToString, vec::Vec};\n" +"use buddy_system_allocator::LockedHeap;\n" +"\n" +"#[global_allocator]\n" +"static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();\n" +"\n" +"static mut HEAP: [u8; 65536] = [0; 65536];\n" +"\n" +"pub fn entry() {\n" +" // Safe because `HEAP` is only used here and `entry` is only called once.\n" +" unsafe {\n" +" // Give the allocator some memory to allocate.\n" +" HEAP_ALLOCATOR\n" +" .lock()\n" +" .init(HEAP.as_mut_ptr() as usize, HEAP.len());\n" +" }\n" +"\n" +" // Now we can do things that require heap allocation.\n" +" let mut v = Vec::new();\n" +" v.push(\"A string\".to_string());\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/alloc.md:38 +msgid "" +"* `buddy_system_allocator` is a third-party crate implementing a basic buddy system allocator. Other\n" +" crates are available, or you can write your own or hook into your existing allocator.\n" +"* The const parameter of `LockedHeap` is the max order of the allocator; i.e. in this case it can\n" +" allocate regions of up to 2**32 bytes.\n" +"* If any crate in your dependency tree depends on `alloc` then you must have exactly one global\n" +" allocator defined in your binary. Usually this is done in the top-level binary crate.\n" +"* `extern crate panic_halt as _` is necessary to ensure that the `panic_halt` crate is linked in so\n" +" we get its panic handler.\n" +"* This example will build but not run, as it doesn't have an entry point." +msgstr "" + +#: src/bare-metal/microcontrollers.md:1 +#, fuzzy +msgid "# Microcontrollers" +msgstr "# Microcontrôleurs" + +#: src/bare-metal/microcontrollers.md:3 +#, fuzzy +msgid "The `cortex_m_rt` crate provides (among other things) a reset handler for Cortex M microcontrollers." +msgstr "La caisse `cortex_m_rt` fournit (entre autres) un gestionnaire de réinitialisation pour les microcontrôleurs Cortex M." + +#: src/bare-metal/microcontrollers.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use cortex_m_rt::entry;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers.md:21 +#, fuzzy +msgid "Next we'll look at how to access peripherals, with increasing levels of abstraction." +msgstr "Ensuite, nous verrons comment accéder aux périphériques, avec des niveaux d'abstraction croissants." + +#: src/bare-metal/microcontrollers.md:25 +#, fuzzy +msgid "" +"* The `cortex_m_rt::entry` macro requires that the function have type `fn() -> !`, because returning\n" +" to the reset handler doesn't make sense.\n" +"* Run the example with `cargo embed --bin minimal`" +msgstr "" +"* La macro `cortex_m_rt::entry` nécessite que la fonction ait le type `fn() -> !`, car le retour\n" +" au gestionnaire de réinitialisation n'a pas de sens.\n" +"* Exécutez l'exemple avec `cargo embed --bin minimal`" + +#: src/bare-metal/microcontrollers/mmio.md:1 +#, fuzzy +msgid "# Raw MMIO" +msgstr "# MMIO brut" + +#: src/bare-metal/microcontrollers/mmio.md:3 +#, fuzzy +msgid "" +"Most microcontrollers access peripherals via memory-mapped IO. Let's try turning on an LED on our\n" +"micro:bit:" +msgstr "" +"La plupart des microcontrôleurs accèdent aux périphériques via des E/S mappées en mémoire. Essayons d'allumer une LED sur notre\n" +"micro:bit:" + +#: src/bare-metal/microcontrollers/mmio.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use core::mem::size_of;\n" +"use cortex_m_rt::entry;\n" +"\n" +"/// GPIO port 0 peripheral address\n" +"const GPIO_P0: usize = 0x5000_0000;\n" +"\n" +"// GPIO peripheral offsets\n" +"const PIN_CNF: usize = 0x700;\n" +"const OUTSET: usize = 0x508;\n" +"const OUTCLR: usize = 0x50c;\n" +"\n" +"// PIN_CNF fields\n" +"const DIR_OUTPUT: u32 = 0x1;\n" +"const INPUT_DISCONNECT: u32 = 0x1 << 1;\n" +"const PULL_DISABLED: u32 = 0x0 << 2;\n" +"const DRIVE_S0S1: u32 = 0x0 << 8;\n" +"const SENSE_DISABLED: u32 = 0x0 << 16;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let pin_cnf_21 = (GPIO_P0 + PIN_CNF + 21 * size_of::()) as *mut u32;\n" +" let pin_cnf_28 = (GPIO_P0 + PIN_CNF + 28 * size_of::()) as *mut u32;\n" +" // Safe because the pointers are to valid peripheral control registers, and\n" +" // no aliases exist.\n" +" unsafe {\n" +" pin_cnf_21.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED,\n" +" );\n" +" pin_cnf_28.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED,\n" +" );\n" +" }\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" let gpio0_outset = (GPIO_P0 + OUTSET) as *mut u32;\n" +" let gpio0_outclr = (GPIO_P0 + OUTCLR) as *mut u32;\n" +" // Safe because the pointers are to valid peripheral control registers, and\n" +" // no aliases exist.\n" +" unsafe {\n" +" gpio0_outclr.write_volatile(1 << 28);\n" +" gpio0_outset.write_volatile(1 << 21);\n" +" }\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:64 +#, fuzzy +msgid "* GPIO 0 pin 21 is connected to the first column of the LED matrix, and pin 28 to the first row." +msgstr "* La broche 21 du GPIO 0 est connectée à la première colonne de la matrice LED et la broche 28 à la première rangée." + +#: src/bare-metal/microcontrollers/mmio.md:66 src/bare-metal/microcontrollers/pacs.md:59 src/bare-metal/microcontrollers/hals.md:43 +#: src/bare-metal/microcontrollers/board-support.md:34 +#, fuzzy +msgid "Run the example with:" +msgstr "Exécutez l'exemple avec :" + +#: src/bare-metal/microcontrollers/mmio.md:68 +msgid "" +"```sh\n" +"cargo embed --bin mmio\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:1 +#, fuzzy +msgid "# Peripheral Access Crates" +msgstr "# Caisses d'accès périphérique" + +#: src/bare-metal/microcontrollers/pacs.md:3 +#, fuzzy +msgid "" +"[`svd2rust`](https://crates.io/crates/svd2rust) generates mostly-safe Rust wrappers for\n" +"memory-mapped peripherals from [CMSIS-SVD](https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html)\n" +"files." +msgstr "" +"[`svd2rust`](https://crates.io/crates/svd2rust) génère des wrappers Rust principalement sûrs pour\n" +"périphériques mappés en mémoire de [CMSIS-SVD](https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html)\n" +"des dossiers." + +#: src/bare-metal/microcontrollers/pacs.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_pac::Peripherals;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p.P0;\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" gpio0.pin_cnf[21].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +" gpio0.pin_cnf[28].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" gpio0.outclr.write(|w| w.pin28().clear());\n" +" gpio0.outset.write(|w| w.pin21().set());\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:49 +#, fuzzy +msgid "" +"* SVD (System View Description) files are XML files typically provided by silicon vendors which\n" +" describe the memory map of the device.\n" +" * They are organised by peripheral, register, field and value, with names, descriptions, addresses\n" +" and so on.\n" +" * SVD files are often buggy and incomplete, so there are various projects which patch the\n" +" mistakes, add missing details, and publish the generated crates.\n" +"* `cortex-m-rt` provides the vector table, among other things.\n" +"* If you `cargo install cargo-binutils` then you can run\n" +" `cargo objdump --bin pac -- -d --no-show-raw-insn` to see the resulting binary." +msgstr "" +"* Les fichiers SVD (System View Description) sont des fichiers XML généralement fournis par les fournisseurs de silicium qui\n" +" décrire la carte mémoire de l'appareil.\n" +" * Ils sont organisés par périphérique, registre, champ et valeur, avec noms, descriptions, adresses\n" +" et ainsi de suite.\n" +" * Les fichiers SVD sont souvent bogués et incomplets, il existe donc divers projets qui corrigent le\n" +" erreurs, ajoutez les détails manquants et publiez les caisses générées.\n" +"* `cortex-m-rt` fournit la table des vecteurs, entre autres choses.\n" +"* Si vous \"installez cargo cargo-binutils\", vous pouvez exécuter\n" +" `cargo objdump --bin pac -- -d --no-show-raw-insn` pour voir le binaire résultant." + +#: src/bare-metal/microcontrollers/pacs.md:61 +msgid "" +"```sh\n" +"cargo embed --bin pac\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:1 +#, fuzzy +msgid "# HAL crates" +msgstr "# caisses HAL" + +#: src/bare-metal/microcontrollers/hals.md:3 +#, fuzzy +msgid "" +"[HAL crates](https://github.com/rust-embedded/awesome-embedded-rust#hal-implementation-crates) for\n" +"many microcontrollers provide wrappers around various peripherals. These generally implement traits\n" +"from [`embedded-hal`](https://crates.io/crates/embedded-hal)." +msgstr "" +"[Caisses HAL](https://github.com/rust-embedded/awesome-embedded-rust#hal-implementation-crates) pour\n" +"de nombreux microcontrôleurs fournissent des wrappers autour de divers périphériques. Ceux-ci implémentent généralement des traits\n" +"de [`embedded-hal`](https://crates.io/crates/embedded-hal)." + +#: src/bare-metal/microcontrollers/hals.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_hal::gpio::{p0, Level};\n" +"use nrf52833_hal::pac::Peripherals;\n" +"use nrf52833_hal::prelude::*;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +"\n" +" // Create HAL wrapper for GPIO port 0.\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let mut col1 = gpio0.p0_28.into_push_pull_output(Level::High);\n" +" let mut row1 = gpio0.p0_21.into_push_pull_output(Level::Low);\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" col1.set_low().unwrap();\n" +" row1.set_high().unwrap();\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:39 +#, fuzzy +msgid "" +" * `set_low` and `set_high` are methods on the `embedded_hal` `OutputPin` trait.\n" +" * HAL crates exist for many Cortex-M and RISC-V devices, including various STM32, GD32, nRF, NXP,\n" +" MSP430, AVR and PIC microcontrollers." +msgstr "" +" * `set_low` et `set_high` sont des méthodes sur le trait `embedded_hal` `OutputPin`.\n" +" * Les caisses HAL existent pour de nombreux appareils Cortex-M et RISC-V, y compris divers STM32, GD32, nRF, NXP,\n" +" Microcontrôleurs MSP430, AVR et PIC." + +#: src/bare-metal/microcontrollers/hals.md:45 +msgid "" +"```sh\n" +"cargo embed --bin hal\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:1 +#, fuzzy +msgid "# Board support crates" +msgstr "# Caisses support planche" + +#: src/bare-metal/microcontrollers/board-support.md:3 +#, fuzzy +msgid "Board support crates provide a further level of wrapping for a specific board for convenience." +msgstr "Les caisses de support de planche offrent un niveau supplémentaire d'emballage pour une planche spécifique pour plus de commodité." + +#: src/bare-metal/microcontrollers/board-support.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use microbit::hal::prelude::*;\n" +"use microbit::Board;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let mut board = Board::take().unwrap();\n" +"\n" +" board.display_pins.col1.set_low().unwrap();\n" +" board.display_pins.row1.set_high().unwrap();\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:28 +#, fuzzy +msgid "" +" * In this case the board support crate is just providing more useful names, and a bit of\n" +" initialisation.\n" +" * The crate may also include drivers for some on-board devices outside of the microcontroller\n" +" itself.\n" +" * `microbit-v2` includes a simple driver for the LED matrix." +msgstr "" +" * Dans ce cas, la caisse de support de carte fournit simplement des noms plus utiles, et un peu de\n" +" initialisation.\n" +" * La caisse peut également inclure des pilotes pour certains périphériques embarqués en dehors du microcontrôleur\n" +" lui-même.\n" +" * `microbit-v2` inclut un pilote simple pour la matrice LED." + +#: src/bare-metal/microcontrollers/board-support.md:36 +msgid "" +"```sh\n" +"cargo embed --bin board_support\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:1 +#, fuzzy +msgid "# The type state pattern" +msgstr "# Le modèle d'état de type" + +#: src/bare-metal/microcontrollers/type-state.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" let pin: P0_01 = gpio0.p0_01;\n" +"\n" +" // let gpio0_01_again = gpio0.p0_01; // Error, moved.\n" +" let pin_input: P0_01> = pin.into_floating_input();\n" +" if pin_input.is_high().unwrap() {\n" +" // ...\n" +" }\n" +" let mut pin_output: P0_01> =\n" +" pin_input.into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);\n" +" pin_output.set_high().unwrap();\n" +" // pin_input.is_high(); // Error, moved.\n" +"\n" +" let _pin2: P0_02> = gpio0\n" +" .p0_02\n" +" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);\n" +" let _pin3: P0_03> = gpio0.p0_03.into_push_pull_output(Level::Low);\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:32 +#, fuzzy +msgid "" +" * Pins don't implement `Copy` or `Clone`, so only one instance of each can exist. Once a pin is\n" +" moved out of the port struct nobody else can take it.\n" +" * Changing the configuration of a pin consumes the old pin instance, so you can’t keep use the old\n" +" instance afterwards.\n" +" * The type of a value indicates the state that it is in: e.g. in this case, the configuration state\n" +" of a GPIO pin. This encodes the state machine into the type system, and ensures that you don't\n" +" try to use a pin in a certain way without properly configuring it first. Illegal state\n" +" transitions are caught at compile time.\n" +" * You can call `is_high` on an input pin and `set_high` on an output pin, but not vice-versa.\n" +" * Many HAL crates follow this pattern." +msgstr "" +" * Les broches n'implémentent pas `Copy` ou `Clone`, donc une seule instance de chacun peut exister. Une fois qu'une broche est\n" +" déplacé hors de la structure du port, personne d'autre ne peut le prendre.\n" +" * La modification de la configuration d'une broche consomme l'ancienne instance de broche, vous ne pouvez donc pas continuer à utiliser l'ancienne\n" +" exemple par la suite.\n" +" * Le type d'une valeur indique l'état dans lequel elle se trouve : par ex. dans ce cas, l'état de la configuration\n" +" d'une broche GPIO. Cela encode la machine d'état dans le système de type et garantit que vous ne\n" +" essayez d'utiliser une broche d'une certaine manière sans la configurer correctement au préalable. État illégal\n" +" les transitions sont interceptées au moment de la compilation.\n" +" * Vous pouvez appeler `is_high` sur une broche d'entrée et `set_high` sur une broche de sortie, mais pas l'inverse.\n" +" * De nombreuses caisses HAL suivent ce modèle." + +#: src/bare-metal/microcontrollers/embedded-hal.md:1 +#, fuzzy +msgid "# `embedded-hal`" +msgstr "# `embedded-hal`" + +#: src/bare-metal/microcontrollers/embedded-hal.md:3 +#, fuzzy +msgid "" +"The [`embedded-hal`](https://crates.io/crates/embedded-hal) crate provides a number of traits\n" +"covering common microcontroller peripherals." +msgstr "" +"La caisse [`embedded-hal`](https://crates.io/crates/embedded-hal) fournit un certain nombre de caractéristiques\n" +"couvrant les périphériques de microcontrôleur courants." + +#: src/bare-metal/microcontrollers/embedded-hal.md:6 +#, fuzzy +msgid "" +" * GPIO\n" +" * ADC\n" +" * I2C, SPI, UART, CAN\n" +" * RNG\n" +" * Timers\n" +" * Watchdogs" +msgstr "" +" * GPIO\n" +" * ADC\n" +" * I2C, SPI, UART, PEUT\n" +" * GNA\n" +" * Minuteries\n" +" * Chiens de garde" + +#: src/bare-metal/microcontrollers/embedded-hal.md:13 +#, fuzzy +msgid "" +"Other crates then implement\n" +"[drivers](https://github.com/rust-embedded/awesome-embedded-rust#driver-crates) in terms of these\n" +"traits, e.g. an accelerometer driver might need an I2C or SPI bus implementation." +msgstr "" +"D'autres caisses mettent alors en œuvre\n" +"[pilotes](https://github.com/rust-embedded/awesome-embedded-rust#driver-crates) en ce qui concerne ces\n" +"traits, par ex. un pilote d'accéléromètre peut nécessiter une implémentation de bus I2C ou SPI." + +#: src/bare-metal/microcontrollers/embedded-hal.md:19 +#, fuzzy +msgid "" +" * There are implementations for many microcontrollers, as well as other platforms such as Linux on\n" +"Raspberry Pi.\n" +" * There is work in progress on an `async` version of `embedded-hal`, but it isn't stable yet." +msgstr "" +" * Il existe des implémentations pour de nombreux microcontrôleurs, ainsi que pour d'autres plates-formes telles que Linux sur\n" +"Tarte aux framboises.\n" +" * Il y a des travaux en cours sur une version `async` de `embedded-hal`, mais ce n'est pas encore stable." + +#: src/bare-metal/microcontrollers/probe-rs.md:1 +#, fuzzy +msgid "# `probe-rs`, `cargo-embed`" +msgstr "# `probe-rs`, `cargo-embed`" + +#: src/bare-metal/microcontrollers/probe-rs.md:3 +#, fuzzy +msgid "" +"[probe-rs](https://probe.rs/) is a handy toolset for embedded debugging, like OpenOCD but better\n" +"integrated." +msgstr "" +"[probe-rs](https://probe.rs/) est un ensemble d'outils pratique pour le débogage intégré, comme OpenOCD mais en mieux\n" +"intégré." + +#: src/bare-metal/microcontrollers/probe-rs.md:6 +#, fuzzy +msgid "" +"* SWD and JTAG via CMSIS-DAP, ST-Link and J-Link probes\n" +"* GDB stub and Microsoft DAP server\n" +"* Cargo integration" +msgstr "" +"* SWD et JTAG via les sondes CMSIS-DAP, ST-Link et J-Link\n" +"* Stub GDB et serveur Microsoft DAP\n" +"* Intégration du fret" + +#: src/bare-metal/microcontrollers/probe-rs.md:10 +#, fuzzy +msgid "" +"`cargo-embed` is a cargo subcommand to build and flash binaries, log\n" +"RTT output and connect GDB. It's configured by an\n" +"`Embed.toml` file in your project directory." +msgstr "" +"`cargo-embed` est une sous-commande cargo pour construire et flasher des binaires, enregistrer\n" +"Sortie RTT et connectez GDB. Il est configuré par un\n" +"Fichier `Embed.toml` dans votre répertoire de projet." + +#: src/bare-metal/microcontrollers/probe-rs.md:16 +#, fuzzy +msgid "" +"* [CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) is an Arm standard\n" +" protocol over USB for an in-circuit debugger to access the CoreSight Debug Access Port of various\n" +" Arm Cortex processors. It's what the on-board debugger on the BBC micro:bit uses.\n" +"* ST-Link is a range of in-circuit debuggers from ST Microelectronics, J-Link is a range from\n" +" SEGGER.\n" +"* The Debug Access Port is usually either a 5-pin JTAG interface or 2-pin Serial Wire Debug.\n" +"* probe-rs is a library which you can integrate into your own tools if you want to.\n" +"* The [Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/) lets\n" +" VSCode and other IDEs debug code running on any supported microcontroller.\n" +"* cargo-embed is a binary built using the probe-rs library.\n" +"* RTT (Real Time Transfers) is a mechanism to transfer data between the debug host and the target\n" +" through a number of ringbuffers." +msgstr "" +"* [CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) est une norme Arm\n" +" protocole sur USB pour un débogueur en circuit pour accéder au port d'accès de débogage CoreSight de divers\n" +" Processeurs Arm Cortex. C'est ce que le débogueur embarqué sur le BBC micro:bit utilise.\n" +"* ST-Link est une gamme de débogueurs en circuit de ST Microelectronics, J-Link est une gamme de\n" +" SEGER.\n" +"* Le port d'accès au débogage est généralement une interface JTAG à 5 broches ou un débogage de fil série à 2 broches.\n" +"* probe-rs est une bibliothèque que vous pouvez intégrer dans vos propres outils si vous le souhaitez.\n" +"* Le [protocole de l'adaptateur de débogage Microsoft] (https://microsoft.github.io/debug-adapter-protocol/) permet\n" +" VSCode et d'autres IDE déboguent le code s'exécutant sur n'importe quel microcontrôleur pris en charge.\n" +"* cargo-embed est un binaire construit à l'aide de la bibliothèque probe-rs.\n" +"* RTT (Real Time Transfers) est un mécanisme de transfert de données entre l'hôte de débogage et la cible\n" +" à travers un certain nombre de tampons circulaires." + +#: src/bare-metal/microcontrollers/debugging.md:1 +#, fuzzy +msgid "# Debugging" +msgstr "# Débogage" + +#: src/bare-metal/microcontrollers/debugging.md:3 +#, fuzzy +msgid "Embed.toml:" +msgstr "Intégrer.toml :" + +#: src/bare-metal/microcontrollers/debugging.md:5 +msgid "" +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:13 +#, fuzzy +msgid "In one terminal under `src/bare-metal/microcontrollers/examples/`:" +msgstr "Dans un terminal sous `src/bare-metal/microcontrollers/examples/` :" + +#: src/bare-metal/microcontrollers/debugging.md:15 +msgid "" +"```sh\n" +"cargo embed --bin board_support debug\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:19 +#, fuzzy +msgid "In another terminal in the same directory:" +msgstr "Dans un autre terminal du même répertoire :" + +#: src/bare-metal/microcontrollers/debugging.md:21 +msgid "" +"```sh\n" +"gdb-multiarch target/thumbv7em-none-eabihf/debug/board_support --eval-command=\"target remote :1337\"\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:27 +#, fuzzy +msgid "In GDB, try running:" +msgstr "Dans GDB, essayez d'exécuter :" + +#: src/bare-metal/microcontrollers/debugging.md:29 +msgid "" +"```gdb\n" +"b src/bin/board_support.rs:29\n" +"b src/bin/board_support.rs:30\n" +"b src/bin/board_support.rs:32\n" +"c\n" +"c\n" +"c\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/other-projects.md:1 src/bare-metal/aps/other-projects.md:1 +#, fuzzy +msgid "# Other projects" +msgstr "# Autres projets" + +#: src/bare-metal/microcontrollers/other-projects.md:3 +#, fuzzy +msgid "" +" * [RTIC](https://rtic.rs/)\n" +" * \"Real-Time Interrupt-driven Concurrency\"\n" +" * Shared resource management, message passing, task scheduling, timer queue\n" +" * [Embassy](https://embassy.dev/)\n" +" * `async` executors with priorities, timers, networking, USB\n" +" * [TockOS](https://www.tockos.org/documentation/getting-started)\n" +" * Security-focused RTOS with preemptive scheduling and Memory Protection Unit support\n" +" * [Hubris](https://hubris.oxide.computer/)\n" +" * Microkernel RTOS from Oxide Computer Company with memory protection, unprivileged drivers, IPC\n" +" * [Bindings for FreeRTOS](https://github.com/lobaro/FreeRTOS-rust)\n" +" * Some platforms have `std` implementations, e.g.\n" +" [esp-idf](https://esp-rs.github.io/book/overview/using-the-standard-library.html)." +msgstr "" +" * [RTIC](https://rtic.rs/)\n" +" * \"Concurrence pilotée par interruption en temps réel\"\n" +" * Gestion des ressources partagées, transmission de messages, planification des tâches, file d'attente du minuteur\n" +" * [Ambassade](https://embassy.dev/)\n" +" * Exécuteurs \"asynchrones\" avec priorités, minuteries, mise en réseau, USB\n" +" * [TockOS](https://www.tockos.org/documentation/getting-started)\n" +" * RTOS axé sur la sécurité avec planification préemptive et prise en charge de l'unité de protection de la mémoire\n" +" * [Hubris](https://hubris.oxide.computer/)\n" +" * Microkernel RTOS d'Oxide Computer Company avec protection de la mémoire, pilotes non privilégiés, IPC\n" +" * [Liaisons pour FreeRTOS](https://github.com/lobaro/FreeRTOS-rust)\n" +" * Certaines plates-formes ont des implémentations \"std\", par ex.\n" +" [esp-idf](https://esp-rs.github.io/book/overview/using-the-standard-library.html)." + +#: src/bare-metal/microcontrollers/other-projects.md:18 +#, fuzzy +msgid "" +" * RTIC can be considered either an RTOS or a concurrency framework.\n" +" * It doesn't include any HALs.\n" +" * It uses the Cortex-M NVIC (Nested Virtual Interrupt Controller) for scheduling rather than a\n" +" proper kernel.\n" +" * Cortex-M only.\n" +" * Google uses TockOS on the Haven microcontroller for Titan security keys.\n" +" * FreeRTOS is mostly written in C, but there are Rust bindings for writing applications." +msgstr "" +" * RTIC peut être considéré comme un RTOS ou un cadre de concurrence.\n" +" * Il n'inclut aucun HAL.\n" +" * Il utilise le Cortex-M NVIC (Nested Virtual Interrupt Controller) pour la planification plutôt qu'un\n" +" noyau approprié.\n" +" * Cortex-M uniquement.\n" +" * Google utilise TockOS sur le microcontrôleur Haven pour les clés de sécurité Titan.\n" +" * FreeRTOS est principalement écrit en C, mais il existe des liaisons Rust pour écrire des applications." + +#: src/exercises/bare-metal/morning.md:3 +#, fuzzy +msgid "We will read the direction from an I2C compass, and log the readings to a serial port." +msgstr "Nous lirons la direction à partir d'une boussole I2C et enregistrerons les lectures sur un port série." + +#: src/exercises/bare-metal/compass.md:1 +#, fuzzy +msgid "# Compass" +msgstr "# Boussole" + +#: src/exercises/bare-metal/compass.md:3 +#, fuzzy +msgid "" +"We will read the direction from an I2C compass, and log the readings to a serial port. If you have\n" +"time, try displaying it on the LEDs somehow too, or use the buttons somehow." +msgstr "" +"Nous lirons la direction à partir d'une boussole I2C et enregistrerons les lectures sur un port série. Si tu as\n" +"temps, essayez de l'afficher sur les LED d'une manière ou d'une autre, ou utilisez les boutons d'une manière ou d'une autre." + +#: src/exercises/bare-metal/compass.md:6 +#, fuzzy +msgid "Hints:" +msgstr "Astuces:" + +#: src/exercises/bare-metal/compass.md:8 +#, fuzzy +msgid "" +"- Check the documentation for the [`lsm303agr`](https://docs.rs/lsm303agr/latest/lsm303agr/) and\n" +" [`microbit-v2`](https://docs.rs/microbit-v2/latest/microbit/) crates, as well as the\n" +" [micro:bit hardware](https://tech.microbit.org/hardware/).\n" +"- The LSM303AGR Inertial Measurement Unit is connected to the internal I2C bus.\n" +"- TWI is another name for I2C, so the I2C master peripheral is called TWIM.\n" +"- The LSM303AGR driver needs something implementing the `embedded_hal::blocking::i2c::WriteRead`\n" +" trait. The\n" +" [`microbit::hal::Twim`](https://docs.rs/microbit-v2/latest/microbit/hal/struct.Twim.html) struct\n" +" implements this.\n" +"- You have a [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/struct.Board.html)\n" +" struct with fields for the various pins and peripherals.\n" +"- You can also look at the\n" +" [nRF52833 datasheet](https://infocenter.nordicsemi.com/pdf/nRF52833_PS_v1.5.pdf) if you want, but\n" +" it shouldn't be necessary for this exercise." +msgstr "" +"- Consultez la documentation du [`lsm303agr`](https://docs.rs/lsm303agr/latest/lsm303agr/) et\n" +" [`microbit-v2`](https://docs.rs/microbit-v2/latest/microbit/) caisses, ainsi que les\n" +" [matériel micro:bit](https://tech.microbit.org/hardware/).\n" +"- La centrale de mesure inertielle LSM303AGR est connectée au bus interne I2C.\n" +"- TWI est un autre nom pour I2C, donc le périphérique maître I2C s'appelle TWIM.\n" +"- Le pilote LSM303AGR a besoin de quelque chose implémentant `embedded_hal::blocking::i2c::WriteRead`\n" +" trait. Le\n" +" [`microbit::hal::Twim`](https://docs.rs/microbit-v2/latest/microbit/hal/struct.Twim.html) structure\n" +" implémente cela.\n" +"- Vous avez un [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/struct.Board.html)\n" +" structure avec des champs pour les différentes broches et périphériques.\n" +"- Vous pouvez également consulter le\n" +" [fiche technique nRF52833](https://infocenter.nordicsemi.com/pdf/nRF52833_PS_v1.5.pdf) si vous le souhaitez, mais\n" +" cela ne devrait pas être nécessaire pour cet exercice." + +#: src/exercises/bare-metal/compass.md:23 +#, fuzzy +msgid "" +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the `compass`\n" +"directory for the following files." +msgstr "" +"Téléchargez le [modèle d'exercice] (../../comprehensive-rust-exercises.zip) et regardez dans la `boussole`\n" +"répertoire pour les fichiers suivants." + +#: src/exercises/bare-metal/compass.md:26 src/exercises/bare-metal/rtc.md:10 +#, fuzzy +msgid "`src/main.rs`:" +msgstr "`src/main.rs` :" + +#: src/exercises/bare-metal/compass.md:30 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"use microbit::{hal::uarte::{Baudrate, Parity, Uarte}, Board};\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // TODO\n" +"\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // TODO\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:64 src/exercises/bare-metal/rtc.md:359 +#, fuzzy +msgid "`Cargo.toml` (you shouldn't need to change this):" +msgstr "`Cargo.toml` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/compass.md:68 +msgid "" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"compass\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"cortex-m-rt = \"0.7.3\"\n" +"embedded-hal = \"0.2.6\"\n" +"lsm303agr = \"0.2.2\"\n" +"microbit-v2 = \"0.13.0\"\n" +"panic-halt = \"0.2.0\"\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:85 +#, fuzzy +msgid "`Embed.toml` (you shouldn't need to change this):" +msgstr "`Embed.toml` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/compass.md:87 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/compass.md:89 +msgid "" +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"\n" +"[debug.reset]\n" +"halt_afterwards = true\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:100 src/exercises/bare-metal/rtc.md:958 +#, fuzzy +msgid "`.cargo/config.toml` (you shouldn't need to change this):" +msgstr "`.cargo/config.toml` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/compass.md:102 src/exercises/bare-metal/rtc.md:960 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/compass.md:104 +msgid "" +"```toml\n" +"[build]\n" +"target = \"thumbv7em-none-eabihf\" # Cortex-M4F\n" +"\n" +"[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))']\n" +"rustflags = [\"-C\", \"link-arg=-Tlink.x\"]\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:112 +#, fuzzy +msgid "See the serial output on Linux with:" +msgstr "Voir la sortie série sur Linux avec :" + +#: src/exercises/bare-metal/compass.md:114 +msgid "" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/ttyACM0\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:118 +#, fuzzy +msgid "Or on Mac OS something like (the device name may be slightly different):" +msgstr "Ou sur Mac OS quelque chose comme (le nom de l'appareil peut être légèrement différent) :" + +#: src/exercises/bare-metal/compass.md:120 +msgid "" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:124 +#, fuzzy +msgid "Use Ctrl+A Ctrl+Q to quit picocom." +msgstr "Utilisez Ctrl+A Ctrl+Q pour quitter picocom." + +#: src/bare-metal/aps.md:1 +#, fuzzy +msgid "# Application processors" +msgstr "# Processeurs d'application" + +#: src/bare-metal/aps.md:3 +#, fuzzy +msgid "" +"So far we've talked about microcontrollers, such as the Arm Cortex-M series. Now let's try writing\n" +"something for Cortex-A. For simplicity we'll just work with QEMU's aarch64\n" +"['virt'](https://qemu-project.gitlab.io/qemu/system/arm/virt.html) board." +msgstr "" +"Jusqu'à présent, nous avons parlé de microcontrôleurs, tels que la série Arm Cortex-M. Essayons maintenant d'écrire\n" +"quelque chose pour Cortex-A. Pour plus de simplicité, nous allons simplement travailler avec aarch64 de QEMU\n" +"['virt'](https://qemu-project.gitlab.io/qemu/system/arm/virt.html)." + +#: src/bare-metal/aps.md:9 +#, fuzzy +msgid "" +"* Broadly speaking, microcontrollers don't have an MMU or multiple levels of privilege (exception\n" +" levels on Arm CPUs, rings on x86), while application processors do.\n" +"* QEMU supports emulating various different machines or board models for each architecture. The\n" +" 'virt' board doesn't correspond to any particular real hardware, but is designed purely for\n" +" virtual machines." +msgstr "" +"* D'une manière générale, les microcontrôleurs n'ont pas de MMU ou plusieurs niveaux de privilège (exception\n" +" niveaux sur les processeurs Arm, sonne sur x86), contrairement aux processeurs d'application.\n" +"* QEMU prend en charge l'émulation de différentes machines ou modèles de cartes pour chaque architecture. Le\n" +" La carte 'virt' ne correspond à aucun matériel réel particulier, mais est conçue uniquement pour\n" +" machines virtuelles." + +#: src/bare-metal/aps/inline-assembly.md:1 +#, fuzzy +msgid "# Inline assembly" +msgstr "# Assemblage en ligne" + +#: src/bare-metal/aps/inline-assembly.md:3 +#, fuzzy +msgid "" +"Sometimes we need to use assembly to do things that aren't possible with Rust code. For example,\n" +"to make an HVC to tell the firmware to power off the system:" +msgstr "" +"Parfois, nous devons utiliser l'assemblage pour faire des choses qui ne sont pas possibles avec le code Rust. Par exemple,\n" +"pour effectuer un HVC pour indiquer au micrologiciel d'éteindre le système :" + +#: src/bare-metal/aps/inline-assembly.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::arch::asm;\n" +"use core::panic::PanicInfo;\n" +"\n" +"mod exceptions;\n" +"\n" +"const PSCI_SYSTEM_OFF: u32 = 0x84000008;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) {\n" +" // Safe because this only uses the declared registers and doesn't do\n" +" // anything with memory.\n" +" unsafe {\n" +" asm!(\"hvc #0\",\n" +" inout(\"w0\") PSCI_SYSTEM_OFF => _,\n" +" inout(\"w1\") 0 => _,\n" +" inout(\"w2\") 0 => _,\n" +" inout(\"w3\") 0 => _,\n" +" inout(\"w4\") 0 => _,\n" +" inout(\"w5\") 0 => _,\n" +" inout(\"w6\") 0 => _,\n" +" inout(\"w7\") 0 => _,\n" +" options(nomem, nostack)\n" +" );\n" +" }\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:39 +#, fuzzy +msgid "(If you actually want to do this, use the [`psci`][1] crate which has wrappers for all these functions.)" +msgstr "(Si vous voulez vraiment faire cela, utilisez le crate [`psci`][1] qui contient des wrappers pour toutes ces fonctions.)" + +#: src/bare-metal/aps/inline-assembly.md:43 +#, fuzzy +msgid "" +"* PSCI is the Arm Power State Coordination Interface, a standard set of functions to manage system\n" +" and CPU power states, among other things. It is implemented by EL3 firmware and hypervisors on\n" +" many systems.\n" +"* The `0 => _` syntax means initialise the register to 0 before running the inline assembly code,\n" +" and ignore its contents afterwards. We need to use `inout` rather than `in` because the call could\n" +" potentially clobber the contents of the registers.\n" +"* This `main` function needs to be `#[no_mangle]` and `extern \"C\"` because it is called from our\n" +" entry point in `entry.S`.\n" +"* `_x0`–`_x3` are the values of registers `x0`–`x3`, which are conventionally used by the bootloader\n" +" to pass things like a pointer to the device tree. According to the standard aarch64 calling\n" +" convention (which is what `extern \"C\"` specifies to use), registers `x0`–`x7` are used for the\n" +" first 8 arguments passed to a function, so `entry.S` doesn't need to do anything special except\n" +" make sure it doesn't change these registers.\n" +"* Run the example in QEMU with `make qemu_psci` under `src/bare-metal/aps/examples`." +msgstr "" +"* PSCI est l'interface de coordination de l'état de l'alimentation du bras, un ensemble standard de fonctions pour gérer le système\n" +" et les états d'alimentation du processeur, entre autres. Il est implémenté par le firmware EL3 et les hyperviseurs sur\n" +" de nombreux systèmes.\n" +"* La syntaxe `0 => _` signifie initialiser le registre à 0 avant d'exécuter le code assembleur en ligne,\n" +" et ignorer son contenu par la suite. Nous devons utiliser `inout` plutôt que `in` car l'appel pourrait\n" +" potentiellement encombrer le contenu des registres.\n" +"* Cette fonction `main` doit être `#[no_mangle]` et `extern \"C\"` car elle est appelée depuis notre\n" +" point d'entrée dans `entry.S`.\n" +"* `_x0`–`_x3` sont les valeurs des registres `x0`–`x3`, qui sont classiquement utilisés par le bootloader\n" +" pour passer des choses comme un pointeur vers l'arborescence des périphériques. Selon l'appel standard aarch64\n" +" convention (qui est ce que `extern \"C\"` spécifie d'utiliser), les registres `x0`–`x7` sont utilisés pour la\n" +" 8 premiers arguments passés à une fonction, donc `entry.S` n'a rien de spécial à faire sauf\n" +" assurez-vous qu'il ne modifie pas ces registres.\n" +"* Exécutez l'exemple dans QEMU avec `make qemu_psci` sous `src/bare-metal/aps/examples`." + +#: src/bare-metal/aps/mmio.md:1 +#, fuzzy +msgid "# Volatile memory access for MMIO" +msgstr "# Accès mémoire volatile pour MMIO" + +#: src/bare-metal/aps/mmio.md:3 +#, fuzzy +msgid "" +" * Use `pointer::read_volatile` and `pointer::write_volatile`.\n" +" * Never hold a reference.\n" +" * `addr_of!` lets you get fields of structs without creating an intermediate reference." +msgstr "" +" * Utilisez `pointer::read_volatile` et `pointer::write_volatile`.\n" +" * Ne détenez jamais une référence.\n" +" * `addr_of!` vous permet d'obtenir des champs de structures sans créer de référence intermédiaire." + +#: src/bare-metal/aps/mmio.md:9 +#, fuzzy +msgid "" +" * Volatile access: read or write operations may have side-effects, so prevent the compiler or\n" +" hardware from reordering, duplicating or eliding them.\n" +" * Usually if you write and then read, e.g. via a mutable reference, the compiler may assume that\n" +" the value read is the same as the value just written, and not bother actually reading memory.\n" +" * Some existing crates for volatile access to hardware do hold references, but this is unsound.\n" +" Whenever a reference exist, the compiler may choose to dereference it.\n" +" * Use the `addr_of!` macro to get struct field pointers from a pointer to the struct." +msgstr "" +" * Accès volatile : les opérations de lecture ou d'écriture peuvent avoir des effets secondaires, évitez donc que le compilateur ou\n" +" matériel de les réorganiser, de les dupliquer ou de les supprimer.\n" +" * Habituellement, si vous écrivez puis lisez, par ex. via une référence mutable, le compilateur peut supposer que\n" +" la valeur lue est la même que la valeur que vous venez d'écrire et ne vous souciez pas de lire la mémoire.\n" +" * Certaines caisses existantes pour l'accès volatile au matériel contiennent des références, mais ce n'est pas valable.\n" +" Chaque fois qu'une référence existe, le compilateur peut choisir de la déréférencer.\n" +" * Utilisez la macro `addr_of!` pour obtenir des pointeurs de champ struct à partir d'un pointeur vers la struct." + +#: src/bare-metal/aps/uart.md:1 +#, fuzzy +msgid "# Let's write a UART driver" +msgstr "# Écrivons un pilote UART" + +#: src/bare-metal/aps/uart.md:3 +#, fuzzy +msgid "The QEMU 'virt' machine has a [PL011][1] UART, so let's write a driver for that." +msgstr "La machine QEMU 'virt' a un [PL011][1] UART, écrivons donc un pilote pour cela." + +#: src/bare-metal/aps/uart.md:5 +msgid "" +"```rust,editable\n" +"const FLAG_REGISTER_OFFSET: usize = 0x18;\n" +"const FR_BUSY: u8 = 1 << 3;\n" +"const FR_TXFF: u8 = 1 << 5;\n" +"\n" +"/// Minimal driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" base_address: *mut u8,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of a\n" +" /// PL011 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u8) -> Self {\n" +" Self { base_address }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register() & FR_TXFF != 0 {}\n" +"\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" self.base_address.write_volatile(byte);\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register() & FR_BUSY != 0 {}\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> u8 {\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { self.base_address.add(FLAG_REGISTER_OFFSET).read_volatile() }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/uart.md:55 +#, fuzzy +msgid "" +"* Note that `Uart::new` is unsafe while the other methods are safe. This is because as long as the\n" +" caller of `Uart::new` guarantees that its safety requirements are met (i.e. that there is only\n" +" ever one instance of the driver for a given UART, and nothing else aliasing its address space),\n" +" then it is always safe to call `write_byte` later because we can assume the necessary\n" +" preconditions.\n" +"* We could have done it the other way around (making `new` safe but `write_byte` unsafe), but that\n" +" would be much less convenient to use as every place that calls `write_byte` would need to reason\n" +" about the safety\n" +"* This is a common pattern for writing safe wrappers of unsafe code: moving the burden of proof for\n" +" soundness from a large number of places to a smaller number of places." +msgstr "" +"* Notez que `Uart::new` n'est pas sûr alors que les autres méthodes sont sûres. C'est parce que tant que le\n" +" l'appelant de `Uart::new` garantit que ses exigences de sécurité sont respectées (c'est-à-dire qu'il n'y a\n" +" jamais une instance du pilote pour un UART donné, et rien d'autre aliasant son espace d'adressage),\n" +" alors il est toujours sûr d'appeler `write_byte` plus tard car nous pouvons supposer que le nécessaire\n" +" conditions préalables.\n" +"* Nous aurions pu faire l'inverse (rendre `new` sûr mais `write_byte` non sûr), mais cela\n" +" serait beaucoup moins pratique à utiliser car chaque endroit qui appelle `write_byte` aurait besoin de raisonner\n" +" sur la sécurité\n" +"* Il s'agit d'un modèle courant pour écrire des wrappers sûrs de code non sécurisé : déplacer la charge de la preuve pour\n" +" solidité d'un grand nombre d'endroits à un plus petit nombre d'endroits." + +#: src/bare-metal/aps/uart.md:66 +#, fuzzy +msgid "" +msgstr "" + +#: src/bare-metal/aps/uart/traits.md:1 +#, fuzzy +msgid "# More traits" +msgstr "# Plus de traits" + +#: src/bare-metal/aps/uart/traits.md:3 +#, fuzzy +msgid "We derived the `Debug` trait. It would be useful to implement a few more traits too." +msgstr "Nous avons dérivé le trait `Debug`. Il serait également utile de mettre en œuvre quelques traits supplémentaires." + +#: src/bare-metal/aps/uart/traits.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use core::fmt::{self, Write};\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/uart/traits.md:24 +#, fuzzy +msgid "" +"* Implementing `Write` lets us use the `write!` and `writeln!` macros with our `Uart` type.\n" +"* Run the example in QEMU with `make qemu_minimal` under `src/bare-metal/aps/examples`." +msgstr "" +"* L'implémentation de `Write` nous permet d'utiliser les macros `write!` et `writeln!` avec notre type `Uart`.\n" +"* Exécutez l'exemple dans QEMU avec `make qemu_minimal` sous `src/bare-metal/aps/examples`." + +#: src/bare-metal/aps/better-uart.md:1 +#, fuzzy +msgid "# A better UART driver" +msgstr "# Un meilleur pilote UART" + +#: src/bare-metal/aps/better-uart.md:3 +#, fuzzy +msgid "" +"The PL011 actually has [a bunch more registers][1], and adding offsets to construct pointers to access\n" +"them is error-prone and hard to read. Plus, some of them are bit fields which would be nice to\n" +"access in a structured way." +msgstr "" +"Le PL011 a en fait [un tas de registres supplémentaires] [1], et ajoute des décalages pour construire des pointeurs pour accéder\n" +"est sujette aux erreurs et difficile à lire. De plus, certains d'entre eux sont des champs de bits, ce qui serait bien de\n" +"accéder de manière structurée." + +#: src/bare-metal/aps/better-uart.md:7 +#, fuzzy +msgid "" +"| Offset | Register name | Width |\n" +"| ------ | ------------- | ----- |\n" +"| 0x00 | DR | 12 |\n" +"| 0x04 | RSR | 4 |\n" +"| 0x18 | FR | 9 |\n" +"| 0x20 | ILPR | 8 |\n" +"| 0x24 | IBRD | 16 |\n" +"| 0x28 | FBRD | 6 |\n" +"| 0x2c | LCR_H | 8 |\n" +"| 0x30 | CR | 16 |\n" +"| 0x34 | IFLS | 6 |\n" +"| 0x38 | IMSC | 11 |\n" +"| 0x3c | RIS | 11 |\n" +"| 0x40 | MIS | 11 |\n" +"| 0x44 | ICR | 11 |\n" +"| 0x48 | DMACR | 3 |" +msgstr "" +"| Décalage | Nom du registre | Largeur |\n" +"| ------ | -------------- | ----- |\n" +"| 0x00 | DR | 12 |\n" +"| 0x04 | RSR | 4 |\n" +"| 0x18 | EN | 9 |\n" +"| 0x20 | ILPR | 8 |\n" +"| 0x24 | BIRD | 16 |\n" +"| 0x28 | FBRD | 6 |\n" +"| 0x2c | LCR_H | 8 |\n" +"| 0x30 | CR | 16 |\n" +"| 0x34 | IFLS | 6 |\n" +"| 0x38 | IMSC | 11 |\n" +"| 0x3c | SIR | 11 |\n" +"| 0x40 | SIG | 11 |\n" +"| 0x44 | RIC | 11 |\n" +"| 0x48 | DMACR | 3 |" + +#: src/bare-metal/aps/better-uart.md:26 +#, fuzzy +msgid "- There are also some ID registers which have been omitted for brevity." +msgstr "- Il existe également des registres d'identification qui ont été omis par souci de brièveté." + +#: src/bare-metal/aps/better-uart/bitflags.md:1 +#, fuzzy +msgid "# Bitflags" +msgstr "# Bitflags" + +#: src/bare-metal/aps/better-uart/bitflags.md:3 +#, fuzzy +msgid "The [`bitflags`](https://crates.io/crates/bitflags) crate is useful for working with bitflags." +msgstr "Le crate [`bitflags`](https://crates.io/crates/bitflags) est utile pour travailler avec les bitflags." + +#: src/bare-metal/aps/better-uart/bitflags.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:37 +#, fuzzy +msgid "" +"* The `bitflags!` macro creates a newtype something like `Flags(u16)`, along with a bunch of method\n" +" implementations to get and set flags." +msgstr "" +"* La macro `bitflags!` crée un nouveau type quelque chose comme `Flags(u16)`, avec un tas de méthodes\n" +" implémentations pour obtenir et définir des drapeaux." + +#: src/bare-metal/aps/better-uart/registers.md:1 +#, fuzzy +msgid "# Multiple registers" +msgstr "# Plusieurs registres" + +#: src/bare-metal/aps/better-uart/registers.md:3 +#, fuzzy +msgid "We can use a struct to represent the memory layout of the UART's registers." +msgstr "Nous pouvons utiliser une structure pour représenter la disposition de la mémoire des registres de l'UART." + +#: src/bare-metal/aps/better-uart/registers.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:41 +#, fuzzy +msgid "" +"* [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-representation) tells\n" +" the compiler to lay the struct fields out in order, following the same rules as C. This is\n" +" necessary for our struct to have a predictable layout, as default Rust representation allows the\n" +" compiler to (among other things) reorder fields however it sees fit." +msgstr "" +"* [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-representation) indique\n" +" le compilateur pour disposer les champs struct dans l'ordre, en suivant les mêmes règles que C. Ceci est\n" +" nécessaire pour que notre structure ait une mise en page prévisible, car la représentation Rust par défaut permet\n" +" compilateur pour (entre autres) réorganiser les champs comme bon lui semble." + +#: src/bare-metal/aps/better-uart/driver.md:1 +#, fuzzy +msgid "# Driver" +msgstr "# Conducteur" + +#: src/bare-metal/aps/better-uart/driver.md:3 +#, fuzzy +msgid "Now let's use the new `Registers` struct in our driver." +msgstr "Utilisons maintenant la nouvelle structure `Registers` dans notre pilote." + +#: src/bare-metal/aps/better-uart/driver.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of a\n" +" /// PL011 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr).read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:64 +#, fuzzy +msgid "" +"* Note the use of `addr_of!` / `addr_of_mut!` to get pointers to individual fields without creating\n" +" an intermediate reference, which would be unsound." +msgstr "" +"* Notez l'utilisation de `addr_of!` / `addr_of_mut!` pour obtenir des pointeurs vers des champs individuels sans créer\n" +" une référence intermédiaire, qui serait malsaine." + +#: src/bare-metal/aps/better-uart/using.md:1 src/bare-metal/aps/logging/using.md:1 +#, fuzzy +msgid "# Using it" +msgstr "# En l'utilisant" + +#: src/bare-metal/aps/better-uart/using.md:3 +#, fuzzy +msgid "" +"Let's write a small program using our driver to write to the serial console, and echo incoming\n" +"bytes." +msgstr "" +"Écrivons un petit programme en utilisant notre pilote pour écrire sur la console série et écho entrant\n" +"octets." + +#: src/bare-metal/aps/better-uart/using.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::{fmt::Write, panic::PanicInfo};\n" +"use log::error;\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"pub const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +"\n" +" writeln!(uart, \"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\").unwrap();\n" +"\n" +" loop {\n" +" if let Some(b) = uart.read_byte() {\n" +" uart.write_byte(b);\n" +" match b {\n" +" b'\\r' => {\n" +" uart.write_byte(b'\\n');\n" +" }\n" +" b'q' => break,\n" +" _ => {}\n" +" }\n" +" }\n" +" }\n" +"\n" +" writeln!(uart, \"Bye!\").unwrap();\n" +" system_off().unwrap();\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:49 +#, fuzzy +msgid "" +"* As in the [inline assembly](../inline-assembly.md) example, this `main` function is called from our\n" +" entry point code in `entry.S`. See the speaker notes there for details.\n" +"* Run the example in QEMU with `make qemu` under `src/bare-metal/aps/examples`." +msgstr "" +"* Comme dans l'exemple [inline assembly](../inline-assembly.md), cette fonction `main` est appelée depuis notre\n" +" code du point d'entrée dans `entry.S`. Voir les notes du conférencier pour plus de détails.\n" +"* Exécutez l'exemple dans QEMU avec `make qemu` sous `src/bare-metal/aps/examples`." + +#: src/bare-metal/aps/logging.md:3 +#, fuzzy +msgid "" +"It would be nice to be able to use the logging macros from the [`log`][1] crate. We can do this by\n" +"implementing the `Log` trait." +msgstr "" +"Ce serait bien de pouvoir utiliser les macros de journalisation du crate [`log`][1]. Nous pouvons le faire en\n" +"implémentant le trait `Log`." + +#: src/bare-metal/aps/logging.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" +" }\n" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/logging.md:50 +#, fuzzy +msgid "* The unwrap in `log` is safe because we initialise `LOGGER` before calling `set_logger`." +msgstr "* Le déballage dans `log` est sûr car nous initialisons `LOGGER` avant d'appeler `set_logger`." + +#: src/bare-metal/aps/logging/using.md:3 +#, fuzzy +msgid "We need to initialise the logger before we use it." +msgstr "Nous devons initialiser l'enregistreur avant de l'utiliser." + +#: src/bare-metal/aps/logging/using.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, LevelFilter};\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"pub const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\");\n" +"\n" +" assert_eq!(x1, 42);\n" +"\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off().unwrap();\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/logging/using.md:45 +#, fuzzy +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`." +msgstr "" +"* Notez que notre gestionnaire de panique peut désormais enregistrer les détails des paniques.\n" +"* Exécutez l'exemple dans QEMU avec `make qemu_logger` sous `src/bare-metal/aps/examples`." + +#: src/bare-metal/aps/other-projects.md:3 +#, fuzzy +msgid "" +" * [oreboot](https://github.com/oreboot/oreboot)\n" +" * \"coreboot without the C\"\n" +" * Supports x86, aarch64 and RISC-V.\n" +" * Relies on LinuxBoot rather than having many drivers itself.\n" +" * [Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials)\n" +" * Initialisation, UART driver, simple bootloader, JTAG, exception levels, exception handling, page tables\n" +" * Not all very well written, so beware.\n" +" * [`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)\n" +" * Static analysis to determine maximum stack usage." +msgstr "" +" * [oreboot](https://github.com/oreboot/oreboot)\n" +" * \"coreboot sans le C\"\n" +" * Prend en charge x86, aarch64 et RISC-V.\n" +" * S'appuie sur LinuxBoot plutôt que d'avoir lui-même de nombreux pilotes.\n" +" * [Tutoriel Rust RaspberryPi OS] (https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials)\n" +" * Initialisation, pilote UART, chargeur de démarrage simple, JTAG, niveaux d'exception, gestion des exceptions, tables de pages\n" +" * Pas tous très bien écrits, alors méfiez-vous.\n" +" * [`pile-appel-cargo`](https://crates.io/crates/pile-appel-cargo)\n" +" * Analyse statique pour déterminer l'utilisation maximale de la pile." + +#: src/bare-metal/useful-crates.md:1 +#, fuzzy +msgid "# Useful crates" +msgstr "# Caisses utiles" + +#: src/bare-metal/useful-crates.md:3 +#, fuzzy +msgid "We'll go over a few crates which solve some common problems in bare-metal programming." +msgstr "Nous allons passer en revue quelques caisses qui résolvent certains problèmes courants de la programmation bare-metal." + +#: src/bare-metal/useful-crates/zerocopy.md:1 +#, fuzzy +msgid "# `zerocopy`" +msgstr "# `zérocopie`" + +#: src/bare-metal/useful-crates/zerocopy.md:3 +#, fuzzy +msgid "" +"The [`zerocopy`][1] crate (from Fuchsia) provides traits and macros for safely converting between\n" +"byte sequences and other types." +msgstr "" +"La caisse [`zerocopy`][1] (de Fuchsia) fournit des traits et des macros pour convertir en toute sécurité entre\n" +"séquences d'octets et autres types." + +#: src/bare-metal/useful-crates/zerocopy.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use zerocopy::AsBytes;\n" +"\n" +"#[repr(u32)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"enum RequestType {\n" +" #[default]\n" +" In = 0,\n" +" Out = 1,\n" +" Flush = 4,\n" +"}\n" +"\n" +"#[repr(C)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"struct VirtioBlockRequest {\n" +" request_type: RequestType,\n" +" reserved: u32,\n" +" sector: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let request = VirtioBlockRequest {\n" +" request_type: RequestType::Flush,\n" +" sector: 42,\n" +" ..Default::default()\n" +" };\n" +"\n" +" assert_eq!(\n" +" request.as_bytes(),\n" +" &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0]\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:40 +#, fuzzy +msgid "" +"This is not suitable for MMIO (as it doesn't use volatile reads and writes), but can be useful for\n" +"working with structures shared with hardware e.g. by DMA, or sent over some external interface." +msgstr "" +"Ce n'est pas adapté pour MMIO (car il n'utilise pas de lectures et d'écritures volatiles), mais peut être utile pour\n" +"travailler avec des structures partagées avec du matériel, par ex. par DMA, ou envoyé sur une interface externe." + +#: src/bare-metal/useful-crates/zerocopy.md:45 +#, fuzzy +msgid "" +"* `FromBytes` can be implemented for types for which any byte pattern is valid, and so can safely be\n" +" converted from an untrusted sequence of bytes.\n" +"* Attempting to derive `FromBytes` for these types would fail, because `RequestType` doesn't use all\n" +" possible u32 values as discriminants, so not all byte patterns are valid.\n" +"* `zerocopy::byteorder` has types for byte-order aware numeric primitives.\n" +"* Run the example with `cargo run` under `src/bare-metal/useful-crates/zerocopy-example/`. (It won't\n" +" run in the Playground because of the crate dependency.)" +msgstr "" +"* `FromBytes` peut être implémenté pour les types pour lesquels n'importe quel modèle d'octet est valide, et peut donc être en toute sécurité\n" +" converti à partir d'une séquence d'octets non fiable.\n" +"* Tenter de dériver `FromBytes` pour ces types échouerait, car `RequestType` n'utilise pas tous\n" +" les valeurs u32 possibles comme discriminants, donc tous les modèles d'octets ne sont pas valides.\n" +"* `zerocopy::byteorder` a des types pour les primitives numériques sensibles à l'ordre des octets.\n" +"* Exécutez l'exemple avec `cargo run` sous `src/bare-metal/useful-crates/zerocopy-example/`. (Ce ne sera pas\n" +" exécuter dans le Playground en raison de la dépendance de la caisse.)" + +#: src/bare-metal/useful-crates/aarch64-paging.md:1 +#, fuzzy +msgid "# `aarch64-paging`" +msgstr "# `aarch64-pagination`" + +#: src/bare-metal/useful-crates/aarch64-paging.md:3 +#, fuzzy +msgid "" +"The [`aarch64-paging`][1] crate lets you create page tables according to the AArch64 Virtual Memory\n" +"System Architecture." +msgstr "" +"La caisse [`aarch64-paging`][1] vous permet de créer des tables de pages en fonction de la mémoire virtuelle AArch64\n" +"Architecture du système." + +#: src/bare-metal/useful-crates/aarch64-paging.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use aarch64_paging::{\n" +" idmap::IdMap,\n" +" paging::{Attributes, MemoryRegion},\n" +"};\n" +"\n" +"const ASID: usize = 1;\n" +"const ROOT_LEVEL: usize = 1;\n" +"\n" +"// Create a new page table with identity mapping.\n" +"let mut idmap = IdMap::new(ASID, ROOT_LEVEL);\n" +"// Map a 2 MiB region of memory as read-only.\n" +"idmap.map_range(\n" +" &MemoryRegion::new(0x80200000, 0x80400000),\n" +" Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,\n" +").unwrap();\n" +"// Set `TTBR0_EL1` to activate the page table.\n" +"idmap.activate();\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:28 +#, fuzzy +msgid "" +"* For now it only supports EL1, but support for other exception levels should be straightforward to\n" +" add.\n" +"* This is used in Android for the [Protected VM Firmware][2].\n" +"* There's no easy way to run this example, as it needs to run on real hardware or under QEMU." +msgstr "" +"* Pour l'instant, il ne prend en charge que EL1, mais la prise en charge d'autres niveaux d'exception devrait être simple à\n" +" ajouter.\n" +"* Ceci est utilisé dans Android pour le [micrologiciel de la machine virtuelle protégée] [2].\n" +"* Il n'y a pas de moyen simple d'exécuter cet exemple, car il doit être exécuté sur du matériel réel ou sous QEMU." + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:1 +#, fuzzy +msgid "# `buddy_system_allocator`" +msgstr "# `buddy_system_allocator`" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:3 +#, fuzzy +msgid "" +"[`buddy_system_allocator`][1] is a third-party crate implementing a basic buddy system allocator.\n" +"It can be used both for [`LockedHeap`][2] implementing [`GlobalAlloc`][3] so you can use the\n" +"standard `alloc` crate (as we saw [before][4]), or for allocating other address space. For example,\n" +"we might want to allocate MMIO space for PCI BARs:" +msgstr "" +"[`buddy_system_allocator`][1] est une caisse tierce implémentant un système d'allocation de copains de base.\n" +"Il peut être utilisé à la fois pour [`LockedHeap`][2] implémentant [`GlobalAlloc`][3] afin que vous puissiez utiliser le\n" +"caisse `alloc` standard (comme nous l'avons vu [avant] [4]), ou pour allouer un autre espace d'adressage. Par exemple,\n" +"nous pourrions vouloir allouer de l'espace MMIO pour les PCI BAR :" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use buddy_system_allocator::FrameAllocator;\n" +"use core::alloc::Layout;\n" +"\n" +"fn main() {\n" +" let mut allocator = FrameAllocator::<32>::new();\n" +" allocator.add_frame(0x200_0000, 0x400_0000);\n" +"\n" +" let layout = Layout::from_size_align(0x100, 0x100).unwrap();\n" +" let bar = allocator\n" +" .alloc_aligned(layout)\n" +" .expect(\"Failed to allocate 0x100 byte MMIO region\");\n" +" println!(\"Allocated 0x100 byte MMIO region at {:#x}\", bar);\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:26 +#, fuzzy +msgid "" +"* PCI BARs always have alignment equal to their size.\n" +"* Run the example with `cargo run` under `src/bare-metal/useful-crates/allocator-example/`. (It won't\n" +" run in the Playground because of the crate dependency.)" +msgstr "" +"* Les PCI BAR ont toujours un alignement égal à leur taille.\n" +"* Exécutez l'exemple avec `cargo run` sous `src/bare-metal/useful-crates/allocator-example/`. (Ce ne sera pas\n" +" exécuter dans le Playground en raison de la dépendance de la caisse.)" + +#: src/bare-metal/useful-crates/tinyvec.md:1 +#, fuzzy +msgid "# `tinyvec`" +msgstr "# `tinyvec`" + +#: src/bare-metal/useful-crates/tinyvec.md:3 +#, fuzzy +msgid "" +"Sometimes you want something which can be resized like a `Vec`, but without heap allocation.\n" +"[`tinyvec`][1] provides this: a vector backed by an array or slice, which could be statically\n" +"allocated or on the stack, which keeps track of how many elements are used and panics if you try to\n" +"use more than are allocated." +msgstr "" +"Parfois, vous voulez quelque chose qui peut être redimensionné comme un `Vec`, mais sans allocation de tas.\n" +"[`tinyvec`][1] fournit ceci : un vecteur soutenu par un tableau ou une tranche, qui pourrait être statiquement\n" +"alloué ou sur la pile, qui garde une trace du nombre d'éléments utilisés et panique si vous essayez de\n" +"utiliser plus que ce qui est alloué." + +#: src/bare-metal/useful-crates/tinyvec.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use tinyvec::{array_vec, ArrayVec};\n" +"\n" +"fn main() {\n" +" let mut numbers: ArrayVec<[u32; 5]> = array_vec!(42, 66);\n" +" println!(\"{numbers:?}\");\n" +" numbers.push(7);\n" +" println!(\"{numbers:?}\");\n" +" numbers.remove(1);\n" +" println!(\"{numbers:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:23 +#, fuzzy +msgid "" +"* `tinyvec` requires that the element type implement `Default` for initialisation.\n" +"* The Rust Playground includes `tinyvec`, so this example will run fine inline." +msgstr "" +"* `tinyvec` nécessite que le type d'élément implémente `Default` pour l'initialisation.\n" +"* Le Rust Playground inclut `tinyvec`, donc cet exemple fonctionnera bien en ligne." + +#: src/bare-metal/useful-crates/spin.md:1 +#, fuzzy +msgid "# `spin`" +msgstr "# `tourner`" + +#: src/bare-metal/useful-crates/spin.md:3 +#, fuzzy +msgid "" +"`std::sync::Mutex` and the other synchronisation primitives from `std::sync` are not available in\n" +"`core` or `alloc`. How can we manage synchronisation or interior mutability, such as for sharing\n" +"state between different CPUs?" +msgstr "" +"`std::sync::Mutex` et les autres primitives de synchronisation de `std::sync` ne sont pas disponibles dans\n" +"`core` ou `alloc`. Comment gérer la synchronisation ou la mutabilité intérieure, comme pour le partage\n" +"état entre différents processeurs ?" + +#: src/bare-metal/useful-crates/spin.md:7 +#, fuzzy +msgid "The [`spin`][1] crate provides spinlock-based equivalents of many of these primitives." +msgstr "Le crate [`spin`][1] fournit des équivalents basés sur des verrous d'attente de plusieurs de ces primitives." + +#: src/bare-metal/useful-crates/spin.md:9 +msgid "" +"```rust,editable,compile_fail\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static counter: SpinMutex = SpinMutex::new(0);\n" +"\n" +"fn main() {\n" +" println!(\"count: {}\", counter.lock());\n" +" *counter.lock() += 2;\n" +" println!(\"count: {}\", counter.lock());\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:23 +msgid "" +"* Be careful to avoid deadlock if you take locks in interrupt handlers.\n" +"* `spin` also has a ticket lock mutex implementation; equivalents of `RwLock`, `Barrier` and `Once`\n" +" from `std::sync`; and `Lazy` for lazy initialisation.\n" +"* The [`once_cell`][2] crate also has some useful types for late initialisation with a slightly\n" +" different approach to `spin::once::Once`.\n" +"* The Rust Playground includes `spin`, so this example will run fine inline." +msgstr "" + +#: src/bare-metal/android.md:3 +#, fuzzy +msgid "" +"To build a bare-metal Rust binary in AOSP, you need to use a `rust_ffi_static` Soong rule to build\n" +"your Rust code, then a `cc_binary` with a linker script to produce the binary itself, and then a\n" +"`raw_binary` to convert the ELF to a raw binary ready to be run." +msgstr "" +"Pour construire un binaire Rust bare-metal dans AOSP, vous devez utiliser une règle Soong `rust_ffi_static` pour construire\n" +"votre code Rust, puis un `cc_binary` avec un script de liaison pour produire le binaire lui-même, puis un\n" +"`raw_binary` pour convertir l'ELF en un binaire brut prêt à être exécuté." + +#: src/bare-metal/android.md:7 +msgid "" +"```soong\n" +"rust_ffi_static {\n" +" name: \"libvmbase_example\",\n" +" defaults: [\"vmbase_ffi_defaults\"],\n" +" crate_name: \"vmbase_example\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libvmbase\",\n" +" ],\n" +"}\n" +"\n" +"cc_binary {\n" +" name: \"vmbase_example\",\n" +" defaults: [\"vmbase_elf_defaults\"],\n" +" srcs: [\n" +" \"idmap.S\",\n" +" ],\n" +" static_libs: [\n" +" \"libvmbase_example\",\n" +" ],\n" +" linker_scripts: [\n" +" \"image.ld\",\n" +" \":vmbase_sections\",\n" +" ],\n" +"}\n" +"\n" +"raw_binary {\n" +" name: \"vmbase_example_bin\",\n" +" stem: \"vmbase_example.bin\",\n" +" src: \":vmbase_example\",\n" +" enabled: false,\n" +" target: {\n" +" android_arm64: {\n" +" enabled: true,\n" +" },\n" +" },\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/android/vmbase.md:1 +#, fuzzy +msgid "# vmbase" +msgstr "# vmbase" + +#: src/bare-metal/android/vmbase.md:3 +#, fuzzy +msgid "" +"For VMs running under crosvm on aarch64, the [vmbase][1] library provides a linker script and useful\n" +"defaults for the build rules, along with an entry point, UART console logging and more." +msgstr "" +"Pour les machines virtuelles exécutées sous crosvm sur aarch64, la bibliothèque [vmbase][1] fournit un script de liaison et des informations " +"utiles.\n" +"valeurs par défaut pour les règles de construction, ainsi qu'un point d'entrée, la journalisation de la console UART et plus encore." + +#: src/bare-metal/android/vmbase.md:6 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use vmbase::{main, println};\n" +"\n" +"main!(main);\n" +"\n" +"pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {\n" +" println!(\"Hello world\");\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/android/vmbase.md:21 +#, fuzzy +msgid "" +"* The `main!` macro marks your main function, to be called from the `vmbase` entry point.\n" +"* The `vmbase` entry point handles console initialisation, and issues a PSCI_SYSTEM_OFF to shutdown\n" +" the VM if your main function returns." +msgstr "" +"* La macro `main!` marque votre fonction principale, à appeler depuis le point d'entrée `vmbase`.\n" +"* Le point d'entrée `vmbase` gère l'initialisation de la console et émet un PSCI_SYSTEM_OFF pour l'arrêt\n" +" la VM si votre fonction principale revient." + +#: src/exercises/bare-metal/afternoon.md:3 +#, fuzzy +msgid "We will write a driver for the PL031 real-time clock device." +msgstr "Nous allons écrire un pilote pour le dispositif d'horloge en temps réel PL031." + +#: src/exercises/bare-metal/rtc.md:1 +#, fuzzy +msgid "# RTC driver" +msgstr "# Pilote RTC" + +#: src/exercises/bare-metal/rtc.md:3 +#, fuzzy +msgid "" +"The QEMU aarch64 virt machine has a [PL031][1] real-time clock at 0x9010000. For this exercise, you\n" +"should write a driver for it and use it to print the current time to the serial console. You can use\n" +"the [`chrono`][2] crate for date/time formatting." +msgstr "" +"La machine QEMU aarch64 virt a une horloge en temps réel [PL031] [1] à 0x9010000. Pour cet exercice, vous\n" +"devrait écrire un pilote pour cela et l'utiliser pour imprimer l'heure actuelle sur la console série. Vous pouvez utiliser\n" +"la caisse [`chrono`][2] pour le formatage de la date/heure." + +#: src/exercises/bare-metal/rtc.md:7 +#, fuzzy +msgid "" +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the `rtc`\n" +"directory for the following files." +msgstr "" +"Téléchargez le [modèle d'exercice] (../../comprehensive-rust-exercises.zip) et regardez dans le `rtc`\n" +"répertoire pour les fichiers suivants." + +#: src/exercises/bare-metal/rtc.md:14 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, LevelFilter};\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"pub const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +"\n" +" // TODO: Initialise RTC and print value.\n" +"\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off().unwrap();\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:52 +#, fuzzy +msgid "`src/exceptions.rs` (you shouldn't need to change this):" +msgstr "`src/exceptions.rs` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/rtc.md:54 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:56 +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" +"use log::error;\n" +"use psci::system_off;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_exception_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_current\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_lower\");\n" +" system_off().unwrap();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:123 +#, fuzzy +msgid "`src/logger.rs` (you shouldn't need to change this):" +msgstr "`src/logger.rs` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/rtc.md:125 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:127 +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: main\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" +" }\n" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:184 +#, fuzzy +msgid "`src/pl011.rs` (you shouldn't need to change this):" +msgstr "`src/pl011.rs` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/rtc.md:186 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:188 +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" +"use core::{\n" +" fmt::{self, Write},\n" +" ptr::{addr_of, addr_of_mut},\n" +"};\n" +"\n" +"// ANCHOR: Flags\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"// ANCHOR_END: Flags\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART Receive Status Register / Error Clear Register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct ReceiveStatus: u16 {\n" +" /// Framing error.\n" +" const FE = 1 << 0;\n" +" /// Parity error.\n" +" const PE = 1 << 1;\n" +" /// Break error.\n" +" const BE = 1 << 2;\n" +" /// Overrun error.\n" +" const OE = 1 << 3;\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Registers\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"// ANCHOR_END: Registers\n" +"\n" +"// ANCHOR: Uart\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of a\n" +" /// PL011 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr).read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" +"}\n" +"// ANCHOR_END: Uart\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:363 +msgid "" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"rtc\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"bitflags = \"2.0.0\"\n" +"chrono = { version = \"0.4.24\", default-features = false }\n" +"log = \"0.4.17\"\n" +"psci = \"0.1.1\"\n" +"spin = \"0.9.8\"\n" +"\n" +"[build-dependencies]\n" +"cc = \"1.0.73\"\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:383 +#, fuzzy +msgid "`build.rs` (you shouldn't need to change this):" +msgstr "`build.rs` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/rtc.md:385 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:387 +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" +"use cc::Build;\n" +"use std::env;\n" +"\n" +"fn main() {\n" +" #[cfg(target_os = \"linux\")]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-linux-gnu\");\n" +" #[cfg(not(target_os = \"linux\"))]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-none-elf\");\n" +"\n" +" Build::new()\n" +" .file(\"entry.S\")\n" +" .file(\"exceptions.S\")\n" +" .file(\"idmap.S\")\n" +" .compile(\"empty\")\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:419 +#, fuzzy +msgid "`entry.S` (you shouldn't need to change this):" +msgstr "`entry.S` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/rtc.md:421 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:423 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".macro adr_l, reg:req, sym:req\n" +"\tadrp \\reg, \\sym\n" +"\tadd \\reg, \\reg, :lo12:\\sym\n" +".endm\n" +"\n" +".macro mov_i, reg:req, imm:req\n" +"\tmovz \\reg, :abs_g3:\\imm\n" +"\tmovk \\reg, :abs_g2_nc:\\imm\n" +"\tmovk \\reg, :abs_g1_nc:\\imm\n" +"\tmovk \\reg, :abs_g0_nc:\\imm\n" +".endm\n" +"\n" +".set .L_MAIR_DEV_nGnRE,\t0x04\n" +".set .L_MAIR_MEM_WBWA,\t0xff\n" +".set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8)\n" +"\n" +"/* 4 KiB granule size for TTBR0_EL1. */\n" +".set .L_TCR_TG0_4KB, 0x0 << 14\n" +"/* 4 KiB granule size for TTBR1_EL1. */\n" +".set .L_TCR_TG1_4KB, 0x2 << 30\n" +"/* Disable translation table walk for TTBR1_EL1, generating a translation fault instead. */\n" +".set .L_TCR_EPD1, 0x1 << 23\n" +"/* Translation table walks for TTBR0_EL1 are inner sharable. */\n" +".set .L_TCR_SH_INNER, 0x3 << 12\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are outer write-back read-allocate write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_OWB, 0x1 << 10\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are inner write-back read-allocate write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_IWB, 0x1 << 8\n" +"/* Size offset for TTBR0_EL1 is 2**39 bytes (512 GiB). */\n" +".set .L_TCR_T0SZ_512, 64 - 39\n" +".set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_TG1_4KB | .L_TCR_EPD1 | .L_TCR_RGN_OWB\n" +".set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | .L_TCR_T0SZ_512\n" +"\n" +"/* Stage 1 instruction access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_I, 0x1 << 12\n" +"/* SP alignment fault if SP is not aligned to a 16 byte boundary. */\n" +".set .L_SCTLR_ELx_SA, 0x1 << 3\n" +"/* Stage 1 data access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_C, 0x1 << 2\n" +"/* EL0 and EL1 stage 1 MMU enabled. */\n" +".set .L_SCTLR_ELx_M, 0x1 << 0\n" +"/* Privileged Access Never is unchanged on taking an exception to EL1. */\n" +".set .L_SCTLR_EL1_SPAN, 0x1 << 23\n" +"/* SETEND instruction disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_SED, 0x1 << 8\n" +"/* Various IT instructions are disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_ITD, 0x1 << 7\n" +".set .L_SCTLR_EL1_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29)\n" +".set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | .L_SCTLR_EL1_ITD | .L_SCTLR_EL1_SED\n" +".set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL1_SPAN | .L_SCTLR_EL1_RES1\n" +"\n" +"/**\n" +" * This is a generic entry point for an image. It carries out the operations required to prepare the\n" +" * loaded image to be run. Specifically, it zeroes the bss section using registers x25 and above,\n" +" * prepares the stack, enables floating point, and sets up the exception vector. It preserves x0-x3\n" +" * for the Rust entry point, as these may contain boot parameters.\n" +" */\n" +".section .init.entry, \"ax\"\n" +".global entry\n" +"entry:\n" +"\t/* Load and apply the memory management configuration, ready to enable MMU and caches. */\n" +"\tadrp x30, idmap\n" +"\tmsr ttbr0_el1, x30\n" +"\n" +"\tmov_i x30, .Lmairval\n" +"\tmsr mair_el1, x30\n" +"\n" +"\tmov_i x30, .Ltcrval\n" +"\t/* Copy the supported PA range into TCR_EL1.IPS. */\n" +"\tmrs x29, id_aa64mmfr0_el1\n" +"\tbfi x30, x29, #32, #4\n" +"\n" +"\tmsr tcr_el1, x30\n" +"\n" +"\tmov_i x30, .Lsctlrval\n" +"\n" +"\t/*\n" +"\t * Ensure everything before this point has completed, then invalidate any potentially stale\n" +"\t * local TLB entries before they start being used.\n" +"\t */\n" +"\tisb\n" +"\ttlbi vmalle1\n" +"\tic iallu\n" +"\tdsb nsh\n" +"\tisb\n" +"\n" +"\t/*\n" +"\t * Configure sctlr_el1 to enable MMU and cache and don't proceed until this has completed.\n" +"\t */\n" +"\tmsr sctlr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Disable trapping floating point access in EL1. */\n" +"\tmrs x30, cpacr_el1\n" +"\torr x30, x30, #(0x3 << 20)\n" +"\tmsr cpacr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Zero out the bss section. */\n" +"\tadr_l x29, bss_begin\n" +"\tadr_l x30, bss_end\n" +"0:\tcmp x29, x30\n" +"\tb.hs 1f\n" +"\tstp xzr, xzr, [x29], #16\n" +"\tb 0b\n" +"\n" +"1:\t/* Prepare the stack. */\n" +"\tadr_l x30, boot_stack_end\n" +"\tmov sp, x30\n" +"\n" +"\t/* Set up exception vector. */\n" +"\tadr x30, vector_table_el1\n" +"\tmsr vbar_el1, x30\n" +"\n" +"\t/* Call into Rust code. */\n" +"\tbl main\n" +"\n" +"\t/* Loop forever waiting for interrupts. */\n" +"2:\twfi\n" +"\tb 2b\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:568 +#, fuzzy +msgid "`exceptions.S` (you shouldn't need to change this):" +msgstr "`exceptions.S` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/rtc.md:570 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:572 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +"/**\n" +" * Saves the volatile registers onto the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers with 18 instructions\n" +" * left.\n" +" *\n" +" * On return, x0 and x1 are initialised to elr_el2 and spsr_el2 respectively,\n" +" * which can be used as the first and second arguments of a subsequent call.\n" +" */\n" +".macro save_volatile_to_stack\n" +"\t/* Reserve stack space and save registers x0-x18, x29 & x30. */\n" +"\tstp x0, x1, [sp, #-(8 * 24)]!\n" +"\tstp x2, x3, [sp, #8 * 2]\n" +"\tstp x4, x5, [sp, #8 * 4]\n" +"\tstp x6, x7, [sp, #8 * 6]\n" +"\tstp x8, x9, [sp, #8 * 8]\n" +"\tstp x10, x11, [sp, #8 * 10]\n" +"\tstp x12, x13, [sp, #8 * 12]\n" +"\tstp x14, x15, [sp, #8 * 14]\n" +"\tstp x16, x17, [sp, #8 * 16]\n" +"\tstr x18, [sp, #8 * 18]\n" +"\tstp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/*\n" +"\t * Save elr_el1 & spsr_el1. This such that we can take nested exception\n" +"\t * and still be able to unwind.\n" +"\t */\n" +"\tmrs x0, elr_el1\n" +"\tmrs x1, spsr_el1\n" +"\tstp x0, x1, [sp, #8 * 22]\n" +".endm\n" +"\n" +"/**\n" +" * Restores the volatile registers from the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers while still leaving 18\n" +" * instructions left; if paired with save_volatile_to_stack, there are 4\n" +" * instructions to spare.\n" +" */\n" +".macro restore_volatile_from_stack\n" +"\t/* Restore registers x2-x18, x29 & x30. */\n" +"\tldp x2, x3, [sp, #8 * 2]\n" +"\tldp x4, x5, [sp, #8 * 4]\n" +"\tldp x6, x7, [sp, #8 * 6]\n" +"\tldp x8, x9, [sp, #8 * 8]\n" +"\tldp x10, x11, [sp, #8 * 10]\n" +"\tldp x12, x13, [sp, #8 * 12]\n" +"\tldp x14, x15, [sp, #8 * 14]\n" +"\tldp x16, x17, [sp, #8 * 16]\n" +"\tldr x18, [sp, #8 * 18]\n" +"\tldp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/* Restore registers elr_el1 & spsr_el1, using x0 & x1 as scratch. */\n" +"\tldp x0, x1, [sp, #8 * 22]\n" +"\tmsr elr_el1, x0\n" +"\tmsr spsr_el1, x1\n" +"\n" +"\t/* Restore x0 & x1, and release stack space. */\n" +"\tldp x0, x1, [sp], #8 * 24\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while using\n" +" * SP0. It behaves similarly to the SPx case by first switching to SPx, doing\n" +" * the work, then switching back to SP0 before returning.\n" +" *\n" +" * Switching to SPx and calling the Rust handler takes 16 instructions. To\n" +" * restore and return we need an additional 16 instructions, so we can implement\n" +" * the whole handler within the allotted 32 instructions.\n" +" */\n" +".macro current_exception_sp0 handler:req\n" +"\tmsr spsel, #1\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\tmsr spsel, #0\n" +"\teret\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while using\n" +" * SPx. It saves volatile registers, calls the Rust handler, restores volatile\n" +" * registers, then returns.\n" +" *\n" +" * This also works for exceptions taken from EL0, if we don't care about\n" +" * non-volatile registers.\n" +" *\n" +" * Saving state and jumping to the Rust handler takes 15 instructions, and\n" +" * restoring and returning also takes 15 instructions, so we can fit the whole\n" +" * handler in 30 instructions, under the limit of 32.\n" +" */\n" +".macro current_exception_spx handler:req\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\teret\n" +".endm\n" +"\n" +".section .text.vector_table_el1, \"ax\"\n" +".global vector_table_el1\n" +".balign 0x800\n" +"vector_table_el1:\n" +"sync_cur_sp0:\n" +"\tcurrent_exception_sp0 sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_sp0:\n" +"\tcurrent_exception_sp0 irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_sp0:\n" +"\tcurrent_exception_sp0 fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_sp0:\n" +"\tcurrent_exception_sp0 serr_current\n" +"\n" +".balign 0x80\n" +"sync_cur_spx:\n" +"\tcurrent_exception_spx sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_spx:\n" +"\tcurrent_exception_spx irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_spx:\n" +"\tcurrent_exception_spx fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_spx:\n" +"\tcurrent_exception_spx serr_current\n" +"\n" +".balign 0x80\n" +"sync_lower_64:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_64:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_64:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_64:\n" +"\tcurrent_exception_spx serr_lower\n" +"\n" +".balign 0x80\n" +"sync_lower_32:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_32:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_32:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_32:\n" +"\tcurrent_exception_spx serr_lower\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:753 +#, fuzzy +msgid "`idmap.S` (you shouldn't need to change this):" +msgstr "`idmap.S` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/rtc.md:755 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:757 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".set .L_TT_TYPE_BLOCK, 0x1\n" +".set .L_TT_TYPE_PAGE, 0x3\n" +".set .L_TT_TYPE_TABLE, 0x3\n" +"\n" +"/* Access flag. */\n" +".set .L_TT_AF, 0x1 << 10\n" +"/* Not global. */\n" +".set .L_TT_NG, 0x1 << 11\n" +".set .L_TT_XN, 0x3 << 53\n" +"\n" +".set .L_TT_MT_DEV, 0x0 << 2\t\t\t// MAIR #0 (DEV_nGnRE)\n" +".set .L_TT_MT_MEM, (0x1 << 2) | (0x3 << 8)\t// MAIR #1 (MEM_WBWA), inner shareable\n" +"\n" +".set .L_BLOCK_DEV, .L_TT_TYPE_BLOCK | .L_TT_MT_DEV | .L_TT_AF | .L_TT_XN\n" +".set .L_BLOCK_MEM, .L_TT_TYPE_BLOCK | .L_TT_MT_MEM | .L_TT_AF | .L_TT_NG\n" +"\n" +".section \".rodata.idmap\", \"a\", %progbits\n" +".global idmap\n" +".align 12\n" +"idmap:\n" +"\t/* level 1 */\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x0\t\t // 1 GiB of device mappings\n" +"\t.quad\t\t.L_BLOCK_MEM | 0x40000000\t// 1 GiB of DRAM\n" +"\t.fill\t\t254, 8, 0x0\t\t\t// 254 GiB of unmapped VA space\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x4000000000 // 1 GiB of device mappings\n" +"\t.fill\t\t255, 8, 0x0\t\t\t// 255 GiB of remaining VA space\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:802 +#, fuzzy +msgid "`image.ld` (you shouldn't need to change this):" +msgstr "`image.ld` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/rtc.md:804 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:806 +msgid "" +"```ld\n" +"/*\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" +" * https://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" +"\n" +"/*\n" +" * Code will start running at this symbol which is placed at the start of the\n" +" * image.\n" +" */\n" +"ENTRY(entry)\n" +"\n" +"MEMORY\n" +"{\n" +"\timage : ORIGIN = 0x40080000, LENGTH = 2M\n" +"}\n" +"\n" +"SECTIONS\n" +"{\n" +"\t/*\n" +"\t * Collect together the code.\n" +"\t */\n" +"\t.init : ALIGN(4096) {\n" +"\t\ttext_begin = .;\n" +"\t\t*(.init.entry)\n" +"\t\t*(.init.*)\n" +"\t} >image\n" +"\t.text : {\n" +"\t\t*(.text.*)\n" +"\t} >image\n" +"\ttext_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together read-only data.\n" +"\t */\n" +"\t.rodata : ALIGN(4096) {\n" +"\t\trodata_begin = .;\n" +"\t\t*(.rodata.*)\n" +"\t} >image\n" +"\t.got : {\n" +"\t\t*(.got)\n" +"\t} >image\n" +"\trodata_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together the read-write data including .bss at the end which\n" +"\t * will be zero'd by the entry code.\n" +"\t */\n" +"\t.data : ALIGN(4096) {\n" +"\t\tdata_begin = .;\n" +"\t\t*(.data.*)\n" +"\t\t/*\n" +"\t\t * The entry point code assumes that .data is a multiple of 32\n" +"\t\t * bytes long.\n" +"\t\t */\n" +"\t\t. = ALIGN(32);\n" +"\t\tdata_end = .;\n" +"\t} >image\n" +"\n" +"\t/* Everything beyond this point will not be included in the binary. */\n" +"\tbin_end = .;\n" +"\n" +"\t/* The entry point code assumes that .bss is 16-byte aligned. */\n" +"\t.bss : ALIGN(16) {\n" +"\t\tbss_begin = .;\n" +"\t\t*(.bss.*)\n" +"\t\t*(COMMON)\n" +"\t\t. = ALIGN(16);\n" +"\t\tbss_end = .;\n" +"\t} >image\n" +"\n" +"\t.stack (NOLOAD) : ALIGN(4096) {\n" +"\t\tboot_stack_begin = .;\n" +"\t\t. += 40 * 4096;\n" +"\t\t. = ALIGN(4096);\n" +"\t\tboot_stack_end = .;\n" +"\t} >image\n" +"\n" +"\t. = ALIGN(4K);\n" +"\tPROVIDE(dma_region = .);\n" +"\n" +"\t/*\n" +"\t * Remove unused sections from the image.\n" +"\t */\n" +"\t/DISCARD/ : {\n" +"\t\t/* The image loads itself so doesn't need these sections. */\n" +"\t\t*(.gnu.hash)\n" +"\t\t*(.hash)\n" +"\t\t*(.interp)\n" +"\t\t*(.eh_frame_hdr)\n" +"\t\t*(.eh_frame)\n" +"\t\t*(.note.gnu.build-id)\n" +"\t}\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:913 +#, fuzzy +msgid "`Makefile` (you shouldn't need to change this):" +msgstr "`Makefile` (vous ne devriez pas avoir besoin de le modifier) :" + +#: src/exercises/bare-metal/rtc.md:915 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:917 +msgid "" +"```makefile\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" +"UNAME := $(shell uname -s)\n" +"ifeq ($(UNAME),Linux)\n" +"\tTARGET = aarch64-linux-gnu\n" +"else\n" +"\tTARGET = aarch64-none-elf\n" +"endif\n" +"OBJCOPY = $(TARGET)-objcopy\n" +"\n" +".PHONY: build qemu_minimal qemu qemu_logger\n" +"\n" +"all: rtc.bin\n" +"\n" +"build:\n" +"\tcargo build\n" +"\n" +"rtc.bin: build\n" +"\t$(OBJCOPY) -O binary target/aarch64-unknown-none/debug/rtc $@\n" +"\n" +"qemu: rtc.bin\n" +"\tqemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s\n" +"\n" +"clean:\n" +"\tcargo clean\n" +"\trm -f *.bin\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:962 +msgid "" +"```toml\n" +"[build]\n" +"target = \"aarch64-unknown-none\"\n" +"rustflags = [\"-C\", \"link-arg=-Timage.ld\"]\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:968 +#, fuzzy +msgid "Run the code in QEMU with `make qemu`." +msgstr "Exécutez le code dans QEMU avec `make qemu`." + +#: src/exercises/solutions.md:1 +#, fuzzy +msgid "# Solutions" +msgstr "# Solutions" + +#: src/exercises/solutions.md:3 +#, fuzzy +msgid "You will find solutions to the exercises on the following pages." +msgstr "Vous trouverez les solutions aux exercices dans les pages suivantes." + +#: src/exercises/solutions.md:5 +#, fuzzy +msgid "" +"Feel free to ask questions about the solutions [on\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Let us know\n" +"if you have a different or better solution than what is presented here." +msgstr "" +"N'hésitez pas à poser des questions sur les solutions [sur\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Faites le nous savoir\n" +"si vous avez une solution différente ou meilleure que celle présentée ici." + +#: src/exercises/solutions.md:10 +#, fuzzy +msgid "" +"> **Note:** Please ignore the `// ANCHOR: label` and `// ANCHOR_END: label`\n" +"> comments you see in the solutions. They are there to make it possible to\n" +"> re-use parts of the solutions as the exercises." +msgstr "" +"> **Remarque :** Veuillez ignorer `// ANCHOR : libellé` et `// ANCHOR_END : libellé`\n" +"> commentaires que vous voyez dans les solutions. Ils sont là pour permettre de\n" +"> réutiliser des parties des solutions comme exercices." + +#: src/exercises/day-1/solutions-morning.md:1 +#, fuzzy +msgid "# Day 1 Morning Exercises" +msgstr "# Exercices du matin du jour 1" + +#: src/exercises/day-1/solutions-morning.md:3 +#, fuzzy +msgid "## Arrays and `for` Loops" +msgstr "## Tableaux et boucles `for`" + +#: src/exercises/day-1/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](for-loops.md))" +msgstr "([retour à l'exercice](for-loops.md))" + +#: src/exercises/day-1/solutions-morning.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: transpose\n" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" // ANCHOR_END: transpose\n" +" let mut result = [[0; 3]; 3];\n" +" for i in 0..3 {\n" +" for j in 0..3 {\n" +" result[j][i] = matrix[i][j];\n" +" }\n" +" }\n" +" return result;\n" +"}\n" +"\n" +"// ANCHOR: pretty_print\n" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" // ANCHOR_END: pretty_print\n" +" for row in matrix {\n" +" println!(\"{row:?}\");\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: tests\n" +"#[test]\n" +"fn test_transpose() {\n" +" let matrix = [\n" +" [101, 102, 103], //\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +" let transposed = transpose(matrix);\n" +" assert_eq!(\n" +" transposed,\n" +" [\n" +" [101, 201, 301], //\n" +" [102, 202, 302],\n" +" [103, 203, 303],\n" +" ]\n" +" );\n" +"}\n" +"// ANCHOR_END: tests\n" +"\n" +"// ANCHOR: main\n" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:78 +#, fuzzy +msgid "### Bonus question" +msgstr "### Question bonus" + +#: src/exercises/day-1/solutions-morning.md:80 +#, fuzzy +msgid "" +"It requires more advanced concepts. It might seem that we could use a slice-of-slices (`&[&[i32]]`) as the input type to transpose and thus make our " +"function handle any size of matrix. However, this quickly breaks down: the return type cannot be `&[&[i32]]` since it needs to own the data you " +"return." +msgstr "" +"Cela nécessite des concepts plus avancés. Il pourrait sembler que nous pourrions utiliser une tranche de tranches (`&[&[i32]]`) comme type d'entrée " +"à transposer et ainsi faire en sorte que notre fonction gère n'importe quelle taille de matrice. Cependant, cela tombe rapidement en panne : le type " +"de retour ne peut pas être `&[&[i32]]` car il doit posséder les données que vous renvoyez." + +#: src/exercises/day-1/solutions-morning.md:82 +#, fuzzy +msgid "" +"You can attempt to use something like `Vec>`, but this doesn't work out-of-the-box either: it's hard to convert from `Vec>` to " +"`&[&[i32]]` so now you cannot easily use `pretty_print` either." +msgstr "" +"Vous pouvez essayer d'utiliser quelque chose comme `Vec>`, mais cela ne fonctionne pas non plus : il est difficile de convertir " +"`Vec>` en `&[ &[i32]]` vous ne pouvez donc plus utiliser facilement `pretty_print` non plus." + +#: src/exercises/day-1/solutions-morning.md:84 +#, fuzzy +msgid "" +"Once we get to traits and generics, we'll be able to use the [`std::convert::AsRef`][1] trait to abstract over anything that can be referenced as a " +"slice." +msgstr "" +"Une fois arrivés aux traits et aux génériques, nous pourrons utiliser le trait [`std::convert::AsRef`][1] pour faire abstraction de tout ce qui peut " +"être référencé en tant que tranche." + +#: src/exercises/day-1/solutions-morning.md:86 +msgid "" +"```rust\n" +"use std::convert::AsRef;\n" +"use std::fmt::Debug;\n" +"\n" +"fn pretty_print(matrix: Matrix)\n" +"where\n" +" T: Debug,\n" +" // A line references a slice of items\n" +" Line: AsRef<[T]>,\n" +" // A matrix references a slice of lines\n" +" Matrix: AsRef<[Line]>\n" +"{\n" +" for row in matrix.as_ref() {\n" +" println!(\"{:?}\", row.as_ref());\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" // &[&[i32]]\n" +" pretty_print(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" +" // [[&str; 2]; 2]\n" +" pretty_print([[\"a\", \"b\"], [\"c\", \"d\"]]);\n" +" // Vec>\n" +" pretty_print(vec![vec![1, 2], vec![3, 4]]);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:113 +#, fuzzy +msgid "In addition, the type itself would not enforce that the child slices are of the same length, so such variable could contain an invalid matrix." +msgstr "" +"De plus, le type lui-même n'imposerait pas que les tranches enfants aient la même longueur, de sorte qu'une telle variable pourrait contenir une " +"matrice non valide." + +#: src/exercises/day-1/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 1 Afternoon Exercises" +msgstr "# Exercices de l'après-midi du jour 1" + +#: src/exercises/day-1/solutions-afternoon.md:3 +#, fuzzy +msgid "## Designing a Library" +msgstr "## Conception d'une bibliothèque" + +#: src/exercises/day-1/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](book-library.md))" +msgstr "([retour à l'exercice](book-library.md))" + +#: src/exercises/day-1/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: setup\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// 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" +"impl Library {\n" +" fn new() -> Library {\n" +" // ANCHOR_END: Library_new\n" +" Library { books: Vec::new() }\n" +" }\n" +"\n" +" // ANCHOR: Library_len\n" +" //fn len(self) -> usize {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_len\n" +" fn len(&self) -> usize {\n" +" self.books.len()\n" +" }\n" +"\n" +" // ANCHOR: Library_is_empty\n" +" //fn is_empty(self) -> bool {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_is_empty\n" +" fn is_empty(&self) -> bool {\n" +" self.books.is_empty()\n" +" }\n" +"\n" +" // ANCHOR: Library_add_book\n" +" //fn add_book(self, book: Book) {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_add_book\n" +" fn add_book(&mut self, book: Book) {\n" +" self.books.push(book)\n" +" }\n" +"\n" +" // ANCHOR: Library_print_books\n" +" //fn print_books(self) {\n" +" // unimplemented!()\n" +" //}\n" +" // ANCHOR_END: Library_print_books\n" +" fn print_books(&self) {\n" +" for book in &self.books {\n" +" println!(\"{}\", book);\n" +" }\n" +" }\n" +"\n" +" // ANCHOR: Library_oldest_book\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // unimplemented!()\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" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();\n" +"\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" +" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\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" +" //}\n" +" //\n" +" //println!(\"Our library has {} books\", library.len());\n" +" for book in library.books {\n" +" println!(\"{book}\");\n" +" }\n" +"}\n" +"// ANCHOR_END: main\n" +"\n" +"#[test]\n" +"fn test_library_len() {\n" +" let mut library = Library::new();\n" +" assert_eq!(library.len(), 0);\n" +" assert!(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" +" assert_eq!(library.len(), 2);\n" +" assert!(!library.is_empty());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_is_empty() {\n" +" let mut library = Library::new();\n" +" assert!(library.is_empty());\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert!(!library.is_empty());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_print_books() {\n" +" let mut library = Library::new();\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" // We could try and capture stdout, but let us just call the\n" +" // method to start with.\n" +" library.print_books();\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_oldest_book() {\n" +" let mut library = Library::new();\n" +" assert!(library.oldest_book().is_none());\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Lord of the Rings\")\n" +" );\n" +"\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Alice's Adventures in Wonderland\")\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:1 +#, fuzzy +msgid "# Day 2 Morning Exercises" +msgstr "# Exercices du matin du jour 2" + +#: src/exercises/day-2/solutions-morning.md:3 +#, fuzzy +msgid "## Points and Polygons" +msgstr "## Points et polygones" + +#: src/exercises/day-2/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](points-polygons.md))" +msgstr "([retour à l'exercice](points-polygones.md))" + +#: src/exercises/day-2/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" +"#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" +"// ANCHOR: Point\n" +"pub struct Point {\n" +" // ANCHOR_END: Point\n" +" x: i32,\n" +" y: i32,\n" +"}\n" +"\n" +"// ANCHOR: Point-impl\n" +"impl Point {\n" +" // ANCHOR_END: Point-impl\n" +" pub fn new(x: i32, y: i32) -> Point {\n" +" Point { x, y }\n" +" }\n" +"\n" +" pub fn magnitude(self) -> f64 {\n" +" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +" }\n" +"\n" +" pub fn dist(self, other: Point) -> f64 {\n" +" (self - other).magnitude()\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x + other.x,\n" +" y: self.y + other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Sub for Point {\n" +" type Output = Self;\n" +"\n" +" fn sub(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x - other.x,\n" +" y: self.y - other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Polygon\n" +"pub struct Polygon {\n" +" // ANCHOR_END: Polygon\n" +" points: Vec,\n" +"}\n" +"\n" +"// ANCHOR: Polygon-impl\n" +"impl Polygon {\n" +" // ANCHOR_END: Polygon-impl\n" +" pub fn new() -> Polygon {\n" +" Polygon { points: Vec::new() }\n" +" }\n" +"\n" +" pub fn add_point(&mut self, point: Point) {\n" +" self.points.push(point);\n" +" }\n" +"\n" +" pub fn left_most_point(&self) -> Option {\n" +" self.points.iter().min_by_key(|p| p.x).copied()\n" +" }\n" +"\n" +" pub fn iter(&self) -> impl Iterator {\n" +" self.points.iter()\n" +" }\n" +"\n" +" pub fn length(&self) -> f64 {\n" +" if self.points.is_empty() {\n" +" return 0.0;\n" +" }\n" +"\n" +" let mut result = 0.0;\n" +" let mut last_point = self.points[0];\n" +" for point in &self.points[1..] {\n" +" result += last_point.dist(*point);\n" +" last_point = *point;\n" +" }\n" +" result += last_point.dist(self.points[0]);\n" +" result\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Circle\n" +"pub struct Circle {\n" +" // ANCHOR_END: Circle\n" +" center: Point,\n" +" radius: i32,\n" +"}\n" +"\n" +"// ANCHOR: Circle-impl\n" +"impl Circle {\n" +" // ANCHOR_END: Circle-impl\n" +" pub fn new(center: Point, radius: i32) -> Circle {\n" +" Circle { center, radius }\n" +" }\n" +"\n" +" pub fn circumference(&self) -> f64 {\n" +" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +" }\n" +"\n" +" pub fn dist(&self, other: &Self) -> f64 {\n" +" self.center.dist(other.center)\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Shape\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"// ANCHOR_END: Shape\n" +"\n" +"impl From for Shape {\n" +" fn from(poly: Polygon) -> Self {\n" +" Shape::Polygon(poly)\n" +" }\n" +"}\n" +"\n" +"impl From for Shape {\n" +" fn from(circle: Circle) -> Self {\n" +" Shape::Circle(circle)\n" +" }\n" +"}\n" +"\n" +"impl Shape {\n" +" pub fn perimeter(&self) -> f64 {\n" +" match self {\n" +" Shape::Polygon(poly) => poly.length(),\n" +" Shape::Circle(circle) => circle.circumference(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 2 Afternoon Exercises" +msgstr "# Exercices de l'après-midi du jour 2" + +#: src/exercises/day-2/solutions-afternoon.md:3 +#, fuzzy +msgid "## Luhn Algorithm" +msgstr "## Algorithme de Luhn" + +#: src/exercises/day-2/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](luhn.md))" +msgstr "([retour à l'exercice](luhn.md))" + +#: src/exercises/day-2/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: luhn\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" // ANCHOR_END: luhn\n" +" let mut digits_seen = 0;\n" +" let mut sum = 0;\n" +" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ').enumerate() {\n" +" match ch.to_digit(10) {\n" +" Some(d) => {\n" +" sum += if i % 2 == 1 {\n" +" let dd = d * 2;\n" +" dd / 10 + dd % 10\n" +" } else {\n" +" d\n" +" };\n" +" digits_seen += 1;\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +"\n" +" if digits_seen < 2 {\n" +" return false;\n" +" }\n" +"\n" +" sum % 10 == 0\n" +"}\n" +"\n" +"fn main() {\n" +" let cc_number = \"1234 5678 1234 5670\";\n" +" println!(\n" +" \"Is {cc_number} a valid credit card number? {}\",\n" +" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" +" );\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:97 +#, fuzzy +msgid "## Strings and Iterators" +msgstr "## Chaînes et itérateurs" + +#: src/exercises/day-2/solutions-afternoon.md:99 +#, fuzzy +msgid "([back to exercise](strings-iterators.md))" +msgstr "([retour à l'exercice](strings-iterators.md))" + +#: src/exercises/day-2/solutions-afternoon.md:101 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: prefix_matches\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" // ANCHOR_END: prefix_matches\n" +" let prefixes = prefix.split('/');\n" +" let request_paths = request_path\n" +" .split('/')\n" +" .map(|p| Some(p))\n" +" .chain(std::iter::once(None));\n" +"\n" +" for (prefix, request_path) in prefixes.zip(request_paths) {\n" +" match request_path {\n" +" Some(request_path) => {\n" +" if (prefix != \"*\") && (prefix != request_path) {\n" +" return false;\n" +" }\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +" true\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:1 +#, fuzzy +msgid "# Day 3 Morning Exercise" +msgstr "# Jour 3 Exercice du matin" + +#: src/exercises/day-3/solutions-morning.md:3 +#, fuzzy +msgid "## A Simple GUI Library" +msgstr "## Une bibliothèque d'interface graphique simple" + +#: src/exercises/day-3/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](simple-gui.md))" +msgstr "([retour à l'exercice](simple-gui.md))" + +#: src/exercises/day-3/solutions-morning.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: setup\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"}\n" +"\n" +"// ANCHOR_END: setup\n" +"\n" +"// ANCHOR: Window-width\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" // ANCHOR_END: Window-width\n" +" std::cmp::max(\n" +" self.title.chars().count(),\n" +" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +" )\n" +" }\n" +"\n" +" // ANCHOR: Window-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Window-draw_into\n" +" let mut inner = String::new();\n" +" for widget in &self.widgets {\n" +" widget.draw_into(&mut inner);\n" +" }\n" +"\n" +" let window_width = self.width();\n" +"\n" +" // TODO: after learning about error handling, you can change\n" +" // draw_into to return Result<(), std::fmt::Error>. Then use\n" +" // the ?-operator here instead of .unwrap().\n" +" writeln!(buffer, \"+-{:- usize {\n" +" // ANCHOR_END: Button-width\n" +" self.label.width() + 8 // add a bit of padding\n" +" }\n" +"\n" +" // ANCHOR: Button-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Button-draw_into\n" +" let width = self.width();\n" +" let mut label = String::new();\n" +" self.label.draw_into(&mut label);\n" +"\n" +" writeln!(buffer, \"+{:- usize {\n" +" // ANCHOR_END: Label-width\n" +" self.label\n" +" .lines()\n" +" .map(|line| line.chars().count())\n" +" .max()\n" +" .unwrap_or(0)\n" +" }\n" +"\n" +" // ANCHOR: Label-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Label-draw_into\n" +" writeln!(buffer, \"{}\", &self.label).unwrap();\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" +"}\n" +"// ANCHOR_END: main\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 3 Afternoon Exercises" +msgstr "# Exercices de l'après-midi du jour 3" + +#: src/exercises/day-3/solutions-afternoon.md:3 +#, fuzzy +msgid "## Safe FFI Wrapper" +msgstr "## Enveloppe FFI sécurisée" + +#: src/exercises/day-3/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](safe-ffi-wrapper.md))" +msgstr "([retour à l'exercice](safe-ffi-wrapper.md))" + +#: src/exercises/day-3/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: ffi\n" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}\n" +"// ANCHOR_END: ffi\n" +"\n" +"// ANCHOR: DirectoryIterator\n" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" // ANCHOR_END: DirectoryIterator\n" +" let path = CString::new(path).map_err(|err| format!(\"Invalid path: {err}\"))?;\n" +" // SAFETY: path.as_ptr() cannot be NULL.\n" +" let dir = unsafe { ffi::opendir(path.as_ptr()) };\n" +" if dir.is_null() {\n" +" Err(format!(\"Could not open {:?}\", path))\n" +" } else {\n" +" Ok(DirectoryIterator { path, dir })\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Iterator\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" // ANCHOR_END: Iterator\n" +" // SAFETY: self.dir is never NULL.\n" +" let dirent = unsafe { ffi::readdir(self.dir) };\n" +" if dirent.is_null() {\n" +" // We have reached the end of the directory.\n" +" return None;\n" +" }\n" +" // SAFETY: dirent is not NULL and dirent.d_name is NUL\n" +" // terminated.\n" +" let d_name = unsafe { CStr::from_ptr((*dirent).d_name.as_ptr()) };\n" +" let os_str = OsStr::from_bytes(d_name.to_bytes());\n" +" Some(os_str.to_owned())\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Drop\n" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" // ANCHOR_END: Drop\n" +" if !self.dir.is_null() {\n" +" // SAFETY: self.dir is not NULL.\n" +" if unsafe { ffi::closedir(self.dir) } != 0 {\n" +" panic!(\"Could not close {:?}\", self.path);\n" +" }\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"// ANCHOR_END: main\n" +"```" +msgstr "" + +#: src/exercises/day-4/solutions-morning.md:1 +#, fuzzy +msgid "# Day 4 Morning Exercise" +msgstr "# Jour 4 Exercice du matin" + +#: src/exercises/day-4/solutions-morning.md:3 +#, fuzzy +msgid "## Dining Philosophers" +msgstr "## Philosophes de la restauration" + +#: src/exercises/day-4/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](dining-philosophers.md))" +msgstr "([retour à l'exercice](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" +"\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/bare-metal/solutions-morning.md:1 +#, fuzzy +msgid "# Bare Metal Rust Morning Exercise" +msgstr "# Exercice du matin sur la rouille du métal nu" + +#: src/exercises/bare-metal/solutions-morning.md:3 +#, fuzzy +msgid "## Compass" +msgstr "## Boussole" + +#: src/exercises/bare-metal/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](compass.md))" +msgstr "([retour à l'exercice](compass.md))" + +#: src/exercises/bare-metal/solutions-morning.md:7 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"// ANCHOR_END: top\n" +"use core::cmp::{max, min};\n" +"use lsm303agr::{AccelOutputDataRate, Lsm303agr, MagOutputDataRate};\n" +"use microbit::{\n" +" display::blocking::Display,\n" +" hal::{\n" +" prelude::*,\n" +" twim::Twim,\n" +" uarte::{Baudrate, Parity, Uarte},\n" +" Timer,\n" +" },\n" +" pac::twim0::frequency::FREQUENCY_A,\n" +" Board,\n" +"};\n" +"\n" +"const COMPASS_SCALE: i32 = 30000;\n" +"const ACCELEROMETER_SCALE: i32 = 700;\n" +"\n" +"// ANCHOR: main\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // ANCHOR_END: main\n" +" writeln!(serial, \"Setting up IMU...\").unwrap();\n" +" let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100);\n" +" let mut imu = Lsm303agr::new_with_i2c(i2c);\n" +" imu.init().unwrap();\n" +" imu.set_mag_odr(MagOutputDataRate::Hz50).unwrap();\n" +" imu.set_accel_odr(AccelOutputDataRate::Hz50).unwrap();\n" +" let mut imu = imu.into_mag_continuous().ok().unwrap();\n" +"\n" +" // Set up display and timer.\n" +" let mut timer = Timer::new(board.TIMER0);\n" +" let mut display = Display::new(board.display_pins);\n" +"\n" +" let mut mode = Mode::Compass;\n" +" let mut button_pressed = false;\n" +"\n" +" // ANCHOR: loop\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // ANCHOR_END: loop\n" +" while !(imu.mag_status().unwrap().xyz_new_data\n" +" && imu.accel_status().unwrap().xyz_new_data)\n" +" {}\n" +" let compass_reading = imu.mag_data().unwrap();\n" +" let accelerometer_reading = imu.accel_data().unwrap();\n" +" writeln!(\n" +" serial,\n" +" \"{},{},{}\\t{},{},{}\",\n" +" compass_reading.x,\n" +" compass_reading.y,\n" +" compass_reading.z,\n" +" accelerometer_reading.x,\n" +" accelerometer_reading.y,\n" +" accelerometer_reading.z,\n" +" )\n" +" .unwrap();\n" +"\n" +" let mut image = [[0; 5]; 5];\n" +" let (x, y) = match mode {\n" +" Mode::Compass => (\n" +" scale(-compass_reading.x, -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize,\n" +" scale(compass_reading.y, -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize,\n" +" ),\n" +" Mode::Accelerometer => (\n" +" scale(\n" +" accelerometer_reading.x,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" scale(\n" +" -accelerometer_reading.y,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" ),\n" +" };\n" +" image[y][x] = 255;\n" +" display.show(&mut timer, image, 100);\n" +"\n" +" // If button A is pressed, switch to the next mode and briefly blink all LEDs on.\n" +" if board.buttons.button_a.is_low().unwrap() {\n" +" if !button_pressed {\n" +" mode = mode.next();\n" +" display.show(&mut timer, [[255; 5]; 5], 200);\n" +" }\n" +" button_pressed = true;\n" +" } else {\n" +" button_pressed = false;\n" +" }\n" +" }\n" +"}\n" +"\n" +"#[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +"enum Mode {\n" +" Compass,\n" +" Accelerometer,\n" +"}\n" +"\n" +"impl Mode {\n" +" fn next(self) -> Self {\n" +" match self {\n" +" Self::Compass => Self::Accelerometer,\n" +" Self::Accelerometer => Self::Compass,\n" +" }\n" +" }\n" +"}\n" +"\n" +"fn scale(value: i32, min_in: i32, max_in: i32, min_out: i32, max_out: i32) -> i32 {\n" +" let range_in = max_in - min_in;\n" +" let range_out = max_out - min_out;\n" +" cap(\n" +" min_out + range_out * (value - min_in) / range_in,\n" +" min_out,\n" +" max_out,\n" +" )\n" +"}\n" +"\n" +"fn cap(value: i32, min_value: i32, max_value: i32) -> i32 {\n" +" max(min_value, min(value, max_value))\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:1 +#, fuzzy +msgid "# Bare Metal Rust Afternoon" +msgstr "# Bare Metal Rust Après-midi" + +#: src/exercises/bare-metal/solutions-afternoon.md:3 +#, fuzzy +msgid "## RTC driver" +msgstr "## Pilote RTC" + +#: src/exercises/bare-metal/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](rtc.md))" +msgstr "([retour à l'exercice](rtc.md))" + +#: src/exercises/bare-metal/solutions-afternoon.md:7 +#, fuzzy +msgid "`main.rs`:" +msgstr "`main.rs` :" + +#: src/exercises/bare-metal/solutions-afternoon.md:9 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"// ANCHOR_END: top\n" +"mod pl031;\n" +"\n" +"use crate::pl031::Rtc;\n" +"use chrono::{TimeZone, Utc};\n" +"// ANCHOR: imports\n" +"use crate::pl011::Uart;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, LevelFilter};\n" +"use psci::system_off;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"pub const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"// ANCHOR_END: imports\n" +"\n" +"/// Base address of the PL031 RTC.\n" +"pub const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;\n" +"\n" +"// ANCHOR: main\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +" // ANCHOR_END: main\n" +"\n" +" // Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 device,\n" +" // and nothing else accesses that address range.\n" +" let rtc = unsafe { Rtc::new(PL031_BASE_ADDRESS) };\n" +" let time = Utc.timestamp_opt(rtc.read().into(), 0).unwrap();\n" +" info!(\"RTC: {time}\");\n" +"\n" +" // ANCHOR: main_end\n" +" system_off().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off().unwrap();\n" +" loop {}\n" +"}\n" +"// ANCHOR_END: main_end\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:79 +#, fuzzy +msgid "`pl031.rs`:" +msgstr "`pl031.rs` :" + +#: src/exercises/bare-metal/solutions-afternoon.md:81 +msgid "" +"```rust\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"use core::ptr::addr_of;\n" +"\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" /// Data register\n" +" dr: u32,\n" +" /// Match register\n" +" mr: u32,\n" +" /// Load register\n" +" lr: u32,\n" +" /// Control register\n" +" cr: u8,\n" +" _reserved0: [u8; 3],\n" +" /// Interrupt Mask Set or Clear register\n" +" imsc: u8,\n" +" _reserved1: [u8; 3],\n" +" /// Raw Interrupt Status\n" +" ris: u8,\n" +" _reserved2: [u8; 3],\n" +" /// Masked Interrupt Status\n" +" mis: u8,\n" +" _reserved3: [u8; 3],\n" +" /// Interrupt Clear Register\n" +" icr: u8,\n" +" _reserved4: [u8; 3],\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"pub struct Rtc {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Rtc {\n" +" /// Constructs a new instance of the RTC driver for a PL031 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of a\n" +" /// PL031 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Reads the current RTC value.\n" +" pub fn read(&self) -> u32 {\n" +" unsafe { addr_of!((*self.registers).dr).read_volatile() }\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Rtc {}\n" +"```" +msgstr "" diff --git a/po/it.po b/po/it.po new file mode 100644 index 0000000..0bc0707 --- /dev/null +++ b/po/it.po @@ -0,0 +1,20304 @@ +msgid "" +msgstr "" +"Project-Id-Version: Comprehensive Rust 🦀\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2023-05-04 19:16+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.2.2\n" + +#: src/SUMMARY.md:3 +msgid "Welcome to Comprehensive Rust 🦀" +msgstr "Benvenuti a Comprehensive Rust 🦀" + +#: src/SUMMARY.md:4 +msgid "Running the Course" +msgstr "Esecuzione del corso" + +#: src/SUMMARY.md:5 +msgid "Course Structure" +msgstr "Struttura del corso" + +#: src/SUMMARY.md:6 +msgid "Keyboard Shortcuts" +msgstr "Tasti rapidi" + +#: src/SUMMARY.md:7 +msgid "Translations" +msgstr "Traduzioni" + +#: src/SUMMARY.md:8 +msgid "Using Cargo" +msgstr "Utilizzo di Cargo" + +#: src/SUMMARY.md:9 +msgid "Rust Ecosystem" +msgstr "Ecosistema di Rust" + +#: src/SUMMARY.md:10 +msgid "Code Samples" +msgstr "Esempi di codice" + +#: src/SUMMARY.md:11 +msgid "Running Cargo Locally" +msgstr "Eseguire Cargo in locale" + +#: src/SUMMARY.md:14 +msgid "Day 1: Morning" +msgstr "Giorno 1: Mattino" + +#: src/SUMMARY.md:18 src/SUMMARY.md:75 src/SUMMARY.md:128 src/SUMMARY.md:184 src/SUMMARY.md:210 src/SUMMARY.md:258 +msgid "Welcome" +msgstr "Benvenuti" + +#: src/SUMMARY.md:19 +msgid "What is Rust?" +msgstr "Cos’è Rust?" + +#: src/SUMMARY.md:20 +msgid "Hello World!" +msgstr "Hello World!" + +#: src/SUMMARY.md:21 +msgid "Small Example" +msgstr "Piccolo esempio" + +#: src/SUMMARY.md:22 +msgid "Why Rust?" +msgstr "Perché Rust?" + +#: src/SUMMARY.md:23 +msgid "Compile Time Guarantees" +msgstr "Garanzie alla Compilazione" + +#: src/SUMMARY.md:24 +msgid "Runtime Guarantees" +msgstr "Garanzie all’Esecuzione" + +#: src/SUMMARY.md:25 +msgid "Modern Features" +msgstr "Funzionalità moderne" + +#: src/SUMMARY.md:26 +msgid "Basic Syntax" +msgstr "Sintassi di base" + +#: src/SUMMARY.md:27 +msgid "Scalar Types" +msgstr "Tipi Scalari" + +#: src/SUMMARY.md:28 +msgid "Compound Types" +msgstr "Tipi Composti" + +#: src/SUMMARY.md:29 +msgid "References" +msgstr "Riferimenti" + +#: src/SUMMARY.md:30 +msgid "Dangling References" +msgstr "Riferimenti pendenti" + +#: src/SUMMARY.md:31 +msgid "Slices" +msgstr "Slice" + +#: src/SUMMARY.md:32 +msgid "String vs str" +msgstr "Differenza tra String e str" + +#: src/SUMMARY.md:33 +msgid "Functions" +msgstr "Funzioni" + +#: src/SUMMARY.md:34 +msgid "Rustdoc" +msgstr "Rustico" + +#: src/SUMMARY.md:35 src/SUMMARY.md:82 +msgid "Methods" +msgstr "Metodi" + +#: src/SUMMARY.md:36 +msgid "Overloading" +msgstr "Overloading" + +#: src/SUMMARY.md:37 src/SUMMARY.md:66 src/SUMMARY.md:90 src/SUMMARY.md:119 src/SUMMARY.md:148 src/SUMMARY.md:176 src/SUMMARY.md:203 src/SUMMARY.md:224 +#: src/SUMMARY.md:250 src/SUMMARY.md:272 src/SUMMARY.md:292 +msgid "Exercises" +msgstr "Esercizi" + +#: src/SUMMARY.md:38 +msgid "Implicit Conversions" +msgstr "Conversione implicita" + +#: src/SUMMARY.md:39 +msgid "Arrays and for Loops" +msgstr "Array e Cicli for" + +#: src/SUMMARY.md:41 +msgid "Day 1: Afternoon" +msgstr "Giorno 1: Pomeriggio" + +#: src/SUMMARY.md:43 +msgid "Variables" +msgstr "Variabili" + +#: src/SUMMARY.md:44 +msgid "Type Inference" +msgstr "Inferenza del Tipo" + +#: src/SUMMARY.md:45 +msgid "static & const" +msgstr "static & const" + +#: src/SUMMARY.md:46 +msgid "Scopes and Shadowing" +msgstr "Scope e Shadowing" + +#: src/SUMMARY.md:47 +msgid "Memory Management" +msgstr "Gestione della Memoria" + +#: src/SUMMARY.md:48 +msgid "Stack vs Heap" +msgstr "Stack vs Heap" + +#: src/SUMMARY.md:49 +msgid "Stack Memory" +msgstr "Memoria sullo Stack" + +#: src/SUMMARY.md:50 +msgid "Manual Memory Management" +msgstr "Gestione manuale della Memoria" + +#: src/SUMMARY.md:51 +msgid "Scope-Based Memory Management" +msgstr "Gestione della Memoria basata su Scope" + +#: src/SUMMARY.md:52 +msgid "Garbage Collection" +msgstr "Garbage Collection" + +#: src/SUMMARY.md:53 +msgid "Rust Memory Management" +msgstr "Gestione della Memoria in Rust" + +#: src/SUMMARY.md:54 +msgid "Comparison" +msgstr "Comparazione" + +#: src/SUMMARY.md:55 +msgid "Ownership" +msgstr "Proprietà" + +#: src/SUMMARY.md:56 +msgid "Move Semantics" +msgstr "Semantica di move" + +#: src/SUMMARY.md:57 +msgid "Moved Strings in Rust" +msgstr "Stringhe a cui è applicata move" + +#: src/SUMMARY.md:58 +msgid "Double Frees in Modern C++" +msgstr "Doppio applicazione di free in C++ moderno" + +#: src/SUMMARY.md:59 +msgid "Moves in Function Calls" +msgstr "Move nelle Chiamate a Funzione" + +#: src/SUMMARY.md:60 +msgid "Copying and Cloning" +msgstr "Copiare (Copy) e Clonare (Clone)" + +#: src/SUMMARY.md:61 +msgid "Borrowing" +msgstr "Prestito (Borrowing)" + +#: src/SUMMARY.md:62 +msgid "Shared and Unique Borrows" +msgstr "Prestito (Borrow) Condiviso (Shared) e Unico (Unique)" + +#: src/SUMMARY.md:63 +msgid "Lifetimes" +msgstr "Lifetime" + +#: src/SUMMARY.md:64 +msgid "Lifetimes in Function Calls" +msgstr "Lifetime in Chiamate a Funzione" + +#: src/SUMMARY.md:65 +msgid "Lifetimes in Data Structures" +msgstr "Lifetime in Strutture Dati" + +#: src/SUMMARY.md:67 +msgid "Designing a Library" +msgstr "Progettare una Libreria" + +#: src/SUMMARY.md:68 +#, fuzzy +msgid "Iterators and Ownership" +msgstr "Iteratori e proprietà" + +#: src/SUMMARY.md:71 +#, fuzzy +msgid "Day 2: Morning" +msgstr "2° giorno: mattina" + +#: src/SUMMARY.md:76 +#, fuzzy +msgid "Structs" +msgstr "Strutture" + +#: src/SUMMARY.md:77 +#, fuzzy +msgid "Tuple Structs" +msgstr "Strutture tuple" + +#: src/SUMMARY.md:78 +#, fuzzy +msgid "Field Shorthand Syntax" +msgstr "Sintassi abbreviata del campo" + +#: src/SUMMARY.md:79 +#, fuzzy +msgid "Enums" +msgstr "Enum" + +#: src/SUMMARY.md:80 +#, fuzzy +msgid "Variant Payloads" +msgstr "Payload varianti" + +#: src/SUMMARY.md:81 +#, fuzzy +msgid "Enum Sizes" +msgstr "Dimensioni enum" + +#: src/SUMMARY.md:83 +#, fuzzy +msgid "Method Receiver" +msgstr "Metodo Ricevitore" + +#: src/SUMMARY.md:84 src/SUMMARY.md:159 src/SUMMARY.md:267 +#, fuzzy +msgid "Example" +msgstr "Esempio" + +#: src/SUMMARY.md:85 +#, fuzzy +msgid "Pattern Matching" +msgstr "Corrispondenza del modello" + +#: src/SUMMARY.md:86 +#, fuzzy +msgid "Destructuring Enums" +msgstr "Enumerazioni destrutturanti" + +#: src/SUMMARY.md:87 +#, fuzzy +msgid "Destructuring Structs" +msgstr "Strutture Destrutturanti" + +#: src/SUMMARY.md:88 +#, fuzzy +msgid "Destructuring Arrays" +msgstr "Array destrutturanti" + +#: src/SUMMARY.md:89 +#, fuzzy +msgid "Match Guards" +msgstr "Partita Guardie" + +#: src/SUMMARY.md:91 +#, fuzzy +msgid "Health Statistics" +msgstr "Statistiche sanitarie" + +#: src/SUMMARY.md:92 +#, fuzzy +msgid "Points and Polygons" +msgstr "Punti e Poligoni" + +#: src/SUMMARY.md:94 +#, fuzzy +msgid "Day 2: Afternoon" +msgstr "2° giorno: pomeriggio" + +#: src/SUMMARY.md:96 src/SUMMARY.md:285 +#, fuzzy +msgid "Control Flow" +msgstr "Flusso di controllo" + +#: src/SUMMARY.md:97 +#, fuzzy +msgid "Blocks" +msgstr "Blocchi" + +#: src/SUMMARY.md:98 +#, fuzzy +msgid "if expressions" +msgstr "se espressioni" + +#: src/SUMMARY.md:99 +#, fuzzy +msgid "if let expressions" +msgstr "se let espressioni" + +#: src/SUMMARY.md:100 +#, fuzzy +msgid "while expressions" +msgstr "mentre le espressioni" + +#: src/SUMMARY.md:101 +#, fuzzy +msgid "while let expressions" +msgstr "mentre lasciate espressioni" + +#: src/SUMMARY.md:102 +#, fuzzy +msgid "for expressions" +msgstr "per le espressioni" + +#: src/SUMMARY.md:103 +#, fuzzy +msgid "loop expressions" +msgstr "espressioni di ciclo" + +#: src/SUMMARY.md:104 +#, fuzzy +msgid "match expressions" +msgstr "corrispondere espressioni" + +#: src/SUMMARY.md:105 +#, fuzzy +msgid "break & continue" +msgstr "interrompere e continuare" + +#: src/SUMMARY.md:106 +#, fuzzy +msgid "Standard Library" +msgstr "Libreria standard" + +#: src/SUMMARY.md:107 +#, fuzzy +msgid "Option and Result" +msgstr "Opzione e Risultato" + +#: src/SUMMARY.md:108 +#, fuzzy +msgid "String" +msgstr "Corda" + +#: src/SUMMARY.md:109 +#, fuzzy +msgid "Vec" +msgstr "Vec" + +#: src/SUMMARY.md:110 +#, fuzzy +msgid "HashMap" +msgstr "Mappa hash" + +#: src/SUMMARY.md:111 +#, fuzzy +msgid "Box" +msgstr "Scatola" + +#: src/SUMMARY.md:112 +#, fuzzy +msgid "Recursive Data Types" +msgstr "Tipi di dati ricorsivi" + +#: src/SUMMARY.md:113 +#, fuzzy +msgid "Niche Optimization" +msgstr "Ottimizzazione di nicchia" + +#: src/SUMMARY.md:114 +#, fuzzy +msgid "Rc" +msgstr "RC" + +#: src/SUMMARY.md:115 +#, fuzzy +msgid "Modules" +msgstr "Moduli" + +#: src/SUMMARY.md:116 +#, fuzzy +msgid "Visibility" +msgstr "Visibilità" + +#: src/SUMMARY.md:117 +#, fuzzy +msgid "Paths" +msgstr "Percorsi" + +#: src/SUMMARY.md:118 +#, fuzzy +msgid "Filesystem Hierarchy" +msgstr "Gerarchia del filesystem" + +#: src/SUMMARY.md:120 +#, fuzzy +msgid "Luhn Algorithm" +msgstr "Algoritmo di Luhn" + +#: src/SUMMARY.md:121 +#, fuzzy +msgid "Strings and Iterators" +msgstr "Stringhe e iteratori" + +#: src/SUMMARY.md:124 +#, fuzzy +msgid "Day 3: Morning" +msgstr "3° giorno: mattina" + +#: src/SUMMARY.md:129 +#, fuzzy +msgid "Generics" +msgstr "Generici" + +#: src/SUMMARY.md:130 +#, fuzzy +msgid "Generic Data Types" +msgstr "Tipi di dati generici" + +#: src/SUMMARY.md:131 +#, fuzzy +msgid "Generic Methods" +msgstr "Metodi generici" + +#: src/SUMMARY.md:132 +#, fuzzy +msgid "Monomorphization" +msgstr "Monomorfizzazione" + +#: src/SUMMARY.md:133 +#, fuzzy +msgid "Traits" +msgstr "Tratti" + +#: src/SUMMARY.md:134 +#, fuzzy +msgid "Trait Objects" +msgstr "Oggetti tratto" + +#: src/SUMMARY.md:135 +#, fuzzy +msgid "Deriving Traits" +msgstr "Tratti derivati" + +#: src/SUMMARY.md:136 +#, fuzzy +msgid "Default Methods" +msgstr "Metodi predefiniti" + +#: src/SUMMARY.md:137 +#, fuzzy +msgid "Trait Bounds" +msgstr "Limiti dei tratti" + +#: src/SUMMARY.md:138 +#, fuzzy +msgid "impl Trait" +msgstr "impl tratto" + +#: src/SUMMARY.md:139 +#, fuzzy +msgid "Important Traits" +msgstr "Tratti importanti" + +#: src/SUMMARY.md:140 +#, fuzzy +msgid "Iterator" +msgstr "Iteratore" + +#: src/SUMMARY.md:141 +#, fuzzy +msgid "FromIterator" +msgstr "FromIterator" + +#: src/SUMMARY.md:142 +#, fuzzy +msgid "From and Into" +msgstr "Da e verso" + +#: src/SUMMARY.md:143 +#, fuzzy +msgid "Read and Write" +msgstr "Leggere e scrivere" + +#: src/SUMMARY.md:144 +#, fuzzy +msgid "Drop" +msgstr "Gocciolare" + +#: src/SUMMARY.md:145 +#, fuzzy +msgid "Default" +msgstr "Predefinito" + +#: src/SUMMARY.md:146 +#, fuzzy +msgid "Operators: Add, Mul, ..." +msgstr "Operatori: Add, Mul, ..." + +#: src/SUMMARY.md:147 +#, fuzzy +msgid "Closures: Fn, FnMut, FnOnce" +msgstr "Chiusure: Fn, FnMut, FnOnce" + +#: src/SUMMARY.md:149 +#, fuzzy +msgid "A Simple GUI Library" +msgstr "Una semplice libreria GUI" + +#: src/SUMMARY.md:151 +#, fuzzy +msgid "Day 3: Afternoon" +msgstr "3° giorno: pomeriggio" + +#: src/SUMMARY.md:153 +#, fuzzy +msgid "Error Handling" +msgstr "Gestione degli errori" + +#: src/SUMMARY.md:154 +#, fuzzy +msgid "Panics" +msgstr "Panico" + +#: src/SUMMARY.md:155 +#, fuzzy +msgid "Catching Stack Unwinding" +msgstr "Cattura Stack Svolgimento" + +#: src/SUMMARY.md:156 +#, fuzzy +msgid "Structured Error Handling" +msgstr "Gestione strutturata degli errori" + +#: src/SUMMARY.md:157 +#, fuzzy +msgid "Propagating Errors with ?" +msgstr "Propagazione degli errori con ?" + +#: src/SUMMARY.md:158 +#, fuzzy +msgid "Converting Error Types" +msgstr "Conversione dei tipi di errore" + +#: src/SUMMARY.md:160 +#, fuzzy +msgid "Deriving Error Enums" +msgstr "Derivazione di enumerazioni di errore" + +#: src/SUMMARY.md:161 +#, fuzzy +msgid "Dynamic Error Types" +msgstr "Tipi di errori dinamici" + +#: src/SUMMARY.md:162 +#, fuzzy +msgid "Adding Context to Errors" +msgstr "Aggiunta di contesto agli errori" + +#: src/SUMMARY.md:163 +#, fuzzy +msgid "Testing" +msgstr "Test" + +#: src/SUMMARY.md:164 +#, fuzzy +msgid "Unit Tests" +msgstr "Test unitari" + +#: src/SUMMARY.md:165 +#, fuzzy +msgid "Test Modules" +msgstr "Moduli di prova" + +#: src/SUMMARY.md:166 +#, fuzzy +msgid "Documentation Tests" +msgstr "Prove di documentazione" + +#: src/SUMMARY.md:167 +#, fuzzy +msgid "Integration Tests" +msgstr "Test di integrazione" + +#: src/SUMMARY.md:168 +#, fuzzy +msgid "Unsafe Rust" +msgstr "Ruggine pericolosa" + +#: src/SUMMARY.md:169 +#, fuzzy +msgid "Dereferencing Raw Pointers" +msgstr "Dereferenziamento dei puntatori grezzi" + +#: src/SUMMARY.md:170 +#, fuzzy +msgid "Mutable Static Variables" +msgstr "Variabili statiche mutabili" + +#: src/SUMMARY.md:171 +#, fuzzy +msgid "Unions" +msgstr "Sindacati" + +#: src/SUMMARY.md:172 +#, fuzzy +msgid "Calling Unsafe Functions" +msgstr "Chiamata di funzioni non sicure" + +#: src/SUMMARY.md:173 +#, fuzzy +msgid "Writing Unsafe Functions" +msgstr "Scrittura di funzioni non sicure" + +#: src/SUMMARY.md:174 +#, fuzzy +msgid "Extern Functions" +msgstr "Funzioni esterne" + +#: src/SUMMARY.md:175 +#, fuzzy +msgid "Implementing Unsafe Traits" +msgstr "Implementazione di tratti non sicuri" + +#: src/SUMMARY.md:177 +#, fuzzy +msgid "Safe FFI Wrapper" +msgstr "Involucro FFI sicuro" + +#: src/SUMMARY.md:180 src/SUMMARY.md:248 +#, fuzzy +msgid "Android" +msgstr "Androide" + +#: src/SUMMARY.md:185 +#, fuzzy +msgid "Setup" +msgstr "Impostare" + +#: src/SUMMARY.md:186 +#, fuzzy +msgid "Build Rules" +msgstr "Regole di costruzione" + +#: src/SUMMARY.md:187 +#, fuzzy +msgid "Binary" +msgstr "Binario" + +#: src/SUMMARY.md:188 +#, fuzzy +msgid "Library" +msgstr "Biblioteca" + +#: src/SUMMARY.md:189 +#, fuzzy +msgid "AIDL" +msgstr "AIDL" + +#: src/SUMMARY.md:190 +#, fuzzy +msgid "Interface" +msgstr "Interfaccia" + +#: src/SUMMARY.md:191 +#, fuzzy +msgid "Implementation" +msgstr "Implementazione" + +#: src/SUMMARY.md:192 +#, fuzzy +msgid "Server" +msgstr "server" + +#: src/SUMMARY.md:193 +#, fuzzy +msgid "Deploy" +msgstr "Distribuisci" + +#: src/SUMMARY.md:194 +#, fuzzy +msgid "Client" +msgstr "Cliente" + +#: src/SUMMARY.md:195 +#, fuzzy +msgid "Changing API" +msgstr "Modifica dell'API" + +#: src/SUMMARY.md:196 src/SUMMARY.md:239 +#, fuzzy +msgid "Logging" +msgstr "Registrazione" + +#: src/SUMMARY.md:197 +#, fuzzy +msgid "Interoperability" +msgstr "Interoperabilità" + +#: src/SUMMARY.md:198 +#, fuzzy +msgid "With C" +msgstr "Con c" + +#: src/SUMMARY.md:199 +#, fuzzy +msgid "Calling C with Bindgen" +msgstr "Chiamare C con Bindgen" + +#: src/SUMMARY.md:200 +#, fuzzy +msgid "Calling Rust from C" +msgstr "Chiamare Rust da C" + +#: src/SUMMARY.md:201 +#, fuzzy +msgid "With C++" +msgstr "Con C++" + +#: src/SUMMARY.md:202 +#, fuzzy +msgid "With Java" +msgstr "Con Java" + +#: src/SUMMARY.md:206 +#, fuzzy +msgid "Bare Metal: Morning" +msgstr "Giorno 1: Mattino" + +#: src/SUMMARY.md:211 +#, fuzzy +msgid "no_std" +msgstr "no_std" + +#: src/SUMMARY.md:212 +#, fuzzy +msgid "A Minimal Example" +msgstr "Un esempio minimo" + +#: src/SUMMARY.md:213 +#, fuzzy +msgid "alloc" +msgstr "alloc" + +#: src/SUMMARY.md:214 +#, fuzzy +msgid "Microcontrollers" +msgstr "Microcontrollori" + +#: src/SUMMARY.md:215 +#, fuzzy +msgid "Raw MMIO" +msgstr "MMIO grezzo" + +#: src/SUMMARY.md:216 +#, fuzzy +msgid "PACs" +msgstr "PAC" + +#: src/SUMMARY.md:217 +#, fuzzy +msgid "HAL Crates" +msgstr "Casse HAL" + +#: src/SUMMARY.md:218 +#, fuzzy +msgid "Board Support Crates" +msgstr "Casse di supporto per schede" + +#: src/SUMMARY.md:219 +#, fuzzy +msgid "The Type State Pattern" +msgstr "Il modello di stato del tipo" + +#: src/SUMMARY.md:220 +#, fuzzy +msgid "embedded-hal" +msgstr "incorporato-hal" + +#: src/SUMMARY.md:221 +#, fuzzy +msgid "probe-rs, cargo-embed" +msgstr "probe-rs, cargo-embed" + +#: src/SUMMARY.md:222 +#, fuzzy +msgid "Debugging" +msgstr "Debug" + +#: src/SUMMARY.md:223 src/SUMMARY.md:241 +#, fuzzy +msgid "Other Projects" +msgstr "Altri progetti" + +#: src/SUMMARY.md:225 +#, fuzzy +msgid "Compass" +msgstr "Bussola" + +#: src/SUMMARY.md:227 +#, fuzzy +msgid "Bare Metal: Afternoon" +msgstr "Giorno 1: Pomeriggio" + +#: src/SUMMARY.md:229 +#, fuzzy +msgid "Application Processors" +msgstr "Processori di applicazioni" + +#: src/SUMMARY.md:230 +#, fuzzy +msgid "Inline Assembly" +msgstr "Assemblaggio in linea" + +#: src/SUMMARY.md:231 +#, fuzzy +msgid "MMIO" +msgstr "MMIO" + +#: src/SUMMARY.md:232 +#, fuzzy +msgid "Let's Write a UART Driver" +msgstr "Scriviamo un driver UART" + +#: src/SUMMARY.md:233 +#, fuzzy +msgid "More Traits" +msgstr "Più tratti" + +#: src/SUMMARY.md:234 +#, fuzzy +msgid "A Better UART Driver" +msgstr "Un driver UART migliore" + +#: src/SUMMARY.md:235 +#, fuzzy +msgid "Bitflags" +msgstr "Bitflag" + +#: src/SUMMARY.md:236 +#, fuzzy +msgid "Multiple Registers" +msgstr "Registri multipli" + +#: src/SUMMARY.md:237 +#, fuzzy +msgid "Driver" +msgstr "Autista" + +#: src/SUMMARY.md:238 src/SUMMARY.md:240 +#, fuzzy +msgid "Using It" +msgstr "Usandolo" + +#: src/SUMMARY.md:242 +#, fuzzy +msgid "Useful Crates" +msgstr "Casse Utili" + +#: src/SUMMARY.md:243 +#, fuzzy +msgid "zerocopy" +msgstr "copia zero" + +#: src/SUMMARY.md:244 +#, fuzzy +msgid "aarch64-paging" +msgstr "aarch64-paginazione" + +#: src/SUMMARY.md:245 +#, fuzzy +msgid "buddy_system_allocator" +msgstr "buddy_system_allocator" + +#: src/SUMMARY.md:246 +#, fuzzy +msgid "tinyvec" +msgstr "tinyvec" + +#: src/SUMMARY.md:247 +#, fuzzy +msgid "spin" +msgstr "rotazione" + +#: src/SUMMARY.md:249 +#, fuzzy +msgid "vmbase" +msgstr "vbase" + +#: src/SUMMARY.md:251 +#, fuzzy +msgid "RTC Driver" +msgstr "Autista RTC" + +#: src/SUMMARY.md:254 +#, fuzzy +msgid "Concurrency: Morning" +msgstr "Concorrenza: mattina" + +#: src/SUMMARY.md:259 +#, fuzzy +msgid "Threads" +msgstr "Discussioni" + +#: src/SUMMARY.md:260 +#, fuzzy +msgid "Scoped Threads" +msgstr "Thread con ambito" + +#: src/SUMMARY.md:261 +#, fuzzy +msgid "Channels" +msgstr "Canali" + +#: src/SUMMARY.md:262 +#, fuzzy +msgid "Unbounded Channels" +msgstr "Canali illimitati" + +#: src/SUMMARY.md:263 +#, fuzzy +msgid "Bounded Channels" +msgstr "Canali delimitati" + +#: src/SUMMARY.md:264 +#, fuzzy +msgid "Shared State" +msgstr "Stato condiviso" + +#: src/SUMMARY.md:265 +#, fuzzy +msgid "Arc" +msgstr "Arco" + +#: src/SUMMARY.md:266 +#, fuzzy +msgid "Mutex" +msgstr "Mutex" + +#: src/SUMMARY.md:268 +#, fuzzy +msgid "Send and Sync" +msgstr "Invia e sincronizza" + +#: src/SUMMARY.md:268 +#, fuzzy +msgid "Send" +msgstr "Inviare" + +#: src/SUMMARY.md:268 +#, fuzzy +msgid "Sync" +msgstr "Sincronizza" + +#: src/SUMMARY.md:271 +#, fuzzy +msgid "Examples" +msgstr "Esempi" + +#: src/SUMMARY.md:273 +#, fuzzy +msgid "Dining Philosophers" +msgstr "Filosofi a tavola" + +#: src/SUMMARY.md:274 +#, fuzzy +msgid "Multi-threaded Link Checker" +msgstr "Verifica link multi-thread" + +#: src/SUMMARY.md:276 +#, fuzzy +msgid "Concurrency: Afternoon" +msgstr "Giorno 1: Pomeriggio" + +#: src/SUMMARY.md:278 +#, fuzzy +msgid "Async Basics" +msgstr "Nozioni di base sull'asincronismo" + +#: src/SUMMARY.md:279 +#, fuzzy +msgid "async/await" +msgstr "asincrono/in attesa" + +#: src/SUMMARY.md:280 +#, fuzzy +msgid "Futures" +msgstr "Futuri" + +#: src/SUMMARY.md:281 +#, fuzzy +msgid "Runtimes" +msgstr "Garanzie all’Esecuzione" + +#: src/SUMMARY.md:282 +#, fuzzy +msgid "Tokio" +msgstr "Tokyo" + +#: src/SUMMARY.md:283 +#, fuzzy +msgid "Tasks" +msgstr "Compiti" + +#: src/SUMMARY.md:284 +#, fuzzy +msgid "Async Channels" +msgstr "Canali asincroni" + +#: src/SUMMARY.md:286 +#, fuzzy +msgid "Join" +msgstr "Giuntura" + +#: src/SUMMARY.md:287 +#, fuzzy +msgid "Select" +msgstr "Selezionare" + +#: src/SUMMARY.md:288 +#, fuzzy +msgid "Pitfalls" +msgstr "Insidie" + +#: src/SUMMARY.md:289 +#, fuzzy +msgid "Blocking the Executor" +msgstr "Blocco dell'esecutore" + +#: src/SUMMARY.md:290 +#, fuzzy +msgid "Pin" +msgstr "Spillo" + +#: src/SUMMARY.md:291 +#, fuzzy +msgid "Async Traits" +msgstr "Tratti asincroni" + +#: src/SUMMARY.md:295 +#, fuzzy +msgid "Final Words" +msgstr "Parole finali" + +#: src/SUMMARY.md:299 +#, fuzzy +msgid "Thanks!" +msgstr "Grazie!" + +#: src/SUMMARY.md:300 +#, fuzzy +msgid "Other Resources" +msgstr "Altre risorse" + +#: src/SUMMARY.md:301 +#, fuzzy +msgid "Credits" +msgstr "Crediti" + +#: src/SUMMARY.md:304 +#, fuzzy +msgid "Solutions" +msgstr "Soluzioni" + +#: src/SUMMARY.md:309 +#, fuzzy +msgid "Day 1 Morning" +msgstr "Giorno 1 Mattina" + +#: src/SUMMARY.md:310 +#, fuzzy +msgid "Day 1 Afternoon" +msgstr "Giorno 1 Pomeriggio" + +#: src/SUMMARY.md:311 +#, fuzzy +msgid "Day 2 Morning" +msgstr "Giorno 2 Mattina" + +#: src/SUMMARY.md:312 +#, fuzzy +msgid "Day 2 Afternoon" +msgstr "Giorno 2 Pomeriggio" + +#: src/SUMMARY.md:313 +#, fuzzy +msgid "Day 3 Morning" +msgstr "Giorno 3 Mattina" + +#: src/SUMMARY.md:314 +#, fuzzy +msgid "Day 3 Afternoon" +msgstr "Giorno 3 Pomeriggio" + +#: src/SUMMARY.md:315 +#, fuzzy +msgid "Bare Metal Rust Morning" +msgstr "Bare Metal Ruggine Mattina" + +#: src/SUMMARY.md:316 +#, fuzzy +msgid "Bare Metal Rust Afternoon" +msgstr "Pomeriggio di ruggine di metallo nudo" + +#: src/SUMMARY.md:317 +#, fuzzy +msgid "Concurrency Morning" +msgstr "Concorrenza Mattina" + +#: src/welcome.md:1 +#, fuzzy +msgid "# Welcome to Comprehensive Rust 🦀" +msgstr "# Benvenuto in Comprehensive Rust 🦀" + +#: src/welcome.md:3 +#, fuzzy +msgid "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" +"google/comprehensive-rust/actions/workflows/build.yml)" +msgstr "" +"[![Crea flusso di lavoro](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)" + +#: src/welcome.md:3 +#, fuzzy +msgid "Build workflow" +msgstr "Crea flusso di lavoro" + +#: src/welcome.md:3 +#, fuzzy +msgid "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" +"google/comprehensive-rust/actions/workflows/build.yml)\n" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)" +msgstr "" +"[![Crea flusso di lavoro](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" +"[![Contributori di GitHub](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs /contributori)" + +#: src/welcome.md:4 +#, fuzzy +msgid "GitHub contributors" +msgstr "Collaboratori di GitHub" + +#: src/welcome.md:4 +#, fuzzy +msgid "" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs/contributors)\n" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers)" +msgstr "" +"[![Contributori di GitHub](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/" +"comprehensive-rust/graphs /contributori)\n" +"[![Stelle di GitHub](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers )" + +#: src/welcome.md:5 +#, fuzzy +msgid "GitHub stars" +msgstr "Stelle di GitHub" + +#: src/welcome.md:5 +#, fuzzy +msgid "" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers)" +msgstr "" +"[![Stelle di GitHub](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +"stargazers )" + +#: src/welcome.md:7 +#, fuzzy +msgid "" +"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 "" +"Questo è un corso Rust di tre giorni sviluppato dal team Android. Il corso copre\n" +"l'intero spettro di Rust, dalla sintassi di base ad argomenti avanzati come i generici\n" +"e gestione degli errori. Include anche contenuti specifici per Android nell'ultimo giorno." + +#: src/welcome.md:11 +#, fuzzy +msgid "" +"The goal of the course is to teach you Rust. We assume you don't know anything\n" +"about Rust and hope to:" +msgstr "" +"L'obiettivo del corso è insegnarti Rust. Partiamo dal presupposto che tu non sappia nulla\n" +"su Rust e spero di:" + +#: src/welcome.md:14 +#, fuzzy +msgid "" +"* Give you a comprehensive understanding of the Rust syntax and language.\n" +"* Enable you to modify existing programs and write new programs in Rust.\n" +"* Show you common Rust idioms." +msgstr "" +"* Fornire una comprensione completa della sintassi e del linguaggio di Rust.\n" +"* Consentono di modificare i programmi esistenti e scrivere nuovi programmi in Rust.\n" +"* Mostra i comuni idiomi di Rust." + +#: src/welcome.md:18 +#, fuzzy +msgid "" +"The first three days show you the fundamentals of Rust. Following this, you're\n" +"invited to dive into one or more spezialized topics:" +msgstr "" +"I primi tre giorni ti mostrano i fondamenti di Rust. A seguito di questo, sei\n" +"invitato ad approfondire uno o più argomenti specialistici:" + +#: src/welcome.md:21 +#, fuzzy +msgid "" +"* [Android](android.md): a half-day course on using Rust for Android platform\n" +" development (AOSP). This includes interoperability wtih 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" +" mutextes) and async/await concurrency (cooperative multitasking using\n" +" futures)." +msgstr "" +"* [Android](android.md): un corso di mezza giornata sull'utilizzo della piattaforma Rust per Android\n" +" sviluppo (AOSP). Ciò include l'interoperabilità con C, C++ e Java.\n" +"* [Bare-metal](bare-metal.md): una lezione di un'intera giornata sull'utilizzo di Rust per bare-metal\n" +" sviluppo (incorporato). Lo sono sia i microcontrollori che i processori applicativi\n" +" coperto.\n" +"* [Concurrency](concurrency.md): una lezione di un'intera giornata sulla concorrenza in Rust. Noi\n" +" coprire sia la concorrenza classica (pianificazione preventiva utilizzando thread e\n" +" mutextes) e async/await concurrency (multitasking cooperativo tramite\n" +" futuri)." + +#: src/welcome.md:32 +#, fuzzy +msgid "## Non-Goals" +msgstr "## Non gol" + +#: src/welcome.md:34 +#, fuzzy +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:" +msgstr "" +"Rust è un linguaggio vasto e non saremo in grado di coprirlo tutto in pochi giorni.\n" +"Alcuni non-obiettivi di questo corso sono:" + +#: src/welcome.md:37 +#, fuzzy +msgid "" +"* 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 "" +"* Scopri come sviluppare macro, per favore vedi [Capitolo 19.5 in Rust\n" +" Libro](https://doc.rust-lang.org/book/ch19-06-macros.html) e [Rust by\n" +" Esempio](https://doc.rust-lang.org/rust-by-example/macros.html) invece." + +#: src/welcome.md:41 +#, fuzzy +msgid "## Assumptions" +msgstr "## Ipotesi" + +#: src/welcome.md:43 +#, fuzzy +msgid "" +"The course assumes that you already know how to program. Rust is a statically\n" +"typed language and we will sometimes make comparisons with C and C++ to better\n" +"explain or contrast the Rust approach." +msgstr "" +"Il corso presuppone che tu sappia già programmare. La ruggine è staticamente\n" +"linguaggio digitato e talvolta faremo confronti migliori con C e C++\n" +"spiegare o contrastare l'approccio di Rust." + +#: src/welcome.md:47 +#, fuzzy +msgid "" +"If you know how to program in a dynamically typed language such as Python or\n" +"JavaScript, then you will be able to follow along just fine too." +msgstr "" +"Se sai come programmare in un linguaggio tipizzato dinamicamente come Python o\n" +"JavaScript, allora sarai anche in grado di seguire bene." + +#: src/welcome.md:50 src/cargo/rust-ecosystem.md:19 src/cargo/code-samples.md:22 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/scalar-types.md:19 src/basic-syntax/compound-types.md:28 +#: 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/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/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: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: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/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 +#: src/bare-metal/microcontrollers/type-state.md:30 src/bare-metal/microcontrollers/embedded-hal.md:17 src/bare-metal/microcontrollers/probe-rs.md:14 +#: src/bare-metal/microcontrollers/debugging.md:25 src/bare-metal/microcontrollers/other-projects.md:16 src/exercises/bare-metal/morning.md:5 +#: src/bare-metal/aps.md:7 src/bare-metal/aps/inline-assembly.md:41 src/bare-metal/aps/mmio.md:7 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: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/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/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 +#, fuzzy +msgid "
" +msgstr "" + +#: src/welcome.md:52 +#, fuzzy +msgid "" +"This is an example of a _speaker note_. We will use these to add additional\n" +"information to the slides. This could be key points which the instructor should\n" +"cover as well as answers to typical questions which come up in class." +msgstr "" +"Questo è un esempio di _nota del relatore_. Useremo questi per aggiungere ulteriori\n" +"informazioni alle diapositive. Questi potrebbero essere punti chiave che l'istruttore dovrebbe\n" +"copertina così come le risposte alle domande tipiche che sorgono in classe." + +#: src/welcome.md:56 src/cargo/rust-ecosystem.md:67 src/cargo/code-samples.md:35 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/scalar-types.md:43 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:41 +#: src/basic-syntax/rustdoc.md:33 src/basic-syntax/methods.md:45 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 src/memory-management/rust.md:18 src/ownership/move-semantics.md:26 +#: 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:104 src/structs.md:41 src/structs/tuple-structs.md:43 src/structs/field-shorthand.md:72 src/enums.md:41 +#: 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: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: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: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:41 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/exercises/day-3/morning.md:11 src/error-handling/result.md:33 +#: 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: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/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 +#: src/bare-metal/microcontrollers/other-projects.md:26 src/exercises/bare-metal/morning.md:11 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: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/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/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 +#, fuzzy +msgid "
" +msgstr "" + +#: src/running-the-course.md:1 +#, fuzzy +msgid "# Running the Course" +msgstr "# Esecuzione del corso" + +#: src/running-the-course.md:3 src/running-the-course/course-structure.md:3 +#, fuzzy +msgid "> This page is for the course instructor." +msgstr "> Questa pagina è per l'istruttore del corso." + +#: src/running-the-course.md:5 +#, fuzzy +msgid "" +"Here is a bit of background information about how we've been running the course\n" +"internally at Google." +msgstr "" +"Ecco alcune informazioni di base su come abbiamo condotto il corso\n" +"internamente a Google." + +#: src/running-the-course.md:8 +#, fuzzy +msgid "Before you run the course, you will want to:" +msgstr "Prima di eseguire il corso, vorrai:" + +#: 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" +" notes!). When presenting, you should make sure to open the speaker notes in a\n" +" 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 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" +" 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" +" In particular, you will be doing a lot of live-coding as an instructor, so a lectern won't\n" +" be very helpful for you.\n" +"\n" +"1. On the day of your course, show up to the room a little early to set things\n" +" up. We recommend presenting directly using `mdbook serve` running on your\n" +" laptop (see the [installation instructions][3]). This ensures optimal performance with no lag as you change pages.\n" +" 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" +" 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." +msgstr "" +"1. Acquisisci familiarità con il materiale del corso. Abbiamo incluso le note del relatore\n" +" per aiutare a evidenziare i punti chiave (per favore aiutateci contribuendo con più relatori\n" +" Appunti!). Durante la presentazione, assicurati di aprire le note del relatore in formato a\n" +" popup (fare clic sul collegamento con una piccola freccia accanto a \"Note del relatore\"). Da questa parte\n" +" hai uno schermo pulito da presentare alla classe.\n" +"\n" +"1. Seleziona il tuo argomento per il pomeriggio del quarto giorno. Questo può essere basato su\n" +" il pubblico che ti aspetti o sulla tua esperienza.\n" +"\n" +"1. Decidi le date. Poiché il corso è grande, ti consigliamo di farlo\n" +" programmare i giorni su due settimane. Lo hanno detto i partecipanti al corso\n" +" trovano utile avere una pausa nel corso poiché li aiuta a elaborare\n" +" tutte le informazioni che diamo loro.\n" +"\n" +"1. Trova una stanza abbastanza grande per i tuoi partecipanti di persona. Consigliamo un\n" +" dimensione della classe di 15-20 persone. È abbastanza piccolo da permettere alle persone di sentirsi a proprio agio\n" +" fare domande --- è anche abbastanza piccolo che un istruttore avrà\n" +" tempo per rispondere alle domande. Assicurati che la stanza abbia _scrivanie_ per te e per il\n" +" studenti: dovrete essere tutti in grado di sedervi e lavorare con i vostri laptop.\n" +" In particolare, eseguirai molto codice dal vivo come istruttore, quindi un leggio no\n" +" essere molto utile per te.\n" +"\n" +"1. Il giorno del corso, presentati in aula un po' prima per sistemare le cose\n" +" su. Ti consigliamo di presentare direttamente utilizzando `mdbook serve` in esecuzione sul tuo\n" +" laptop (vedere le [istruzioni di installazione][3]). Ciò garantisce prestazioni ottimali senza ritardi quando si cambiano le pagine.\n" +" L'uso del tuo laptop ti consentirà anche di correggere errori di battitura come te o il corso\n" +" i partecipanti li individuano.\n" +"\n" +"1. Lascia che le persone risolvano gli esercizi da sole o in piccoli gruppi. Assicurati che\n" +" chiedi alle persone se sono bloccate o se c'è qualcosa in cui puoi aiutarle. Quando\n" +" vedi che diverse persone hanno lo stesso problema, segnalalo alla classe\n" +" e offrire una soluzione, ad esempio mostrando alle persone dove trovare le informazioni pertinenti\n" +" informazioni nella libreria standard." + +#: src/running-the-course.md:44 +#, fuzzy +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!" +msgstr "" +"Questo è tutto, buona fortuna con il corso! Speriamo che sarà altrettanto divertente per\n" +"te come lo è stato per noi!" + +#: src/running-the-course.md:47 +#, fuzzy +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" +"better. Your students are also very welcome to [send us feedback][2]!" +msgstr "" +"Si prega di [fornire feedback][1] in seguito in modo che possiamo continuare a migliorare il\n" +"corso. Ci piacerebbe sapere cosa ha funzionato bene per te e cosa si può fare\n" +"Meglio. Anche i tuoi studenti sono i benvenuti a [inviarci feedback][2]!" + +#: src/running-the-course/course-structure.md:1 +#, fuzzy +msgid "# Course Structure" +msgstr "# Struttura del corso" + +#: src/running-the-course/course-structure.md:5 +#, fuzzy +msgid "The course is fast paced and covers a lot of ground:" +msgstr "Il corso è veloce e copre un sacco di terreno:" + +#: src/running-the-course/course-structure.md:7 +#, fuzzy +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." +msgstr "" +"* Giorno 1: Basic Rust, proprietà e controllo del prestito.\n" +"* Giorno 2: tipi di dati composti, pattern matching, libreria standard.\n" +"* Giorno 3: Tratti e generici, gestione degli errori, test, Rust non sicuro." + +#: src/running-the-course/course-structure.md:11 +#, fuzzy +msgid "## Deep Dives" +msgstr "## Immersioni profonde" + +#: src/running-the-course/course-structure.md:13 +#, fuzzy +msgid "" +"In addition to the 3-day class on Rust Fundamentals, we cover some more\n" +"specialized topics:" +msgstr "" +"Oltre alla lezione di 3 giorni sui fondamenti della ruggine, ne copriamo altri\n" +"argomenti specialistici:" + +#: src/running-the-course/course-structure.md:16 +#, fuzzy +msgid "### Android" +msgstr "###Android" + +#: src/running-the-course/course-structure.md:18 +#, fuzzy +msgid "" +"The [Android Deep Dive](../android.md) is a half-day course on using Rust for\n" +"Android platform development. This includes interoperability wtih C, C++, and\n" +"Java." +msgstr "" +"L'[Android Deep Dive](../android.md) è un corso di mezza giornata sull'utilizzo di Rust per\n" +"Sviluppo della piattaforma Android. Ciò include l'interoperabilità con C, C++ e\n" +"Giava." + +#: src/running-the-course/course-structure.md:22 +#, fuzzy +msgid "" +"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 "" +"Avrai bisogno di un [checkout AOSP][1]. Fai un checkout del [corso\n" +"repository][2] sulla stessa macchina e sposta la directory `src/android/` in\n" +"la radice del tuo checkout AOSP. Ciò garantirà che il sistema di compilazione Android\n" +"vede i file `Android.bp` in `src/android/`." + +#: src/running-the-course/course-structure.md:27 +#, fuzzy +msgid "" +"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 "" +"Assicurati che `adb sync` funzioni con il tuo emulatore o dispositivo reale e precompila tutto\n" +"Esempi di Android che utilizzano `src/android/build_all.sh`. Leggi lo script per vedere il file\n" +"comandi che esegue e assicurati che funzionino quando li esegui a mano." + +#: src/running-the-course/course-structure.md:34 +#, fuzzy +msgid "### Bare-Metal" +msgstr "### Metallo nudo" + +#: src/running-the-course/course-structure.md:36 +#, fuzzy +msgid "" +"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 "" +"The [Bare-Metal Deep Dive](../bare-metal.md): una lezione di un'intera giornata sull'uso di Rust per\n" +"sviluppo bare metal (incorporato). Sia i microcontrollori che l'applicazione\n" +"i processori sono coperti." + +#: src/running-the-course/course-structure.md:40 +#, fuzzy +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 "" +"Per la parte del microcontrollore, dovrai acquistare il [BBC\n" +"micro:bit](https://microbit.org/) scheda di sviluppo v2 in anticipo. Tutti\n" +"dovrà installare un certo numero di pacchetti come descritto nel file [welcome\n" +"page](../bare-metal.md)." + +#: src/running-the-course/course-structure.md:45 +#, fuzzy +msgid "### Concurrency" +msgstr "### Concorrenza" + +#: src/running-the-course/course-structure.md:47 +#, fuzzy +msgid "" +"The [Concurrency Deep Dive](../concurrency.md) is a full day class on classical\n" +"as well as `async`/`await` concurrency." +msgstr "" +"Il [Concurrency Deep Dive](../concurrency.md) è un corso di un'intera giornata sulla musica classica\n" +"così come la concorrenza `async`/`await`." + +#: src/running-the-course/course-structure.md:50 +#, fuzzy +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 "" +"Avrai bisogno di una nuova configurazione della cassa e delle dipendenze scaricate e pronte per\n" +"andare. Puoi quindi copiare/incollare gli esempi in `src/main.rs` per sperimentare\n" +"loro:" + +#: src/running-the-course/course-structure.md:54 +msgid "" +"```shell\n" +"cargo init concurrency\n" +"cd concurrency\n" +"cargo add tokio --features full\n" +"cargo run\n" +"```" +msgstr "" + +#: src/running-the-course/course-structure.md:61 +#, fuzzy +msgid "## Format" +msgstr "## Formato" + +#: src/running-the-course/course-structure.md:63 +#, fuzzy +msgid "" +"The course is meant to be very interactive and we recommend letting the\n" +"questions drive the exploration of Rust!" +msgstr "" +"Il corso è pensato per essere molto interattivo e si consiglia di lasciare il\n" +"le domande guidano l'esplorazione di Rust!" + +#: src/running-the-course/keyboard-shortcuts.md:1 +#, fuzzy +msgid "# Keyboard Shortcuts" +msgstr "# Tasti rapidi" + +#: src/running-the-course/keyboard-shortcuts.md:3 +#, fuzzy +msgid "There are several useful keyboard shortcuts in mdBook:" +msgstr "Ci sono diverse utili scorciatoie da tastiera in mdBook:" + +#: src/running-the-course/keyboard-shortcuts.md:5 +#, fuzzy +msgid "" +"* Arrow-Left: Navigate to the previous page.\n" +"* Arrow-Right: Navigate to the next page.\n" +"* Ctrl + Enter: Execute the code sample that has focus.\n" +"* s: Activate the search bar." +msgstr "" +"* Freccia-sinistra: passa alla pagina precedente.\n" +"* Freccia-destra: passa alla pagina successiva.\n" +"* Ctrl + Invio: esegue l'esempio di codice attivo.\n" +"* s: attiva la barra di ricerca." + +#: src/running-the-course/translations.md:1 +#, fuzzy +msgid "# Translations" +msgstr "# Traduzioni" + +#: src/running-the-course/translations.md:3 +#, fuzzy +msgid "" +"The course has been translated into other languages by a set of wonderful\n" +"volunteers:" +msgstr "" +"Il corso è stato tradotto in altre lingue da una serie di meravigliosi\n" +"volontari:" + +#: src/running-the-course/translations.md:6 +#, fuzzy +msgid "" +"* [Brazilian Portuguese][pt-BR] by [@rastringer] and [@hugojacob].\n" +"* [Korean][ko] by [@keispace], [@jiyongp] and [@jooyunghan]." +msgstr "" +"* [Portoghese brasiliano][pt-BR] di [@rastringer] e [@hugojacob].\n" +"* [Coreano][ko] di [@keispace], [@jiyongp] e [@jooyunghan]." + +#: src/running-the-course/translations.md:9 +#, fuzzy +msgid "Use the language picker in the top-right corner to switch between languages." +msgstr "Usa il selettore di lingua nell'angolo in alto a destra per passare da una lingua all'altra." + +#: src/running-the-course/translations.md:11 +#, fuzzy +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]." +msgstr "" +"Se vuoi aiutare con questo sforzo, consulta [le nostre istruzioni] per sapere come farlo\n" +"andare avanti. Le traduzioni sono coordinate su [issue tracker]." + +#: src/cargo.md:1 +#, fuzzy +msgid "# Using Cargo" +msgstr "# Utilizzo del carico" + +#: src/cargo.md:3 +#, fuzzy +msgid "" +"When you start reading about Rust, you will soon meet [Cargo](https://doc.rust-lang.org/cargo/), the standard tool\n" +"used in the Rust ecosystem to build and run Rust applications. Here we want to\n" +"give a brief overview of what Cargo is and how it fits into the wider ecosystem\n" +"and how it fits into this training." +msgstr "" +"Quando inizi a leggere di Rust, incontrerai presto [Cargo](https://doc.rust-lang.org/cargo/), lo strumento standard\n" +"utilizzato nell'ecosistema Rust per creare ed eseguire applicazioni Rust. Qui vogliamo\n" +"fornire una breve panoramica di cos'è Cargo e di come si inserisce nell'ecosistema più ampio\n" +"e come si inserisce in questa formazione." + +#: src/cargo.md:8 +#, fuzzy +msgid "## Installation" +msgstr "## Installazione" + +#: src/cargo.md:10 +#, fuzzy +msgid "### Rustup (Recommended)" +msgstr "### Rustup (consigliato)" + +#: src/cargo.md:12 +#, fuzzy +msgid "" +"You can follow the instructions to install cargo and rust compiler, among other standard ecosystem tools with the [rustup][3] tool, which is " +"maintained by the Rust Foundation." +msgstr "" +"Puoi seguire le istruzioni per installare il compilatore cargo e rust, tra gli altri strumenti standard dell'ecosistema con lo strumento [rustup]" +"[3], gestito dalla Rust Foundation." + +#: src/cargo.md:14 +#, fuzzy +msgid "" +"Along with cargo and rustc, Rustup will install itself as a command line utility that you can use to install/switch toolchains, setup cross " +"compilation, etc." +msgstr "" +"Insieme a cargo e rustc, Rustup si installerà come un'utilità della riga di comando che puoi utilizzare per installare/cambiare toolchain, " +"configurare la compilazione incrociata, ecc." + +#: src/cargo.md:16 +#, fuzzy +msgid "### Package Managers" +msgstr "### Gestori di pacchetti" + +#: src/cargo.md:18 +#, fuzzy +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 "Su Debian/Ubuntu, puoi installare Cargo, il sorgente Rust e il [Rust formatter][6] con" + +#: src/cargo.md:22 +msgid "" +"```shell\n" +"$ sudo apt install cargo rust-src rustfmt\n" +"```" +msgstr "" + +#: src/cargo.md:26 +#, fuzzy +msgid "" +"This will allow [rust-analyzer][1] to jump to the definitions. We suggest using\n" +"[VS Code][2] to edit the code (but any LSP compatible editor works)." +msgstr "" +"Ciò consentirà a [rust-analyzer][1] di saltare alle definizioni. Si consiglia di utilizzare\n" +"[VS Code][2] per modificare il codice (ma qualsiasi editor compatibile con LSP funziona)." + +#: src/cargo.md:29 +#, fuzzy +msgid "" +"Some folks also like to use the [JetBrains][4] family of IDEs, which do their own analysis but have their own tradeoffs. If you prefer them, you can " +"install the [Rust Plugin][5]. Please take note that as of January 2023 debugging only works on the CLion version of the JetBrains IDEA suite." +msgstr "" +"Ad alcune persone piace anche usare la famiglia di IDE [JetBrains][4], che eseguono le proprie analisi ma hanno i propri compromessi. Se li " +"preferisci, puoi installare il [Rust Plugin][5]. Tieni presente che a partire da gennaio 2023 il debug funziona solo sulla versione CLion della " +"suite JetBrains IDEA." + +#: src/cargo/rust-ecosystem.md:1 +#, fuzzy +msgid "# The Rust Ecosystem" +msgstr "# L'ecosistema della ruggine" + +#: src/cargo/rust-ecosystem.md:3 +#, fuzzy +msgid "The Rust ecosystem consists of a number of tools, of which the main ones are:" +msgstr "L'ecosistema Rust è costituito da una serie di strumenti, di cui i principali sono:" + +#: src/cargo/rust-ecosystem.md:5 +#, fuzzy +msgid "" +"* `rustc`: the Rust compiler which turns `.rs` files into binaries and other\n" +" intermediate formats.\n" +"\n" +"* `cargo`: the Rust dependency manager and build tool. Cargo knows how to\n" +" download dependencies hosted on and it will pass them to\n" +" `rustc` when building your project. Cargo also comes with a built-in test\n" +" runner which is used to execute unit tests.\n" +"\n" +"* `rustup`: the Rust toolchain installer and updater. This tool is used to\n" +" install and update `rustc` and `cargo` when new versions of Rust is released.\n" +" In addition, `rustup` can also download documentation for the standard\n" +" library. You can have multiple versions of Rust installed at once and `rustup`\n" +" will let you switch between them as needed." +msgstr "" +"* `rustc`: il compilatore Rust che trasforma i file `.rs` in binari e altro\n" +" formati intermedi.\n" +"\n" +"* `cargo`: il gestore delle dipendenze di Rust e lo strumento di compilazione. Il carico sa come\n" +" scarica le dipendenze ospitate su e le passerà a\n" +" `rustc` quando costruisci il tuo progetto. Cargo include anche un test integrato\n" +" runner che viene utilizzato per eseguire unit test.\n" +"\n" +"* `rustup`: il programma di installazione e aggiornamento della toolchain di Rust. Questo strumento è utilizzato per\n" +" installare e aggiornare `rustc` e `cargo` quando vengono rilasciate nuove versioni di Rust.\n" +" Inoltre, `rustup` può anche scaricare la documentazione per lo standard\n" +" biblioteca. Puoi avere più versioni di Rust installate contemporaneamente e `rustup`\n" +" ti permetterà di passare da uno all'altro secondo necessità." + +#: 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:48 +#: src/error-handling/converting-error-types-example.md:50 src/concurrency/threads.md:30 src/async/async-await.md:25 +#, fuzzy +msgid "Key points:" +msgstr "Punti chiave:" + +#: src/cargo/rust-ecosystem.md:23 +#, fuzzy +msgid "" +"* Rust has a rapid release schedule with a new release coming out\n" +" every six weeks. New releases maintain backwards compatibility with\n" +" old releases --- plus they enable new functionality.\n" +"\n" +"* There are three release channels: \"stable\", \"beta\", and \"nightly\".\n" +"\n" +"* New features are being tested on \"nightly\", \"beta\" is what becomes\n" +" \"stable\" every six weeks.\n" +"\n" +"* Rust also has [editions]: the current edition is Rust 2021. Previous\n" +" editions were Rust 2015 and Rust 2018.\n" +"\n" +" * The editions are allowed to make backwards incompatible changes to\n" +" the language.\n" +"\n" +" * To prevent breaking code, editions are opt-in: you select the\n" +" edition for your crate via the `Cargo.toml` file.\n" +"\n" +" * To avoid splitting the ecosystem, Rust compilers can mix code\n" +" written for different editions.\n" +"\n" +" * Mention that it is quite rare to ever use the compiler directly not through `cargo` (most users never do).\n" +"\n" +" * It might be worth alluding that Cargo itself is an extremely powerful and comprehensive tool. It is capable of many advanced features including " +"but not limited to: \n" +" * Project/package structure\n" +" * [workspaces]\n" +" * Dev Dependencies and Runtime Dependency management/caching\n" +" * [build scripting]\n" +" * [global installation]\n" +" * It is also extensible with sub command plugins as well (such as [cargo clippy]).\n" +" * Read more from the [official Cargo Book]" +msgstr "" +"* Rust ha un programma di rilascio rapido con una nuova versione in uscita\n" +" ogni sei settimane. Le nuove versioni mantengono la retrocompatibilità con\n" +" vecchie versioni --- in più abilitano nuove funzionalità.\n" +"\n" +"* Esistono tre canali di rilascio: \"stable\", \"beta\" e \"nightly\".\n" +"\n" +"* Le nuove funzionalità vengono testate su \"nightly\", \"beta\" è ciò che diventa\n" +" \"stabile\" ogni sei settimane.\n" +"\n" +"* Rust ha anche [edizioni]: l'edizione attuale è Rust 2021. Precedente\n" +" le edizioni erano Rust 2015 e Rust 2018.\n" +"\n" +" * Le edizioni possono apportare modifiche incompatibili con le versioni precedenti\n" +" la lingua.\n" +"\n" +" * Per evitare di violare il codice, le edizioni sono opt-in: selezioni il file\n" +" edizione per la tua cassa tramite il file `Cargo.toml`.\n" +"\n" +" * Per evitare di dividere l'ecosistema, i compilatori di Rust possono mescolare il codice\n" +" scritto per diverse edizioni.\n" +"\n" +" * Menziona che è abbastanza raro usare il compilatore direttamente non attraverso `cargo` (la maggior parte degli utenti non lo fa mai).\n" +"\n" +" * Potrebbe valere la pena accennare al fatto che Cargo stesso è uno strumento estremamente potente e completo. È in grado di offrire molte " +"funzionalità avanzate, tra cui, a titolo esemplificativo ma non esaustivo:\n" +" * Struttura del progetto/pacchetto\n" +" * [aree di lavoro]\n" +" * Dipendenze di sviluppo e gestione/memorizzazione nella cache delle dipendenze di runtime\n" +" * [costruisci script]\n" +" * [installazione globale]\n" +" * È anche estensibile anche con plug-in di comandi secondari (come [cargo clippy]).\n" +" * Leggi di più dal [libro ufficiale dei carichi]" + +#: src/cargo/code-samples.md:1 +#, fuzzy +msgid "# Code Samples in This Training" +msgstr "# Esempi di codice in questa formazione" + +#: 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" +"ensures a consistent experience for everyone." +msgstr "" +"Per questa formazione, esploreremo principalmente il linguaggio Rust attraverso esempi\n" +"che può essere eseguito tramite il tuo browser. Questo rende la configurazione molto più semplice e\n" +"garantisce un'esperienza coerente per tutti." + +#: 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 "" +"L'installazione di Cargo è ancora incoraggiata: ti renderà più facile fare il\n" +"esercizi. L'ultimo giorno faremo un esercizio più ampio che ti mostrerà come farlo\n" +"lavora con le dipendenze e per questo hai bisogno di Cargo." + +#: src/cargo/code-samples.md:11 +#, fuzzy +msgid "The code blocks in this course are fully interactive:" +msgstr "I blocchi di codice in questo corso sono completamente interattivi:" + +#: src/cargo/code-samples.md:13 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" println!(\"Edit me!\");\n" +"}\n" +"```" +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 "" +"Puoi usare Ctrl + Invio per eseguire il codice quando il focus è in\n" +"casella di testo." + +#: 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:" +msgstr "" +"La maggior parte degli esempi di codice sono modificabili come mostrato sopra. Alcuni esempi di codice\n" +"non sono modificabili per vari motivi:" + +#: 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" +"\n" +"* The embedded playgrounds lose their state the moment you navigate\n" +" away from the page! This is the reason that the students should\n" +" solve the exercises using a local Rust installation or via the\n" +" Playground." +msgstr "" +"* I playground incorporati non possono eseguire unit test. Copia e incolla il file\n" +" code e aprilo nel Playground reale per dimostrare i test unitari.\n" +"\n" +"* I playground incorporati perdono il loro stato nel momento in cui navighi\n" +" via dalla pagina! Questo è il motivo per cui gli studenti dovrebbero\n" +" risolvere gli esercizi utilizzando un'installazione locale di Rust o tramite il\n" +" Terreno di gioco." + +#: src/cargo/running-locally.md:1 +#, fuzzy +msgid "# Running Code Locally with Cargo" +msgstr "# Esecuzione del codice in locale con Cargo" + +#: 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 "" +"Se vuoi sperimentare il codice sul tuo sistema, avrai bisogno di\n" +"per installare prima Rust. Fallo seguendo le [istruzioni nel file Rust\n" +"Libro][1]. Questo dovrebbe darti un `rustc` e un `cargo` funzionanti. Al tempo di\n" +"scrivendo, l'ultima versione stabile di Rust ha questi numeri di versione:" + +#: src/cargo/running-locally.md:8 +msgid "" +"```shell\n" +"% rustc --version\n" +"rustc 1.61.0 (fe5b13d68 2022-05-18)\n" +"% cargo --version\n" +"cargo 1.61.0 (a028ae4 2022-04-29)\n" +"```" +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" +"of the examples in this training:" +msgstr "" +"Con questo è a posto, segui questi passaggi per creare un binario Rust da uno\n" +"degli esempi in questa formazione:" + +#: src/cargo/running-locally.md:18 +msgid "" +"1. Click the \"Copy to clipboard\" button on the example you want to copy.\n" +"\n" +"2. Use `cargo new exercise` to create a new `exercise/` directory for your code:\n" +"\n" +" ```shell\n" +" $ cargo new exercise\n" +" Created binary (application) `exercise` package\n" +" ```\n" +"\n" +"3. Navigate into `exercise/` and use `cargo run` to build and run your binary:\n" +"\n" +" ```shell\n" +" $ cd exercise\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +" Running `target/debug/exercise`\n" +" Hello, world!\n" +" ```\n" +"\n" +"4. Replace the boiler-plate code in `src/main.rs` with your own code. For\n" +" example, using the example on the previous page, make `src/main.rs` look like\n" +"\n" +" ```rust\n" +" fn main() {\n" +" println!(\"Edit me!\");\n" +" }\n" +" ```\n" +"\n" +"5. Use `cargo run` to build and run your updated binary:\n" +"\n" +" ```shell\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +" Running `target/debug/exercise`\n" +" Edit me!\n" +" ```\n" +"\n" +"6. Use `cargo check` to quickly check your project for errors, use `cargo build`\n" +" to compile it without running it. You will find the output in `target/debug/`\n" +" for a normal debug build. Use `cargo build --release` to produce an optimized\n" +" release build in `target/release/`.\n" +"\n" +"7. You can add dependencies for your project by editing `Cargo.toml`. When you\n" +" run `cargo` commands, it will automatically download and compile missing\n" +" dependencies for you." +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 "" +"Cerca di incoraggiare i partecipanti alla classe a installare Cargo e utilizzare a\n" +"editore locale. Semplificherà la loro vita poiché avranno a\n" +"normale ambiente di sviluppo." + +#: src/welcome-day-1.md:1 +#, fuzzy +msgid "# Welcome to Day 1" +msgstr "# Benvenuto al primo giorno" + +#: 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 "" +"Questo è il primo giorno di Comprehensive Rust. Copriremo molto terreno\n" +"Oggi:" + +#: src/welcome-day-1.md:6 +#, fuzzy +msgid "" +"* Basic Rust syntax: variables, scalar and compound types, enums, structs,\n" +" references, functions, and methods.\n" +"\n" +"* Memory management: stack vs heap, manual memory management, scope-based memory\n" +" management, and garbage collection.\n" +"\n" +"* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." +msgstr "" +"* Sintassi di base di Rust: variabili, tipi scalari e composti, enum, struct,\n" +" riferimenti, funzioni e metodi.\n" +"\n" +"* Gestione della memoria: stack vs heap, gestione manuale della memoria, memoria basata sull'ambito\n" +" gestione e raccolta dei rifiuti.\n" +"\n" +"* Proprietà: semantica di spostamento, copia e clonazione, prestito e durata." + +#: src/welcome-day-1.md:16 +#, fuzzy +msgid "Please remind the students that:" +msgstr "Si ricorda agli studenti che:" + +#: 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" +"* 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 "" +"* Dovrebbero fare domande quando le ricevono, non salvarle fino alla fine.\n" +"* La lezione è pensata per essere interattiva e le discussioni sono molto incoraggiate!\n" +" * In qualità di istruttore, dovresti cercare di mantenere le discussioni pertinenti, ad es.\n" +" mantieni la relazione con il modo in cui Rust fa le cose rispetto a qualche altra lingua. Può essere\n" +" difficile trovare il giusto equilibrio, ma peccare per permettere discussioni\n" +" poiché coinvolgono le persone molto più della comunicazione unidirezionale.\n" +"* Le domande probabilmente significheranno che parleremo di cose prima delle diapositive.\n" +" * Questo è perfettamente a posto! La ripetizione è una parte importante dell'apprendimento. Ricordare\n" +" che le diapositive sono solo un supporto e sei libero di saltarle come preferisci\n" +" Piace." + +#: 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 "" +"L'idea per il primo giorno è mostrare _quanto basta_ di Rust per poter parlare\n" +"sul famoso controllo dei prestiti. Il modo in cui Rust gestisce la memoria è una caratteristica importante\n" +"e dovremmo mostrarlo subito agli studenti." + +#: 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 "" +"Se stai insegnando questo in un'aula, questo è un buon posto per esaminare il\n" +"programma. Suggeriamo di dividere la giornata in due parti (seguendo le slide):" + +#: src/welcome-day-1.md:36 +#, fuzzy +msgid "" +"* Morning: 9:00 to 12:00,\n" +"* Afternoon: 13:00 to 16:00." +msgstr "" +"* Mattina: dalle 9:00 alle 12:00,\n" +"* Pomeriggio: dalle 13:00 alle 16:00." + +#: 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!" +msgstr "" +"Ovviamente puoi regolarlo se necessario. Assicurati di includere pause,\n" +"consigliamo una pausa ogni ora!" + +#: src/welcome-day-1/what-is-rust.md:1 +#, fuzzy +msgid "# What is Rust?" +msgstr "# Cos'è la ruggine?" + +#: 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 è un nuovo linguaggio di programmazione che ha avuto la sua versione [1.0 nel 2015][1]:" + +#: 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" +"* Rust supports many [platforms and\n" +" architectures](https://doc.rust-lang.org/nightly/rustc/platform-support.html):\n" +" * x86, ARM, WebAssembly, ...\n" +" * Linux, Mac, Windows, ...\n" +"* Rust is used for a wide range of devices:\n" +" * firmware and boot loaders,\n" +" * smart displays,\n" +" * mobile phones,\n" +" * desktops,\n" +" * servers." +msgstr "" +"* Rust è un linguaggio compilato staticamente con un ruolo simile a C++\n" +" * `rustc` utilizza LLVM come backend.\n" +"* Rust supporta molte [piattaforme e\n" +" architetture](https://doc.rust-lang.org/nightly/rustc/platform-support.html):\n" +" * x86, ARM, WebAssembly, ...\n" +" * Linux, Mac, Windows, ...\n" +"* La ruggine viene utilizzata per un'ampia gamma di dispositivi:\n" +" * firmware e caricatori di avvio,\n" +" * display intelligenti,\n" +" * cellulari,\n" +" * desktop,\n" +" * server." + +#: src/welcome-day-1/what-is-rust.md:21 +#, fuzzy +msgid "Rust fits in the same area as C++:" +msgstr "Rust si adatta alla stessa area di C++:" + +#: src/welcome-day-1/what-is-rust.md:23 +#, fuzzy +msgid "" +"* High flexibility.\n" +"* High level of control.\n" +"* Can be scaled down to very constrained devices like mobile phones.\n" +"* Has no runtime or garbage collection.\n" +"* Focuses on reliability and safety without sacrificing performance." +msgstr "" +"* Elevata flessibilità.\n" +"* Alto livello di controllo.\n" +"* Può essere ridotto a dispositivi molto vincolati come i telefoni cellulari.\n" +"* Non ha runtime o garbage collection.\n" +"* Si concentra su affidabilità e sicurezza senza sacrificare le prestazioni." + +#: src/hello-world.md:1 +#, fuzzy +msgid "# Hello World!" +msgstr "# Ciao mondo!" + +#: src/hello-world.md:3 +#, fuzzy +msgid "" +"Let us jump into the simplest possible Rust program, a classic Hello World\n" +"program:" +msgstr "" +"Passiamo al programma Rust più semplice possibile, un classico Hello World\n" +"programma:" + +#: src/hello-world.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" println!(\"Hello 🌍!\");\n" +"}\n" +"```" +msgstr "" + +#: src/hello-world.md:12 +#, fuzzy +msgid "What you see:" +msgstr "Quello che vedi:" + +#: 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" +"* The `main` function is the entry point of the program.\n" +"* Rust has hygienic macros, `println!` is an example of this.\n" +"* Rust strings are UTF-8 encoded and can contain any Unicode character." +msgstr "" +"* Le funzioni sono introdotte con `fn`.\n" +"* I blocchi sono delimitati da parentesi graffe come in C e C++.\n" +"* La funzione `main` è il punto di ingresso del programma.\n" +"* Rust ha macro igieniche, `println!` ne è un esempio.\n" +"* Le stringhe Rust sono codificate in UTF-8 e possono contenere qualsiasi carattere Unicode." + +#: 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 "" +"Questa diapositiva cerca di mettere gli studenti a proprio agio con il codice Rust. Vedranno\n" +"un sacco di esso nei prossimi quattro giorni, quindi iniziamo in piccolo con qualcosa di familiare." + +#: src/hello-world.md:27 +#, fuzzy +msgid "" +"* Rust is very much like other languages in the C/C++/Java tradition. It is\n" +" imperative (not functional) and it doesn't try to reinvent things unless\n" +" absolutely necessary.\n" +"\n" +"* Rust is modern with full support for things like Unicode.\n" +"\n" +"* Rust uses macros for situations where you want to have a variable number of\n" +" arguments (no function [overloading](basic-syntax/functions-interlude.md)).\n" +"\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)." +msgstr "" +"* Rust è molto simile ad altri linguaggi della tradizione C/C++/Java. È\n" +" imperativo (non funzionale) e non cerca di reinventare le cose a meno che\n" +" assolutamente necessario.\n" +"\n" +"* Rust è moderno con pieno supporto per cose come Unicode.\n" +"\n" +"* Rust utilizza le macro per le situazioni in cui si desidera avere un numero variabile di\n" +" argomenti (nessuna funzione [sovraccarico](basic-syntax/functions-interlude.md)).\n" +"\n" +"* Le macro essendo \"igieniche\" significa che non catturano accidentalmente identificatori da\n" +" l'ambito in cui vengono utilizzate. Le macro di Rust sono in realtà solo\n" +" [parzialmente igienico](https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene.html)." + +#: src/hello-world/small-example.md:1 +#, fuzzy +msgid "# Small Example" +msgstr "# Piccolo esempio" + +#: src/hello-world/small-example.md:3 +#, fuzzy +msgid "Here is a small example program in Rust:" +msgstr "Ecco un piccolo programma di esempio in Rust:" + +#: src/hello-world/small-example.md:5 +msgid "" +"```rust,editable\n" +"fn main() { // Program entry point\n" +" let mut x: i32 = 6; // Mutable variable binding\n" +" print!(\"{x}\"); // Macro for printing, like printf\n" +" while x != 1 { // No parenthesis around expression\n" +" if x % 2 == 0 { // Math like in other languages\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +" print!(\" -> {x}\");\n" +" }\n" +" println!();\n" +"}\n" +"```" +msgstr "" + +#: 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 "" +"Il codice implementa la congettura di Collatz: si ritiene che il ciclo lo farà\n" +"finiscono sempre, ma questo non è ancora provato. Modifica il codice e gioca con diversi\n" +"ingressi." + +#: src/hello-world/small-example.md:29 +#, fuzzy +msgid "" +"* Explain that all variables are statically typed. Try removing `i32` to trigger\n" +" type inference. Try with `i8` instead and trigger a runtime integer overflow.\n" +"\n" +"* Change `let mut x` to `let x`, discuss the compiler error.\n" +"\n" +"* Show how `print!` gives a compilation error if the arguments don't match the\n" +" format string.\n" +"\n" +"* Show how you need to use `{}` as a placeholder if you want to print an\n" +" expression which is more complex than just a single variable.\n" +"\n" +"* Show the students the standard library, show them how to search for `std::fmt`\n" +" 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 "" +"* Spiegare che tutte le variabili sono tipizzate staticamente. Prova a rimuovere \"i32\" per attivare\n" +" inferenza di tipo. Prova invece con `i8` e attiva un overflow di runtime integer.\n" +"\n" +"* Modificare `let mut x` in `let x`, discutere l'errore del compilatore.\n" +"\n" +"* Mostra come `print!` restituisce un errore di compilazione se gli argomenti non corrispondono a\n" +" stringa di formato.\n" +"\n" +"* Mostra come devi usare `{}` come segnaposto se vuoi stampare un file\n" +" espressione che è più complessa di una singola variabile.\n" +"\n" +"* Mostra agli studenti la libreria standard, mostra loro come cercare `std::fmt`\n" +" che ha le regole del mini-linguaggio di formattazione. È importante che il\n" +" gli studenti acquisiscono familiarità con la ricerca nella libreria standard." + +#: src/why-rust.md:1 +#, fuzzy +msgid "# Why Rust?" +msgstr "# Perché ruggine?" + +#: src/why-rust.md:3 +#, fuzzy +msgid "Some unique selling points of Rust:" +msgstr "Alcuni punti di forza unici di Rust:" + +#: src/why-rust.md:5 +#, fuzzy +msgid "" +"* Compile time memory safety.\n" +"* Lack of undefined runtime behavior.\n" +"* Modern language features." +msgstr "" +"* Sicurezza della memoria del tempo di compilazione.\n" +"* Mancanza di comportamento runtime non definito.\n" +"* Funzionalità del linguaggio moderno." + +#: 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 "" +"Assicurati di chiedere alla classe con quali lingue ha esperienza. Dipendente\n" +"nella risposta puoi evidenziare diverse caratteristiche di Rust:" + +#: 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" +" have the memory unsafety issues. In addition, you get a modern language with\n" +" constructs like pattern matching and built-in dependency management.\n" +"\n" +"* Experience with Java, Go, Python, JavaScript...: You get the same memory safety\n" +" as in those languages, plus a similar high-level language feeling. In addition\n" +" 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 "" +"* Esperienza con C o C++: Rust elimina un'intera classe di _errori di runtime_\n" +" tramite il controllo del prestito. Ottieni prestazioni come in C e C++, ma non lo fai\n" +" hanno i problemi di sicurezza della memoria. Inoltre, ottieni un linguaggio moderno con\n" +" costrutti come il pattern matching e la gestione delle dipendenze incorporata.\n" +"\n" +"* Esperienza con Java, Go, Python, JavaScript...: Ottieni la stessa sicurezza della memoria\n" +" come in quelle lingue, più una simile sensazione linguistica di alto livello. Inoltre\n" +" ottieni prestazioni veloci e prevedibili come C e C++ (nessun Garbage Collector)\n" +" così come l'accesso all'hardware di basso livello (se ne hai bisogno)" + +#: src/why-rust/compile-time.md:1 +#, fuzzy +msgid "# Compile Time Guarantees" +msgstr "# Compile Time Guarantees" + +#: src/why-rust/compile-time.md:3 +#, fuzzy +msgid "Static memory management at compile time:" +msgstr "Gestione della memoria statica in fase di compilazione:" + +#: src/why-rust/compile-time.md:5 +#, fuzzy +msgid "" +"* No uninitialized variables.\n" +"* No memory leaks (_mostly_, see notes).\n" +"* No double-frees.\n" +"* No use-after-free.\n" +"* No `NULL` pointers.\n" +"* No forgotten locked mutexes.\n" +"* No data races between threads.\n" +"* No iterator invalidation." +msgstr "" +"* Nessuna variabile non inizializzata.\n" +"* Nessuna perdita di memoria (_principalmente_, vedi note).\n" +"* Nessuna doppia libera.\n" +"* Nessun utilizzo dopo-gratis.\n" +"* Nessun puntatore `NULL`.\n" +"* Nessun mutex bloccato dimenticato.\n" +"* Nessuna gara di dati tra i thread.\n" +"* Nessuna invalidazione dell'iteratore." + +#: src/why-rust/compile-time.md:16 +#, fuzzy +msgid "" +"It is possible to produce memory leaks in (safe) Rust. Some examples\n" +"are:" +msgstr "" +"È possibile produrre perdite di memoria in (sicuro) Rust. Qualche esempio\n" +"Sono:" + +#: 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" +" 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" +"* You can also accidentally create a [reference cycle] with `Rc` or\n" +" `Arc`.\n" +"* In fact, some will consider infinitely populating a collection a memory\n" +" leak and Rust does not protect from those." +msgstr "" +"* Puoi usare [`Box::leak`] per far trapelare un puntatore. Un uso di questo potrebbe\n" +" be per ottenere variabili statiche inizializzate in runtime e di dimensioni runtime\n" +"* Puoi usare [`std::mem::forget`] per fare in modo che il compilatore \"dimentichi\"\n" +" un valore (il che significa che il distruttore non viene mai eseguito).\n" +"* Puoi anche creare accidentalmente un [ciclo di riferimento] con `Rc` o\n" +" 'Arco'.\n" +"* In effetti, alcuni considereranno il popolamento infinito di una raccolta un ricordo\n" +" perdite e la ruggine non protegge da quelle." + +#: 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 "" +"Ai fini di questo corso, si dovrebbe intendere \"Nessuna perdita di memoria\".\n" +"come \"Praticamente nessuna perdita di memoria * accidentale *\"." + +#: src/why-rust/runtime.md:1 +#, fuzzy +msgid "# Runtime Guarantees" +msgstr "# Garanzie di autonomia" + +#: src/why-rust/runtime.md:3 +#, fuzzy +msgid "No undefined behavior at runtime:" +msgstr "Nessun comportamento indefinito in fase di esecuzione:" + +#: src/why-rust/runtime.md:5 +#, fuzzy +msgid "" +"* Array access is bounds checked.\n" +"* Integer overflow is defined." +msgstr "" +"* L'accesso all'array è controllato dai limiti.\n" +"* L'overflow di numeri interi è definito." + +#: 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" +" semantics. By default, you get panics in debug mode (`cargo build`)\n" +" and wrap-around in release mode (`cargo build --release`).\n" +"\n" +"* Bounds checking cannot be disabled with a compiler flag. It can also\n" +" not be disabled directly with the `unsafe` keyword. However,\n" +" `unsafe` allows you to call functions such as `slice::get_unchecked`\n" +" which does not do bounds checking." +msgstr "" +"* L'overflow di numeri interi è definito tramite un flag in fase di compilazione. Le opzioni sono\n" +" o un panico (un crash controllato del programma) o un wrap-around\n" +" semantica. Per impostazione predefinita, ottieni il panico in modalità di debug (`cargo build`)\n" +" e wrap-around in modalità rilascio (`cargo build --release`).\n" +"\n" +"* Il controllo dei limiti non può essere disabilitato con un flag del compilatore. Io posso anche\n" +" non essere disabilitato direttamente con la parola chiave `unsafe`. Tuttavia,\n" +" `unsafe` ti permette di chiamare funzioni come `slice::get_unchecked`\n" +" che non esegue il controllo dei limiti." + +#: src/why-rust/modern.md:1 +#, fuzzy +msgid "# Modern Features" +msgstr "# Funzionalità moderne" + +#: src/why-rust/modern.md:3 +#, fuzzy +msgid "Rust is built with all the experience gained in the last 40 years." +msgstr "Rust è costruito con tutta l'esperienza maturata negli ultimi 40 anni." + +#: src/why-rust/modern.md:5 +#, fuzzy +msgid "## Language Features" +msgstr "## Caratteristiche del linguaggio" + +#: src/why-rust/modern.md:7 +#, fuzzy +msgid "" +"* Enums and pattern matching.\n" +"* Generics.\n" +"* No overhead FFI.\n" +"* Zero-cost abstractions." +msgstr "" +"* Enumerazioni e pattern matching.\n" +"* Generici.\n" +"* Nessun FFI in testa.\n" +"* Astrazioni a costo zero." + +#: src/why-rust/modern.md:12 +#, fuzzy +msgid "## Tooling" +msgstr "## Utensili" + +#: 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 "" +"* Grandi errori del compilatore.\n" +"* Gestore delle dipendenze integrato.\n" +"* Supporto integrato per i test.\n" +"* Eccellente supporto del protocollo Language Server." + +#: src/why-rust/modern.md:23 +#, fuzzy +msgid "" +"* Zero-cost abstractions, similar to C++, means that you don't have to 'pay'\n" +" for higher-level programming constructs with memory or CPU. For example,\n" +" writing a loop using `for` should result in roughly the same low level\n" +" instructions as using the `.iter().fold()` construct.\n" +"\n" +"* It may be worth mentioning that Rust enums are 'Algebraic Data Types', also\n" +" known as 'sum types', which allow the type system to express things like\n" +" `Option` and `Result`.\n" +"\n" +"* Remind people to read the errors --- many developers have gotten used to\n" +" ignore lengthy compiler output. The Rust compiler is significantly more\n" +" talkative than other compilers. It will often provide you with _actionable_\n" +" feedback, ready to copy-paste into your code.\n" +"\n" +"* The Rust standard library is small compared to languages like Java, Python,\n" +" and Go. Rust does not come with several things you might consider standard and\n" +" essential:\n" +"\n" +" * a random number generator, but see [rand].\n" +" * support for SSL or TLS, but see [rusttls].\n" +" * support for JSON, but see [serde_json].\n" +"\n" +" The reasoning behind this is that functionality in the standard library cannot\n" +" go away, so it has to be very stable. For the examples above, the Rust\n" +" community is still working on finding the best solution --- and perhaps there\n" +" isn't a single \"best solution\" for some of these things.\n" +"\n" +" Rust comes with a built-in package manager in the form of Cargo and this makes\n" +" it trivial to download and compile third-party crates. A consequence of this\n" +" is that the standard library can be smaller.\n" +"\n" +" Discovering good third-party crates can be a problem. Sites like\n" +" help with this by letting you compare health metrics for\n" +" crates to find a good and trusted one.\n" +" \n" +"* [rust-analyzer] is a well supported LSP implementation used in major\n" +" IDEs and text editors." +msgstr "" +"* Astrazioni a costo zero, simili a C++, significa che non devi \"pagare\"\n" +" per costrutti di programmazione di livello superiore con memoria o CPU. Per esempio,\n" +" scrivere un ciclo usando `for` dovrebbe comportare all'incirca lo stesso livello basso\n" +" istruzioni come usare il costrutto `.iter().fold()`.\n" +"\n" +"* Potrebbe valere la pena ricordare che anche le enum di Rust sono \"tipi di dati algebrici\".\n" +" noti come \"tipi di somma\", che consentono al sistema di tipi di esprimere cose come\n" +" `Opzione` e `Risultato`.\n" +"\n" +"* Ricorda alle persone di leggere gli errori --- a cui molti sviluppatori si sono abituati\n" +" ignora il lungo output del compilatore. Il compilatore Rust è molto di più\n" +" loquace rispetto ad altri compilatori. Ti fornirà spesso _actionable_\n" +" feedback, pronto per il copia-incolla nel tuo codice.\n" +"\n" +"* La libreria standard di Rust è piccola rispetto a linguaggi come Java, Python,\n" +" e vai. Rust non viene fornito con molte cose che potresti considerare standard e\n" +" essenziale:\n" +"\n" +" * un generatore di numeri casuali, ma vedi [rand].\n" +" * supporto per SSL o TLS, ma vedi [rusttls].\n" +" * supporto per JSON, ma vedi [serde_json].\n" +"\n" +" Il ragionamento alla base di ciò è che la funzionalità nella libreria standard non può\n" +" andare via, quindi deve essere molto stabile. Per gli esempi precedenti, Rust\n" +" la comunità sta ancora lavorando per trovare la soluzione migliore --- e forse lì\n" +" non è un'unica \"soluzione migliore\" per alcune di queste cose.\n" +"\n" +" Rust viene fornito con un gestore di pacchetti integrato sotto forma di Cargo e questo rende\n" +" è banale scaricare e compilare casse di terze parti. Una conseguenza di ciò\n" +" è che la libreria standard può essere più piccola.\n" +"\n" +" La scoperta di buone casse di terze parti può essere un problema. Siti come\n" +" aiuta in questo consentendoti di confrontare le metriche di salute per\n" +" casse per trovarne una buona e fidata.\n" +" \n" +"* [rust-analyzer] è un'implementazione LSP ben supportata utilizzata in major\n" +" IDE ed editor di testo." + +#: src/basic-syntax.md:1 +#, fuzzy +msgid "# Basic Syntax" +msgstr "# Sintassi di base" + +#: src/basic-syntax.md:3 +#, fuzzy +msgid "Much of the Rust syntax will be familiar to you from C, C++ or Java:" +msgstr "Gran parte della sintassi di Rust ti sarà familiare da C, C++ o Java:" + +#: 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" +" */`.\n" +"* Keywords like `if` and `while` work the same.\n" +"* Variable assignment is done with `=`, comparison is done with `==`." +msgstr "" +"* I blocchi e gli ambiti sono delimitati da parentesi graffe.\n" +"* I commenti di riga iniziano con `//`, i commenti di blocco sono delimitati da `/* ...\n" +" */'.\n" +"* Parole chiave come \"if\" e \"while\" funzionano allo stesso modo.\n" +"* L'assegnazione delle variabili viene eseguita con `=`, il confronto viene eseguito con `==`." + +#: src/basic-syntax/scalar-types.md:1 +#, fuzzy +msgid "# Scalar Types" +msgstr "# Tipi scalari" + +#: src/basic-syntax/scalar-types.md:3 +#, fuzzy +msgid "" +"| | Types | Literals |\n" +"|------------------------|--------------------------------------------|-------------------------------|\n" +"| Signed integers | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `-10`, `0`, `1_000`, `123i64` |\n" +"| Unsigned integers | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, `10u16` |\n" +"| Floating point numbers | `f32`, `f64` | `3.14`, `-10.0e20`, `2f32` |\n" +"| Strings | `&str` | `\"foo\"`, `\"two\\nlines\"` |\n" +"| Unicode scalar values | `char` | `'a'`, `'α'`, `'∞'` |\n" +"| Booleans | `bool` | `true`, `false` |" +msgstr "" +"| | Tipi | Letterali |\n" +"|------------------------|------------------------ ---------------------|---------------------------- --|\n" +"| Interi con segno | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `-10`, `0`, `1_000`, `123i64` |\n" +"| Interi senza segno | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, `10u16` |\n" +"| Numeri in virgola mobile | `f32`, `f64` | `3.14`, `-10.0e20`, `2f32` |\n" +"| Corde | `&str` | `\"pippo\"`, `\"due\\nrighe\"` |\n" +"| Valori scalari Unicode | `char` | `'a'`, `'α'`, `'∞'` |\n" +"| Booleani | `bool` | `vero`, `falso` |" + +#: src/basic-syntax/scalar-types.md:12 +#, fuzzy +msgid "The types have widths as follows:" +msgstr "I tipi hanno larghezze come segue:" + +#: src/basic-syntax/scalar-types.md:14 +#, fuzzy +msgid "" +"* `iN`, `uN`, and `fN` are _N_ bits wide,\n" +"* `isize` and `usize` are the width of a pointer,\n" +"* `char` is 32 bit wide,\n" +"* `bool` is 8 bit wide." +msgstr "" +"* `iN`, `uN` e `fN` sono larghi _N_ bit,\n" +"* `isize` e `usize` sono la larghezza di un puntatore,\n" +"* `char` è largo 32 bit,\n" +"* `bool` è largo 8 bit." + +#: src/basic-syntax/scalar-types.md:21 +#, fuzzy +msgid "There are a few syntaxes which are not shown above:" +msgstr "Ci sono alcune sintassi che non sono mostrate sopra:" + +#: 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 "" + +#: src/basic-syntax/compound-types.md:1 +#, fuzzy +msgid "# Compound Types" +msgstr "# Tipi composti" + +#: src/basic-syntax/compound-types.md:3 +msgid "" +"| | Types | Literals |\n" +"|--------|-------------------------------|-----------------------------------|\n" +"| Arrays | `[T; N]` | `[20, 30, 40]`, `[0; 3]` |\n" +"| Tuples | `()`, `(T,)`, `(T1, T2)`, ... | `()`, `('x',)`, `('x', 1.2)`, ... |" +msgstr "" + +#: src/basic-syntax/compound-types.md:8 +#, fuzzy +msgid "Array assignment and access:" +msgstr "Assegnazione e accesso all'array:" + +#: src/basic-syntax/compound-types.md:10 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut a: [i8; 10] = [42; 10];\n" +" a[5] = 0;\n" +" println!(\"a: {:?}\", a);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/compound-types.md:18 +#, fuzzy +msgid "Tuple assignment and access:" +msgstr "Assegnazione e accesso alla tupla:" + +#: src/basic-syntax/compound-types.md:20 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let t: (i8, bool) = (7, true);\n" +" println!(\"1st index: {}\", t.0);\n" +" println!(\"2nd index: {}\", t.1);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/compound-types.md:32 +#, fuzzy +msgid "Arrays:" +msgstr "Array:" + +#: src/basic-syntax/compound-types.md:34 +msgid "" +"* Arrays have elements of the same type, `T`, and length, `N`, which is a compile-time constant.\n" +" Note that the length of the array is *part of its type*, which means that `[u8; 3]` and\n" +" `[u8; 4]` are considered two different types.\n" +"\n" +"* We can use literals to assign values to arrays.\n" +"\n" +"* In the main function, the print statement asks for the debug implementation with the `?` format\n" +" parameter: `{}` gives the default output, `{:?}` gives the debug output. We\n" +" could also have used `{a}` and `{a:?}` without specifying the value after the\n" +" format string.\n" +"\n" +"* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read." +msgstr "" + +#: src/basic-syntax/compound-types.md:47 +#, fuzzy +msgid "Tuples:" +msgstr "Tuple:" + +#: src/basic-syntax/compound-types.md:49 +#, fuzzy +msgid "" +"* Like arrays, tuples have a fixed length.\n" +"\n" +"* Tuples group together values of different types into a compound type.\n" +"\n" +"* Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`.\n" +"\n" +"* The empty tuple `()` is also known as the \"unit type\". It is both a type, and\n" +" the only valid value of that type - that is to say both the type and its value\n" +" are expressed as `()`. It is used to indicate, for example, that a function or\n" +" expression has no return value, as we'll see in a future slide. \n" +" * You can think of it as `void` that can be familiar to you from other \n" +" programming languages." +msgstr "" +"* Come gli array, le tuple hanno una lunghezza fissa.\n" +"\n" +"* Le tuple raggruppano valori di tipi diversi in un tipo composto.\n" +"\n" +"* È possibile accedere ai campi di una tupla tramite il punto e l'indice del valore, ad es. `t.0`, `t.1`.\n" +"\n" +"* La tupla vuota `()` è anche nota come \"tipo di unità\". È sia un tipo che\n" +" l'unico valore valido di quel tipo, vale a dire sia il tipo che il suo valore\n" +" sono espressi come `()`. Viene utilizzato per indicare, ad esempio, che una funzione o\n" +" expression non ha alcun valore di ritorno, come vedremo in una diapositiva futura.\n" +" * Puoi pensarlo come un \"vuoto\" che può esserti familiare da altri\n" +" linguaggi di programmazione." + +#: src/basic-syntax/references.md:1 +#, fuzzy +msgid "# References" +msgstr "# Riferimenti" + +#: src/basic-syntax/references.md:3 +#, fuzzy +msgid "Like C++, Rust has references:" +msgstr "Come C++, Rust ha riferimenti:" + +#: src/basic-syntax/references.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x: i32 = 10;\n" +" let ref_x: &mut i32 = &mut x;\n" +" *ref_x = 20;\n" +" println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/references.md:14 +#, fuzzy +msgid "Some notes:" +msgstr "Alcune note:" + +#: 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 "" +"* Dobbiamo dereferenziare `ref_x` quando lo assegni, in modo simile ai puntatori C e C++.\n" +"* In alcuni casi Rust dereferenzia automaticamente, in particolare durante l'invocazione\n" +" metodi (prova `ref_x.count_ones()`).\n" +"* I riferimenti dichiarati come `mut` possono essere associati a valori diversi nel corso della loro durata." + +#: src/basic-syntax/references.md:21 +#, fuzzy +msgid "" +"
\n" +"Key points:" +msgstr "" +"\n" +"Punti chiave:" + +#: src/basic-syntax/references.md:24 +#, fuzzy +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 "" +"* Assicurati di notare la differenza tra `let mut ref_x: &i32` e `let ref_x:\n" +" &mut i32`. Il primo rappresenta un riferimento mutevole a cui può essere associato\n" +" valori diversi, mentre il secondo rappresenta un riferimento a un valore mutabile." + +#: src/basic-syntax/references-dangling.md:1 +#, fuzzy +msgid "# Dangling References" +msgstr "# Riferimenti penzolanti" + +#: src/basic-syntax/references-dangling.md:3 +#, fuzzy +msgid "Rust will statically forbid dangling references:" +msgstr "Rust proibirà staticamente i riferimenti penzolanti:" + +#: src/basic-syntax/references-dangling.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let ref_x: &i32;\n" +" {\n" +" let x: i32 = 10;\n" +" ref_x = &x;\n" +" }\n" +" println!(\"ref_x: {ref_x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/references-dangling.md:16 +#, 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 "" +"* Si dice che un riferimento \"prenda in prestito\" il valore a cui si riferisce.\n" +"* Rust tiene traccia delle vite di tutti i riferimenti per assicurarsi che durino a lungo\n" +" Abbastanza.\n" +"* Parleremo di più del prestito quando arriveremo alla proprietà." + +#: src/basic-syntax/slices.md:1 +#, fuzzy +msgid "# Slices" +msgstr "# Fette" + +#: src/basic-syntax/slices.md:3 +#, fuzzy +msgid "A slice gives you a view into a larger collection:" +msgstr "Una sezione ti offre una vista in una raccolta più ampia:" + +#: src/basic-syntax/slices.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" +" println!(\"a: {a:?}\");\n" +"\n" +" let s: &[i32] = &a[2..4];\n" +" println!(\"s: {s:?}\");\n" +"}\n" +"```" +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 "" +"* Le sezioni prendono in prestito i dati dal tipo a fette.\n" +"* Domanda: Cosa succede se modifichi `a[3]`?" + +#: 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" +"* If the slice starts at index 0, Rust’s range syntax allows us to drop the starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are " +"identical.\n" +" \n" +"* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are identical.\n" +"\n" +"* To easily create a slice of the full array, we can therefore use `&a[..]`.\n" +"\n" +"* `s` is a reference to a slice of `i32`s. Notice that the type of `s` (`&[i32]`) no longer mentions the array length. This allows us to perform " +"computation on slices of different sizes.\n" +" \n" +"* Slices always borrow from another object. In this example, `a` has to remain 'alive' (in scope) for at least as long as our slice. \n" +" \n" +"* The question about modifying `a[3]` can spark an interesting discussion, but the answer is that for memory safety reasons\n" +" you cannot do it through `a` after you created a slice, but you can read the data from both `a` and `s` safely. \n" +" More details will be explained in the borrow checker section." +msgstr "" +"* Creiamo una sezione prendendo in prestito `a` e specificando gli indici iniziale e finale tra parentesi.\n" +"\n" +"* Se la slice inizia all'indice 0, la sintassi dell'intervallo di Rust ci consente di eliminare l'indice iniziale, il che significa che `&a[0..a." +"len()]` e `&a[..a.len()]` sono identici .\n" +" \n" +"* Lo stesso vale per l'ultimo indice, quindi `&a[2..a.len()]` e `&a[2..]` sono identici.\n" +"\n" +"* Per creare facilmente una porzione dell'array completo, possiamo quindi utilizzare `&a[..]`.\n" +"\n" +"* `s` è un riferimento a una porzione di `i32`s. Si noti che il tipo di `s` (`&[i32]`) non menziona più la lunghezza dell'array. Questo ci permette " +"di eseguire il calcolo su fette di diverse dimensioni.\n" +" \n" +"* Le fette prendono sempre in prestito da un altro oggetto. In questo esempio, `a` deve rimanere 'vivo' (nello scope) almeno quanto la nostra " +"fetta.\n" +" \n" +"* La domanda sulla modifica di `a[3]` può innescare una discussione interessante, ma la risposta è che per motivi di sicurezza della memoria\n" +" non puoi farlo tramite \"a\" dopo aver creato una sezione, ma puoi leggere i dati sia da \"a\" che da \"s\" in modo sicuro.\n" +" Maggiori dettagli saranno spiegati nella sezione controllo del prestito." + +#: src/basic-syntax/string-slices.md:1 +#, fuzzy +msgid "# `String` vs `str`" +msgstr "# `String` vs `str`" + +#: src/basic-syntax/string-slices.md:3 +#, fuzzy +msgid "We can now understand the two string types in Rust:" +msgstr "Ora possiamo comprendere i due tipi di stringhe in Rust:" + +#: src/basic-syntax/string-slices.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: &str = \"World\";\n" +" println!(\"s1: {s1}\");\n" +"\n" +" let mut s2: String = String::from(\"Hello \");\n" +" println!(\"s2: {s2}\");\n" +" s2.push_str(s1);\n" +" println!(\"s2: {s2}\");\n" +" \n" +" let s3: &str = &s2[6..];\n" +" println!(\"s3: {s3}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/string-slices.md:20 +#, fuzzy +msgid "Rust terminology:" +msgstr "Terminologia della ruggine:" + +#: src/basic-syntax/string-slices.md:22 +#, fuzzy +msgid "" +"* `&str` an immutable reference to a string slice.\n" +"* `String` a mutable string buffer." +msgstr "" +"* `&str` un riferimento immutabile a uno slice di stringa.\n" +"* `String` un buffer di stringa mutabile." + +#: src/basic-syntax/string-slices.md:27 +msgid "" +"* `&str` introduces a string slice, which is an immutable reference to UTF-8 encoded string data \n" +" stored in a block of memory. String literals (`”Hello”`), are stored in the program’s binary.\n" +"\n" +"* Rust’s `String` type is a wrapper around a vector of bytes. As with a `Vec`, it is owned.\n" +" \n" +"* As with many other types `String::from()` creates a string from a string literal; `String::new()` \n" +" creates a new empty string, to which string data can be added using the `push()` and `push_str()` methods.\n" +"\n" +"* The `format!()` macro is a convenient way to generate an owned string from dynamic values. It \n" +" accepts the same format specification as `println!()`.\n" +" \n" +"* You can borrow `&str` slices from `String` via `&` and optionally range selection.\n" +" \n" +"* For C++ programmers: think of `&str` as `const char*` from C++, but the one that always points \n" +" to a valid string in memory. Rust `String` is a rough equivalent of `std::string` from C++ \n" +" (main difference: it can only contain UTF-8 encoded bytes and will never use a small-string optimization).\n" +" " +msgstr "" + +#: src/basic-syntax/functions.md:1 +#, fuzzy +msgid "# Functions" +msgstr "# Funzioni" + +#: src/basic-syntax/functions.md:3 +#, fuzzy +msgid "A Rust version of the famous [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz) interview question:" +msgstr "Una versione Rust della famosa domanda dell'intervista [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz):" + +#: src/basic-syntax/functions.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" print_fizzbuzz_to(20);\n" +"}\n" +"\n" +"fn is_divisible(n: u32, divisor: u32) -> bool {\n" +" if divisor == 0 {\n" +" return false;\n" +" }\n" +" n % divisor == 0\n" +"}\n" +"\n" +"fn fizzbuzz(n: u32) -> String {\n" +" let fizz = if is_divisible(n, 3) { \"fizz\" } else { \"\" };\n" +" let buzz = if is_divisible(n, 5) { \"buzz\" } else { \"\" };\n" +" if fizz.is_empty() && buzz.is_empty() {\n" +" return format!(\"{n}\");\n" +" }\n" +" format!(\"{fizz}{buzz}\")\n" +"}\n" +"\n" +"fn print_fizzbuzz_to(n: u32) {\n" +" for i in 1..=n {\n" +" println!(\"{}\", fizzbuzz(i));\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/functions.md:35 +msgid "" +"* We refer in `main` to a function written below. Neither forward declarations nor headers are necessary. \n" +"* Declaration parameters are followed by a type (the reverse of some programming languages), then a return type.\n" +"* The last expression in a function body (or any block) becomes the return value. Simply omit the `;` 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 `print_fizzbuzz_to()` contains `=n`, which causes it to include the upper bound." +msgstr "" + +#: src/basic-syntax/rustdoc.md:1 +#, fuzzy +msgid "# Rustdoc" +msgstr "#RustDoc" + +#: src/basic-syntax/rustdoc.md:3 +#, fuzzy +msgid "All language items in Rust can be documented using special `///` syntax." +msgstr "Tutti gli elementi del linguaggio in Rust possono essere documentati usando la sintassi speciale `///`." + +#: src/basic-syntax/rustdoc.md:5 +msgid "" +"```rust,editable\n" +"/// Determine whether the first argument is divisible by the second argument.\n" +"///\n" +"/// If the second argument is zero, the result is false.\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" +"```" +msgstr "" + +#: src/basic-syntax/rustdoc.md:17 +#, fuzzy +msgid "" +"The contents are treated as Markdown. All published Rust library crates are\n" +"automatically documented at [`docs.rs`](https://docs.rs) using the\n" +"[rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It is\n" +"idiomatic to document all public items in an API using this pattern." +msgstr "" +"I contenuti sono trattati come Markdown. Tutti i crate della libreria Rust pubblicati lo sono\n" +"documentato automaticamente in [`docs.rs`](https://docs.rs) utilizzando il file\n" +"[rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) strumento. È\n" +"idiomatico per documentare tutti gli elementi pubblici in un'API utilizzando questo modello." + +#: src/basic-syntax/rustdoc.md:24 +#, fuzzy +msgid "" +"* Show students the generated docs for the `rand` crate at\n" +" [`docs.rs/rand`](https://docs.rs/rand).\n" +"\n" +"* This course does not include rustdoc on slides, just to save space, but in\n" +" real code they should be present.\n" +"\n" +"* Inner doc comments are discussed later (in the page on modules) and need not\n" +" be addressed here." +msgstr "" +"* Mostra agli studenti i documenti generati per la cassa `rand` su\n" +" [`docs.rs/rand`](https://docs.rs/rand).\n" +"\n" +"* Questo corso non include rustdoc sulle diapositive, solo per risparmiare spazio, ma in\n" +" codice reale dovrebbero essere presenti.\n" +"\n" +"* I commenti interni al documento sono discussi più avanti (nella pagina sui moduli) e non sono necessari\n" +" essere affrontato qui." + +#: src/basic-syntax/methods.md:1 src/methods.md:1 +#, fuzzy +msgid "# Methods" +msgstr "# Metodi" + +#: src/basic-syntax/methods.md:3 +#, fuzzy +msgid "" +"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 "" +"I metodi sono funzioni associate a un tipo. L'argomento `self` di un metodo è\n" +"un'istanza del tipo a cui è associata:" + +#: src/basic-syntax/methods.md:6 +msgid "" +"```rust,editable\n" +"struct Rectangle {\n" +" width: u32,\n" +" height: u32,\n" +"}\n" +"\n" +"impl Rectangle {\n" +" fn area(&self) -> u32 {\n" +" self.width * self.height\n" +" }\n" +"\n" +" fn inc_width(&mut self, delta: u32) {\n" +" self.width += delta;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut rect = Rectangle { width: 10, height: 5 };\n" +" println!(\"old area: {}\", rect.area());\n" +" rect.inc_width(5);\n" +" println!(\"new area: {}\", rect.area());\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/methods.md:30 +#, fuzzy +msgid "* We will look much more at methods in today's exercise and in tomorrow's class." +msgstr "* Approfondiremo maggiormente i metodi nell'esercizio di oggi e nella lezione di domani." + +#: 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" +msgstr "# Funzione sovraccarico" + +#: src/basic-syntax/functions-interlude.md:3 +#, fuzzy +msgid "Overloading is not supported:" +msgstr "Il sovraccarico non è supportato:" + +#: src/basic-syntax/functions-interlude.md:5 +#, fuzzy +msgid "" +"* Each function has a single implementation:\n" +" * Always takes a fixed number of parameters.\n" +" * Always takes a single set of parameter types.\n" +"* Default values are not supported:\n" +" * All call sites have the same number of arguments.\n" +" * Macros are sometimes used as an alternative." +msgstr "" +"* Ogni funzione ha una singola implementazione:\n" +" * Accetta sempre un numero fisso di parametri.\n" +" * Accetta sempre un singolo set di tipi di parametro.\n" +"* I valori predefiniti non sono supportati:\n" +" * Tutti i siti di chiamata hanno lo stesso numero di argomenti.\n" +" * Le macro sono talvolta utilizzate come alternativa." + +#: src/basic-syntax/functions-interlude.md:12 +#, fuzzy +msgid "However, function parameters can be generic:" +msgstr "Tuttavia, i parametri delle funzioni possono essere generici:" + +#: src/basic-syntax/functions-interlude.md:14 +msgid "" +"```rust,editable\n" +"fn pick_one(a: T, b: T) -> T {\n" +" if std::process::id() % 2 == 0 { a } else { b }\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"coin toss: {}\", pick_one(\"heads\", \"tails\"));\n" +" println!(\"cash prize: {}\", pick_one(500, 1000));\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/functions-interlude.md:27 +#, fuzzy +msgid "" +"* When using generics, the standard library's `Into` can provide a kind of limited\n" +" polymorphism on argument types. We will see more details in a later section." +msgstr "" +"* Quando si usano i generici, `Into` della libreria standard può fornire una sorta di limited\n" +" polimorfismo sui tipi di argomento. Vedremo maggiori dettagli in una sezione successiva." + +#: src/basic-syntax/functions-interlude.md:30 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/day-1/morning.md:1 +#, fuzzy +msgid "# Day 1: Morning Exercises" +msgstr "# Giorno 1: Esercizi mattutini" + +#: src/exercises/day-1/morning.md:3 +#, fuzzy +msgid "In these exercises, we will explore two parts of Rust:" +msgstr "In questi esercizi esploreremo due parti di Rust:" + +#: src/exercises/day-1/morning.md:5 +#, fuzzy +msgid "" +"* Implicit conversions between types.\n" +"\n" +"* Arrays and `for` loops." +msgstr "" +"* Conversioni implicite tra tipi.\n" +"\n" +"* Array e cicli `for`." + +#: src/exercises/day-1/morning.md:11 +#, fuzzy +msgid "A few things to consider while solving the exercises:" +msgstr "Alcune cose da considerare durante la risoluzione degli esercizi:" + +#: src/exercises/day-1/morning.md:13 +#, fuzzy +msgid "" +"* Use a local Rust installation, if possible. This way you can get\n" +" auto-completion in your editor. See the page about [Using Cargo] for details\n" +" on installing Rust.\n" +"\n" +"* Alternatively, use the Rust Playground." +msgstr "" +"* Utilizzare un'installazione locale di Rust, se possibile. In questo modo puoi ottenere\n" +" completamento automatico nel tuo editor. Vedi la pagina su [Utilizzo del carico] per i dettagli\n" +" sull'installazione di Rust.\n" +"\n" +"* In alternativa, usa Rust Playground." + +#: src/exercises/day-1/morning.md:19 +#, fuzzy +msgid "" +"The code snippets are not editable on purpose: the inline code snippets lose\n" +"their state if you navigate away from the page." +msgstr "" +"Gli snippet di codice non sono modificabili di proposito: gli snippet di codice in linea perdono\n" +"il loro stato se esci dalla pagina." + +#: src/exercises/day-1/morning.md:22 src/exercises/day-1/afternoon.md:11 src/exercises/day-2/morning.md:11 src/exercises/day-2/afternoon.md:7 +#: src/exercises/day-3/morning.md:7 src/exercises/bare-metal/morning.md:7 src/exercises/bare-metal/afternoon.md:7 +#: src/exercises/concurrency/morning.md:12 +#, fuzzy +msgid "After looking at the exercises, you can look at the [solutions] provided." +msgstr "Dopo aver esaminato gli esercizi, puoi esaminare le [soluzioni] fornite." + +#: src/exercises/day-1/implicit-conversions.md:1 +#, fuzzy +msgid "# Implicit Conversions" +msgstr "# Conversioni implicite" + +#: src/exercises/day-1/implicit-conversions.md:3 +#, fuzzy +msgid "" +"Rust will not automatically apply _implicit conversions_ between types ([unlike\n" +"C++][3]). You can see this in a program like this:" +msgstr "" +"Rust non applicherà automaticamente le _conversioni implicite_ tra i tipi ([a differenza di\n" +"C++][3]). Puoi vederlo in un programma come questo:" + +#: src/exercises/day-1/implicit-conversions.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"fn multiply(x: i16, y: i16) -> i16 {\n" +" x * y\n" +"}\n" +"\n" +"fn main() {\n" +" let x: i8 = 15;\n" +" let y: i16 = 1000;\n" +"\n" +" println!(\"{x} * {y} = {}\", multiply(x, y));\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/implicit-conversions.md:19 +#, fuzzy +msgid "" +"The Rust integer types all implement the [`From`][1] and [`Into`][2]\n" +"traits to let us convert between them. The `From` trait has a single `from()`\n" +"method and similarly, the `Into` trait has a single `into()` method.\n" +"Implementing these traits is how a type expresses that it can be converted into\n" +"another type." +msgstr "" +"Tutti i tipi interi di Rust implementano [`From`][1] e [`Into`][2]\n" +"tratti per farci convertire tra di loro. Il tratto `From` ha un singolo `from()`\n" +"e allo stesso modo, il tratto `Into` ha un singolo metodo `into()`.\n" +"L'implementazione di questi tratti è il modo in cui un tipo esprime ciò in cui può essere convertito\n" +"un altro tipo." + +#: src/exercises/day-1/implicit-conversions.md:25 +#, fuzzy +msgid "" +"The standard library has an implementation of `From for i16`, which means\n" +"that we can convert a variable `x` of type `i8` to an `i16` by calling \n" +"`i16::from(x)`. Or, simpler, with `x.into()`, because `From for i16`\n" +"implementation automatically create an implementation of `Into for i8`." +msgstr "" +"La libreria standard ha un'implementazione di `From for i16`, che significa\n" +"che possiamo convertire una variabile `x` di tipo `i8` in una `i16` chiamando\n" +"`i16::da(x)`. O, più semplicemente, con `x.into()`, perché `From for i16`\n" +"l'implementazione crea automaticamente un'implementazione di `Into per i8`." + +#: src/exercises/day-1/implicit-conversions.md:30 +#, fuzzy +msgid "" +"The same applies for your own `From` implementations for your own types, so it is\n" +"sufficient to only implement `From` to get a respective `Into` implementation automatically." +msgstr "" +"Lo stesso vale per le tue implementazioni `From` per i tuoi tipi, così è\n" +"sufficiente implementare solo `From` per ottenere automaticamente una rispettiva implementazione `Into`." + +#: src/exercises/day-1/implicit-conversions.md:33 +#, fuzzy +msgid "" +"1. Execute the above program and look at the compiler error.\n" +"\n" +"2. Update the code above to use `into()` to do the conversion.\n" +"\n" +"3. Change the types of `x` and `y` to other things (such as `f32`, `bool`,\n" +" `i128`) to see which types you can convert to which other types. Try\n" +" converting small types to big types and the other way around. Check the\n" +" [standard library documentation][1] to see if `From` is implemented for\n" +" the pairs you check." +msgstr "" +"1. Eseguire il programma precedente e osservare l'errore del compilatore.\n" +"\n" +"2. Aggiorna il codice sopra per utilizzare `into()` per eseguire la conversione.\n" +"\n" +"3. Cambia i tipi di `x` e `y` in altre cose (come `f32`, `bool`,\n" +" `i128`) per vedere quali tipi è possibile convertire in quali altri tipi. Tentativo\n" +" convertire caratteri piccoli in caratteri grandi e viceversa. Controlla il\n" +" [documentazione della libreria standard][1] per vedere se `From` è implementato per\n" +" le coppie che controlli." + +#: src/exercises/day-1/for-loops.md:1 +#, fuzzy +msgid "# Arrays and `for` Loops" +msgstr "# Array e cicli `for`" + +#: src/exercises/day-1/for-loops.md:3 +#, fuzzy +msgid "We saw that an array can be declared like this:" +msgstr "Abbiamo visto che un array può essere dichiarato in questo modo:" + +#: src/exercises/day-1/for-loops.md:5 +msgid "" +"```rust\n" +"let array = [10, 20, 30];\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:9 +#, fuzzy +msgid "You can print such an array by asking for its debug representation with `{:?}`:" +msgstr "Puoi stampare un tale array chiedendo la sua rappresentazione di debug con `{:?}`:" + +#: src/exercises/day-1/for-loops.md:11 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" println!(\"array: {array:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:18 +#, fuzzy +msgid "" +"Rust lets you iterate over things like arrays and ranges using the `for`\n" +"keyword:" +msgstr "" +"Rust ti consente di iterare cose come array e intervalli usando il `for`\n" +"parola chiave:" + +#: src/exercises/day-1/for-loops.md:21 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" print!(\"Iterating over array:\");\n" +" for n in array {\n" +" print!(\" {n}\");\n" +" }\n" +" println!();\n" +"\n" +" print!(\"Iterating over range:\");\n" +" for i in 0..3 {\n" +" print!(\" {}\", array[i]);\n" +" }\n" +" println!();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:38 +#, fuzzy +msgid "" +"Use the above to write a function `pretty_print` which pretty-print a matrix and\n" +"a function `transpose` which will transpose a matrix (turn rows into columns):" +msgstr "" +"Usa quanto sopra per scrivere una funzione `pretty_print` che stampa in modo grazioso una matrice e\n" +"una funzione `transpose` che traspone una matrice (trasforma le righe in colonne):" + +#: src/exercises/day-1/for-loops.md:41 +msgid "" +"```bob\n" +" ⎛⎡1 2 3⎤⎞ ⎡1 4 7⎤\n" +"\"transpose\"⎜⎢4 5 6⎥⎟ \"==\"⎢2 5 8⎥\n" +" ⎝⎣7 8 9⎦⎠ ⎣3 6 9⎦\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:47 +#, fuzzy +msgid "Hard-code both functions to operate on 3 × 3 matrices." +msgstr "Hard-code entrambe le funzioni per operare su matrici 3 × 3." + +#: src/exercises/day-1/for-loops.md:49 +#, fuzzy +msgid "" +"Copy the code below to and implement the\n" +"functions:" +msgstr "" +"Copia il codice qui sotto in e implementa il file\n" +"funzioni:" + +#: src/exercises/day-1/for-loops.md:52 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" unimplemented!()\n" +"}\n" +"\n" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" unimplemented!()\n" +"}\n" +"\n" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/for-loops.md:80 +#, fuzzy +msgid "## Bonus Question" +msgstr "## Domanda bonus" + +#: src/exercises/day-1/for-loops.md:82 +#, fuzzy +msgid "" +"Could you use `&[i32]` slices instead of hard-coded 3 × 3 matrices for your\n" +"argument and return types? Something like `&[&[i32]]` for a two-dimensional\n" +"slice-of-slices. Why or why not?" +msgstr "" +"Potresti usare fette `&[i32]` invece di matrici 3 × 3 codificate per il tuo\n" +"argomenti e tipi restituiti? Qualcosa come \"&[&[i32]]\" per un oggetto bidimensionale\n" +"fetta di fette. Perché o perché no?" + +#: src/exercises/day-1/for-loops.md:87 +#, fuzzy +msgid "" +"See the [`ndarray` crate](https://docs.rs/ndarray/) for a production quality\n" +"implementation." +msgstr "" +"Guarda la [cassa `ndarray`](https://docs.rs/ndarray/) per una qualità di produzione\n" +"implementazione." + +#: src/exercises/day-1/for-loops.md:92 +#, fuzzy +msgid "" +"The solution and the answer to the bonus section are available in the \n" +"[Solution](solutions-morning.md#arrays-and-for-loops) section." +msgstr "" +"La soluzione e la risposta alla sezione bonus sono disponibili nel\n" +"[Soluzione](solutions-morning.md#arrays-and-for-loops)." + +#: src/basic-syntax/variables.md:1 +#, fuzzy +msgid "# Variables" +msgstr "# Variabili" + +#: src/basic-syntax/variables.md:3 +#, fuzzy +msgid "" +"Rust provides type safety via static typing. Variable bindings are immutable by\n" +"default:" +msgstr "" +"Rust fornisce sicurezza di tipo tramite tipizzazione statica. Le associazioni variabili sono immutabili da\n" +"predefinito:" + +#: src/basic-syntax/variables.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x: i32 = 10;\n" +" println!(\"x: {x}\");\n" +" // x = 20;\n" +" // println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/variables.md:17 +#, fuzzy +msgid "" +"* Due to type inference the `i32` is optional. We will gradually show the types less and less as the course progresses.\n" +"* Note that since `println!` is a macro, `x` is not moved, even using the function like syntax of `println!(\"x: {}\", x)`" +msgstr "" +"* A causa dell'inferenza del tipo, `i32` è facoltativo. Mostreremo gradualmente i tipi sempre meno man mano che il corso procede.\n" +"* Nota che poiché `println!` è una macro, `x` non viene spostata, anche usando la sintassi di funzione simile a `println!(\"x: {}\", x)`" + +#: src/basic-syntax/type-inference.md:1 +#, fuzzy +msgid "# Type Inference" +msgstr "# Digitare Inferenza" + +#: src/basic-syntax/type-inference.md:3 +#, fuzzy +msgid "Rust will look at how the variable is _used_ to determine the type:" +msgstr "Rust esaminerà come la variabile viene _usata_ per determinare il tipo:" + +#: src/basic-syntax/type-inference.md:5 +msgid "" +"```rust,editable\n" +"fn takes_u32(x: u32) {\n" +" println!(\"u32: {x}\");\n" +"}\n" +"\n" +"fn takes_i8(y: i8) {\n" +" println!(\"i8: {y}\");\n" +"}\n" +"\n" +"fn main() {\n" +" let x = 10;\n" +" let y = 20;\n" +"\n" +" takes_u32(x);\n" +" takes_i8(y);\n" +" // takes_u32(y);\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/type-inference.md:26 +#, fuzzy +msgid "This slide demonstrates how the Rust compiler infers types based on constraints given by variable declarations and usages." +msgstr "Questa diapositiva mostra come il compilatore Rust deduce i tipi in base ai vincoli dati dalle dichiarazioni e dagli usi delle variabili." + +#: src/basic-syntax/type-inference.md:28 +#, fuzzy +msgid "" +"It is very important to emphasize that variables declared like this are not of some sort of dynamic \"any type\" that can\n" +"hold any data. The machine code generated by such declaration is identical to the explicit declaration of a type.\n" +"The compiler does the job for us and helps us write more concise code." +msgstr "" +"È molto importante sottolineare che le variabili dichiarate in questo modo non sono di una sorta di \"qualsiasi tipo\" dinamico che può\n" +"detenere alcun dato. Il codice macchina generato da tale dichiarazione è identico alla dichiarazione esplicita di un tipo.\n" +"Il compilatore fa il lavoro per noi e ci aiuta a scrivere codice più conciso." + +#: src/basic-syntax/type-inference.md:32 +#, fuzzy +msgid "" +"The following code tells the compiler to copy into a certain generic container without the code ever explicitly specifying the contained type, using " +"`_` as a placeholder:" +msgstr "" +"Il codice seguente indica al compilatore di copiare in un determinato contenitore generico senza che il codice specifichi mai esplicitamente il tipo " +"contenuto, utilizzando `_` come segnaposto:" + +#: src/basic-syntax/type-inference.md:34 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut v = Vec::new();\n" +" v.push((10, false));\n" +" v.push((20, true));\n" +" println!(\"v: {v:?}\");\n" +"\n" +" let vv = v.iter().collect::>();\n" +" println!(\"vv: {vv:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/type-inference.md:46 +#, fuzzy +msgid "" +"[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.collect) relies on `FromIterator`, which [`HashSet`](https://doc." +"rust-lang.org/std/iter/trait.FromIterator.html) implements." +msgstr "" +"[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.collect) si basa su `FromIterator`, che [`HashSet`](https:/ /doc." +"rust-lang.org/std/iter/trait.FromIterator.html) implementa." + +#: src/basic-syntax/static-and-const.md:1 +#, fuzzy +msgid "# Static and Constant Variables" +msgstr "# Variabili statiche e costanti" + +#: src/basic-syntax/static-and-const.md:3 +#, fuzzy +msgid "Global state is managed with static and constant variables." +msgstr "Lo stato globale è gestito con variabili statiche e costanti." + +#: src/basic-syntax/static-and-const.md:5 +#, fuzzy +msgid "## `const`" +msgstr "## `const`" + +#: src/basic-syntax/static-and-const.md:7 +#, fuzzy +msgid "You can declare compile-time constants:" +msgstr "Puoi dichiarare costanti in fase di compilazione:" + +#: src/basic-syntax/static-and-const.md:9 +msgid "" +"```rust,editable\n" +"const DIGEST_SIZE: usize = 3;\n" +"const ZERO: Option = Some(42);\n" +"\n" +"fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {\n" +" let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];\n" +" for (idx, &b) in text.as_bytes().iter().enumerate() {\n" +" digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE].wrapping_add(b);\n" +" }\n" +" digest\n" +"}\n" +"\n" +"fn main() {\n" +" let digest = compute_digest(\"Hello\");\n" +" println!(\"Digest: {digest:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/static-and-const.md:27 +#, fuzzy +msgid "According the the [Rust RFC Book][1] these are inlined upon use." +msgstr "Secondo il [Rust RFC Book][1] questi sono incorporati dopo l'uso." + +#: src/basic-syntax/static-and-const.md:29 +#, fuzzy +msgid "## `static`" +msgstr "## `statico`" + +#: src/basic-syntax/static-and-const.md:31 +#, fuzzy +msgid "You can also declare static variables:" +msgstr "Puoi anche dichiarare variabili statiche:" + +#: src/basic-syntax/static-and-const.md:33 +msgid "" +"```rust,editable\n" +"static BANNER: &str = \"Welcome to RustOS 3.14\";\n" +"\n" +"fn main() {\n" +" println!(\"{BANNER}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/static-and-const.md:41 +#, fuzzy +msgid "" +"As noted in the [Rust RFC Book][1], these are not inlined upon use and have an actual associated memory location. This is useful for unsafe and " +"embedded code, and the variable lives through the entirety of the program execution." +msgstr "" +"Come notato nel [Rust RFC Book][1], questi non sono allineati durante l'uso e hanno una posizione di memoria associata effettiva. Questo è utile per " +"il codice non sicuro e incorporato e la variabile vive per tutta l'esecuzione del programma." + +#: src/basic-syntax/static-and-const.md:44 +#, fuzzy +msgid "We will look at mutating static data in the [chapter on Unsafe Rust](../unsafe.md)." +msgstr "Esamineremo la modifica dei dati statici nel [capitolo su Unsafe Rust](../unsafe.md)." + +#: src/basic-syntax/static-and-const.md:48 +#, fuzzy +msgid "" +"* Mention that `const` behaves semantically similar to C++'s `constexpr`.\n" +"* `static`, on the other hand, is much more similar to a `const` or mutable global variable in C++.\n" +"* It isn't super common that one would need a runtime evaluated constant, but it is helpful and safer than using a static." +msgstr "" +"* Menziona che `const` si comporta semanticamente in modo simile a `constexpr` del C++.\n" +"* `static`, d'altra parte, è molto più simile a una `const` o variabile globale mutabile in C++.\n" +"* Non è molto comune che si abbia bisogno di una costante valutata in fase di esecuzione, ma è utile e più sicura rispetto all'utilizzo di una " +"statica." + +#: src/basic-syntax/scopes-shadowing.md:1 +#, fuzzy +msgid "# Scopes and Shadowing" +msgstr "# Ambiti e Shadowing" + +#: src/basic-syntax/scopes-shadowing.md:3 +#, fuzzy +msgid "" +"You can shadow variables, both those from outer scopes and variables from the\n" +"same scope:" +msgstr "" +"Puoi ombreggiare le variabili, sia quelle degli ambiti esterni che le variabili del file\n" +"stessa portata:" + +#: src/basic-syntax/scopes-shadowing.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a = 10;\n" +" println!(\"before: {a}\");\n" +"\n" +" {\n" +" let a = \"hello\";\n" +" println!(\"inner scope: {a}\");\n" +"\n" +" let a = true;\n" +" println!(\"shadowed in inner scope: {a}\");\n" +" }\n" +"\n" +" println!(\"after: {a}\");\n" +"}\n" +"```" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:25 +#, fuzzy +msgid "" +"* Definition: Shadowing is different from mutation, because after shadowing both variable's memory locations exist at the same time. Both are " +"available under the same name, depending where you use it in the code. \n" +"* A shadowing variable can have a different type. \n" +"* Shadowing looks obscure at first, but is convenient for holding on to values after `.unwrap()`.\n" +"* The following code demonstrates why the compiler can't simply reuse memory locations when shadowing an immutable variable in a scope, even if the " +"type does not change." +msgstr "" +"* Definizione: l'ombreggiatura è diversa dalla mutazione, perché dopo l'ombreggiatura le locazioni di memoria di entrambe le variabili esistono " +"contemporaneamente. Entrambi sono disponibili con lo stesso nome, a seconda di dove lo usi nel codice.\n" +"* Una variabile di ombreggiatura può avere un tipo diverso.\n" +"* L'ombreggiatura all'inizio sembra oscura, ma è utile per conservare i valori dopo `.unwrap()`.\n" +"* Il codice seguente dimostra perché il compilatore non può semplicemente riutilizzare le posizioni di memoria durante lo shadowing di una variabile " +"immutabile in un ambito, anche se il tipo non cambia." + +#: src/basic-syntax/scopes-shadowing.md:30 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let a = 1;\n" +" let b = &a;\n" +" let a = a + 1;\n" +" println!(\"{a} {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management.md:1 +#, fuzzy +msgid "# Memory Management" +msgstr "# Gestione della memoria" + +#: src/memory-management.md:3 +#, fuzzy +msgid "Traditionally, languages have fallen into two broad categories:" +msgstr "Tradizionalmente, le lingue sono state suddivise in due grandi categorie:" + +#: src/memory-management.md:5 +#, fuzzy +msgid "" +"* Full control via manual memory management: C, C++, Pascal, ...\n" +"* Full safety via automatic memory management at runtime: Java, Python, Go, Haskell, ..." +msgstr "" +"* Controllo completo tramite gestione manuale della memoria: C, C++, Pascal, ...\n" +"* Piena sicurezza tramite la gestione automatica della memoria in fase di esecuzione: Java, Python, Go, Haskell, ..." + +#: src/memory-management.md:8 +#, fuzzy +msgid "Rust offers a new mix:" +msgstr "Rust offre un nuovo mix:" + +#: src/memory-management.md:10 +#, fuzzy +msgid "" +"> Full control *and* safety via compile time enforcement of correct memory\n" +"> management." +msgstr "" +"> Pieno controllo *e* sicurezza tramite applicazione in fase di compilazione della memoria corretta\n" +"> gestione." + +#: src/memory-management.md:13 +#, fuzzy +msgid "It does this with an explicit ownership concept." +msgstr "Lo fa con un concetto di proprietà esplicito." + +#: src/memory-management.md:15 +#, fuzzy +msgid "First, let's refresh how memory management works." +msgstr "Innanzitutto, aggiorniamo il funzionamento della gestione della memoria." + +#: src/memory-management/stack-vs-heap.md:1 +#, fuzzy +msgid "# The Stack vs The Heap" +msgstr "# La pila contro l'heap" + +#: src/memory-management/stack-vs-heap.md:3 +#, fuzzy +msgid "" +"* Stack: Continuous area of memory for local variables.\n" +" * Values have fixed sizes known at compile time.\n" +" * Extremely fast: just move a stack pointer.\n" +" * Easy to manage: follows function calls.\n" +" * Great memory locality.\n" +"\n" +"* Heap: Storage of values outside of function calls.\n" +" * Values have dynamic sizes determined at runtime.\n" +" * Slightly slower than the stack: some book-keeping needed.\n" +" * No guarantee of memory locality." +msgstr "" +"* Stack: area continua di memoria per le variabili locali.\n" +" * I valori hanno dimensioni fisse note al momento della compilazione.\n" +" * Estremamente veloce: basta spostare un puntatore dello stack.\n" +" * Facile da gestire: segue le chiamate alle funzioni.\n" +" * Ottima località di memoria.\n" +"\n" +"* Heap: archiviazione di valori al di fuori delle chiamate di funzione.\n" +" * I valori hanno dimensioni dinamiche determinate in fase di esecuzione.\n" +" * Leggermente più lento della pila: è necessaria un po' di contabilità.\n" +" * Nessuna garanzia di località di memoria." + +#: src/memory-management/stack.md:1 +#, fuzzy +msgid "# Stack Memory" +msgstr "# Memoria impilabile" + +#: src/memory-management/stack.md:3 +#, fuzzy +msgid "" +"Creating a `String` puts fixed-sized data on the stack and dynamically sized\n" +"data on the heap:" +msgstr "" +"La creazione di una `Stringa` mette i dati di dimensioni fisse nello stack e dimensionati dinamicamente\n" +"dati sull'heap:" + +#: src/memory-management/stack.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1 = String::from(\"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:12 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | e | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:28 +msgid "" +"* Mention that a `String` is backed by a `Vec`, so it has a capacity and length and can grow if mutable via reallocation on the heap.\n" +"\n" +"* If students ask about it, you can mention that the underlying memory is heap allocated using the [System Allocator] and custom allocators can be " +"implemented using the [Allocator API]\n" +"\n" +"* We can inspect the memory layout with `unsafe` code. However, you should point out that this is rightfully unsafe!\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could lead to\n" +" // undefined behavior.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +" }\n" +" }\n" +" ```" +msgstr "" + +#: src/memory-management/manual.md:1 +#, fuzzy +msgid "# Manual Memory Management" +msgstr "# Gestione manuale della memoria" + +#: src/memory-management/manual.md:3 +#, fuzzy +msgid "You allocate and deallocate heap memory yourself." +msgstr "Allocate e deallocate voi stessi la memoria dell'heap." + +#: src/memory-management/manual.md:5 +#, fuzzy +msgid "If not done with care, this can lead to crashes, bugs, security vulnerabilities, and memory leaks." +msgstr "Se non fatto con cura, ciò può portare a arresti anomali, bug, vulnerabilità di sicurezza e perdite di memoria." + +#: src/memory-management/manual.md:7 +#, fuzzy +msgid "## C Example" +msgstr "## C Esempio" + +#: src/memory-management/manual.md:9 +#, fuzzy +msgid "You must call `free` on every pointer you allocate with `malloc`:" +msgstr "Devi chiamare `free` su ogni puntatore allocato con `malloc`:" + +#: src/memory-management/manual.md:11 +msgid "" +"```c\n" +"void foo(size_t n) {\n" +" int* int_array = (int*)malloc(n * sizeof(int));\n" +" //\n" +" // ... lots of code\n" +" //\n" +" free(int_array);\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/manual.md:21 +#, fuzzy +msgid "" +"Memory is leaked if the function returns early between `malloc` and `free`: the\n" +"pointer is lost and we cannot deallocate the memory." +msgstr "" +"La memoria viene persa se la funzione ritorna in anticipo tra `malloc` e `free`: the\n" +"puntatore è perso e non possiamo deallocare la memoria." + +#: src/memory-management/scope-based.md:1 +#, fuzzy +msgid "# Scope-Based Memory Management" +msgstr "# Gestione della memoria basata sull'ambito" + +#: src/memory-management/scope-based.md:3 +#, fuzzy +msgid "Constructors and destructors let you hook into the lifetime of an object." +msgstr "Costruttori e distruttori ti consentono di agganciarti alla vita di un oggetto." + +#: src/memory-management/scope-based.md:5 +#, fuzzy +msgid "" +"By wrapping a pointer in an object, you can free memory when the object is\n" +"destroyed. The compiler guarantees that this happens, even if an exception is\n" +"raised." +msgstr "" +"Avvolgendo un puntatore in un oggetto, puoi liberare memoria quando l'oggetto è\n" +"distrutto. Il compilatore garantisce che ciò accada, anche se lo è un'eccezione\n" +"sollevato." + +#: src/memory-management/scope-based.md:9 +#, fuzzy +msgid "" +"This is often called _resource acquisition is initialization_ (RAII) and gives\n" +"you smart pointers." +msgstr "" +"Questo è spesso chiamato _l'acquisizione delle risorse è l'inizializzazione_ (RAII) e dà\n" +"puntatori intelligenti." + +#: src/memory-management/scope-based.md:12 +#, fuzzy +msgid "## C++ Example" +msgstr "## Esempio C++" + +#: src/memory-management/scope-based.md:14 +msgid "" +"```c++\n" +"void say_hello(std::unique_ptr person) {\n" +" std::cout << \"Hello \" << person->name << std::endl;\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/scope-based.md:20 +#, fuzzy +msgid "" +"* The `std::unique_ptr` object is allocated on the stack, and points to\n" +" memory allocated on the heap.\n" +"* At the end of `say_hello`, the `std::unique_ptr` destructor will run.\n" +"* The destructor frees the `Person` object it points to." +msgstr "" +"* L'oggetto `std::unique_ptr` è allocato nello stack e punta a\n" +" memoria allocata nell'heap.\n" +"* Alla fine di `say_hello`, verrà eseguito il distruttore `std::unique_ptr`.\n" +"* Il distruttore libera l'oggetto `Person` a cui punta." + +#: src/memory-management/scope-based.md:25 +#, fuzzy +msgid "Special move constructors are used when passing ownership to a function:" +msgstr "I costruttori di mosse speciali vengono utilizzati quando si passa la proprietà a una funzione:" + +#: src/memory-management/scope-based.md:27 +msgid "" +"```c++\n" +"std::unique_ptr person = find_person(\"Carla\");\n" +"say_hello(std::move(person));\n" +"```" +msgstr "" + +#: src/memory-management/garbage-collection.md:1 +#, fuzzy +msgid "# Automatic Memory Management" +msgstr "# Gestione automatica della memoria" + +#: src/memory-management/garbage-collection.md:3 +#, fuzzy +msgid "" +"An alternative to manual and scope-based memory management is automatic memory\n" +"management:" +msgstr "" +"Un'alternativa alla gestione della memoria manuale e basata sull'ambito è la memoria automatica\n" +"gestione:" + +#: src/memory-management/garbage-collection.md:6 +#, fuzzy +msgid "" +"* The programmer never allocates or deallocates memory explicitly.\n" +"* A garbage collector finds unused memory and deallocates it for the programmer." +msgstr "" +"* Il programmatore non alloca o dealloca mai la memoria in modo esplicito.\n" +"* Un Garbage Collector trova la memoria inutilizzata e la dealloca per il programmatore." + +#: src/memory-management/garbage-collection.md:9 +#, fuzzy +msgid "## Java Example" +msgstr "## Esempio Java" + +#: src/memory-management/garbage-collection.md:11 +#, fuzzy +msgid "The `person` object is not deallocated after `sayHello` returns:" +msgstr "L'oggetto `person` non viene deallocato dopo che `sayHello` restituisce:" + +#: src/memory-management/garbage-collection.md:13 +msgid "" +"```java\n" +"void sayHello(Person person) {\n" +" System.out.println(\"Hello \" + person.getName());\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/rust.md:1 +#, fuzzy +msgid "# Memory Management in Rust" +msgstr "# Gestione della memoria in Rust" + +#: src/memory-management/rust.md:3 +#, fuzzy +msgid "Memory management in Rust is a mix:" +msgstr "La gestione della memoria in Rust è un mix:" + +#: src/memory-management/rust.md:5 +#, fuzzy +msgid "" +"* Safe and correct like Java, but without a garbage collector.\n" +"* Depending on which abstraction (or combination of abstractions) you choose, can be a single unique pointer, reference counted, or atomically " +"reference counted.\n" +"* Scope-based like C++, but the compiler enforces full adherence.\n" +"* A Rust user can choose the right abstraction for the situation, some even have no cost at runtime like C." +msgstr "" +"* Sicuro e corretto come Java, ma senza un garbage collector.\n" +"* A seconda dell'astrazione (o combinazione di astrazioni) scelta, può trattarsi di un singolo puntatore univoco, del conteggio dei riferimenti o " +"del conteggio dei riferimenti atomici.\n" +"* Basato sull'ambito come C++, ma il compilatore applica la piena aderenza.\n" +"* Un utente Rust può scegliere l'astrazione giusta per la situazione, alcuni addirittura non hanno alcun costo in fase di esecuzione come C." + +#: src/memory-management/rust.md:10 +#, fuzzy +msgid "It achieves this by modeling _ownership_ explicitly." +msgstr "Raggiunge questo modellando _ownership_ in modo esplicito." + +#: src/memory-management/rust.md:14 +#, fuzzy +msgid "" +"* If asked how at this point, you can mention that in Rust this is usually handled by RAII wrapper types such as [Box], [Vec], [Rc], or [Arc]. These " +"encapsulate ownership and memory allocation via various means, and prevent the potential errors in C.\n" +"\n" +"* You may be asked about destructors here, the [Drop] trait is the Rust equivalent." +msgstr "" +"* Se ti viene chiesto come a questo punto, puoi menzionare che in Rust questo è solitamente gestito da tipi di wrapper RAII come [Box], [Vec], [Rc] " +"o [Arc]. Questi incapsulano la proprietà e l'allocazione della memoria tramite vari mezzi e prevengono i potenziali errori in C.\n" +"\n" +"* Qui ti potrebbe essere chiesto dei distruttori, il tratto [Drop] è l'equivalente di Rust." + +#: src/memory-management/comparison.md:1 +#, fuzzy +msgid "# Comparison" +msgstr "# Confronto" + +#: src/memory-management/comparison.md:3 +#, fuzzy +msgid "Here is a rough comparison of the memory management techniques." +msgstr "Ecco un confronto approssimativo delle tecniche di gestione della memoria." + +#: src/memory-management/comparison.md:5 +#, fuzzy +msgid "## Pros of Different Memory Management Techniques" +msgstr "## Pro di diverse tecniche di gestione della memoria" + +#: src/memory-management/comparison.md:7 +#, fuzzy +msgid "" +"* Manual like C:\n" +" * No runtime overhead.\n" +"* Automatic like Java:\n" +" * Fully automatic.\n" +" * Safe and correct.\n" +"* Scope-based like C++:\n" +" * Partially automatic.\n" +" * No runtime overhead.\n" +"* Compiler-enforced scope-based like Rust:\n" +" * Enforced by compiler.\n" +" * No runtime overhead.\n" +" * Safe and correct." +msgstr "" +"* Manuale come C:\n" +" * Nessun sovraccarico di runtime.\n" +"* Automatico come Java:\n" +" * Completamente automatico.\n" +" * Sicuro e corretto.\n" +"* Basato sull'ambito come C++:\n" +" * Parzialmente automatico.\n" +" * Nessun sovraccarico di runtime.\n" +"* Basato sull'ambito imposto dal compilatore come Rust:\n" +" * Applicato dal compilatore.\n" +" * Nessun sovraccarico di runtime.\n" +" * Sicuro e corretto." + +#: src/memory-management/comparison.md:20 +#, fuzzy +msgid "## Cons of Different Memory Management Techniques" +msgstr "## Contro di diverse tecniche di gestione della memoria" + +#: src/memory-management/comparison.md:22 +#, fuzzy +msgid "" +"* Manual like C:\n" +" * Use-after-free.\n" +" * Double-frees.\n" +" * Memory leaks.\n" +"* Automatic like Java:\n" +" * Garbage collection pauses.\n" +" * Destructor delays.\n" +"* Scope-based like C++:\n" +" * Complex, opt-in by programmer.\n" +" * Potential for use-after-free.\n" +"* Compiler-enforced and scope-based like Rust:\n" +" * Some upfront complexity.\n" +" * Can reject valid programs." +msgstr "" +"* Manuale come C:\n" +" * Usa-dopo-gratis.\n" +" * Doppia libera.\n" +" * Perdite di memoria.\n" +"* Automatico come Java:\n" +" * La raccolta dei rifiuti si interrompe.\n" +" * Ritardi del distruttore.\n" +"* Basato sull'ambito come C++:\n" +" * Complesso, opt-in dal programmatore.\n" +" * Potenziale per uso dopo-gratis.\n" +"* Applicato al compilatore e basato sull'ambito come Rust:\n" +" * Qualche complessità iniziale.\n" +" * Può rifiutare programmi validi." + +#: src/ownership.md:1 +#, fuzzy +msgid "# Ownership" +msgstr "# Proprietà" + +#: src/ownership.md:3 +#, fuzzy +msgid "" +"All variable bindings have a _scope_ where they are valid and it is an error to\n" +"use a variable outside its scope:" +msgstr "" +"Tutte le associazioni di variabili hanno un _scope_ in cui sono valide ed è un errore\n" +"usa una variabile al di fuori del suo ambito:" + +#: src/ownership.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" {\n" +" let p = Point(3, 4);\n" +" println!(\"x: {}\", p.0);\n" +" }\n" +" println!(\"y: {}\", p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership.md:18 +#, fuzzy +msgid "" +"* At the end of the scope, the variable is _dropped_ and the data is freed.\n" +"* A destructor can run here to free up resources.\n" +"* We say that the variable _owns_ the value." +msgstr "" +"* Alla fine dell'ambito, la variabile viene _eliminata_ ei dati vengono liberati.\n" +"* Un distruttore può essere eseguito qui per liberare risorse.\n" +"* Diciamo che la variabile _possiede_ il valore." + +#: src/ownership/move-semantics.md:1 +#, fuzzy +msgid "# Move Semantics" +msgstr "# Sposta la semantica" + +#: src/ownership/move-semantics.md:3 +#, fuzzy +msgid "An assignment will transfer ownership between variables:" +msgstr "Un'assegnazione trasferirà la proprietà tra le variabili:" + +#: src/ownership/move-semantics.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Hello!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/move-semantics.md:14 +#, fuzzy +msgid "" +"* The assignment of `s1` to `s2` transfers ownership.\n" +"* The data was _moved_ from `s1` and `s1` is no longer accessible.\n" +"* When `s1` goes out of scope, nothing happens: it has no ownership.\n" +"* When `s2` goes out of scope, the string data is freed.\n" +"* There is always _exactly_ one variable binding which owns a value." +msgstr "" +"* L'assegnazione di \"s1\" a \"s2\" trasferisce la proprietà.\n" +"* I dati sono stati _spostati_ da `s1` e `s1` non è più accessibile.\n" +"* Quando `s1` esce dall'ambito, non accade nulla: non ha proprietà.\n" +"* Quando `s2` esce dall'ambito, i dati della stringa vengono liberati.\n" +"* C'è sempre _esattamente_ un legame di variabile che possiede un valore." + +#: src/ownership/move-semantics.md:22 +#, fuzzy +msgid "" +"* Mention that this is the opposite of the defaults in C++, which copies by value unless you use `std::move` (and the move constructor is " +"defined!).\n" +"\n" +"* In Rust, clones are explicit (by using `clone`)." +msgstr "" +"* Menziona che questo è l'opposto dei valori predefiniti in C++, che copia per valore a meno che tu non usi `std::move` (e il costruttore di " +"movimento è definito!).\n" +"\n" +"* In Rust, i cloni sono espliciti (utilizzando `clone`)." + +#: src/ownership/moved-strings-rust.md:1 +#, fuzzy +msgid "# Moved Strings in Rust" +msgstr "# Stringhe spostate in Rust" + +#: src/ownership/moved-strings-rust.md:3 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Rust\");\n" +" let s2: String = s1;\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:10 +#, fuzzy +msgid "" +"* The heap data from `s1` is reused for `s2`.\n" +"* When `s1` goes out of scope, nothing happens (it has been moved from)." +msgstr "" +"* I dati dell'heap da `s1` vengono riutilizzati per `s2`.\n" +"* Quando `s1` esce dall'ambito, non accade nulla (è stato spostato da)." + +#: src/ownership/moved-strings-rust.md:13 +#, fuzzy +msgid "Before move to `s2`:" +msgstr "Prima di passare a `s2`:" + +#: src/ownership/moved-strings-rust.md:15 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| R | u | s | t | :\n" +": | len | 4 | : : +----+----+----+----+ :\n" +": | capacity | 4 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - -'\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:30 +#, fuzzy +msgid "After move to `s2`:" +msgstr "Dopo il passaggio a `s2`:" + +#: src/ownership/moved-strings-rust.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 \"(inaccessible)\" : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" +": | len | 4 | : | : +----+----+----+----+ :\n" +": | capacity | 4 | : | : :\n" +": +-----------+-------+ : | : :\n" +": : | `- - - - - - - - - - - - - -'\n" +": s2 : |\n" +": +-----------+-------+ : |\n" +": | ptr | o---+---+--'\n" +": | len | 4 | :\n" +": | capacity | 4 | :\n" +": +-----------+-------+ :\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:1 +#, fuzzy +msgid "# Double Frees in Modern C++" +msgstr "# Double Free nel C++ moderno" + +#: src/ownership/double-free-modern-cpp.md:3 +#, fuzzy +msgid "Modern C++ solves this differently:" +msgstr "Il moderno C++ risolve questo problema in modo diverso:" + +#: src/ownership/double-free-modern-cpp.md:5 +msgid "" +"```c++\n" +"std::string s1 = \"Cpp\";\n" +"std::string s2 = s1; // Duplicate the data in s1.\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:10 +#, fuzzy +msgid "" +"* The heap data from `s1` is duplicated and `s2` gets its own independent copy.\n" +"* When `s1` and `s2` go out of scope, they each free their own memory." +msgstr "" +"* I dati dell'heap da `s1` vengono duplicati e `s2` ottiene la propria copia indipendente.\n" +"* Quando `s1` e `s2` escono dall'ambito, ciascuno libera la propria memoria." + +#: src/ownership/double-free-modern-cpp.md:13 +#, fuzzy +msgid "Before copy-assignment:" +msgstr "Prima dell'assegnazione della copia:" + +#: src/ownership/double-free-modern-cpp.md:16 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:30 +#, fuzzy +msgid "After copy-assignment:" +msgstr "Dopo l'assegnazione della copia:" + +#: src/ownership/double-free-modern-cpp.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : : :\n" +": s2 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+-----+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:1 +#, fuzzy +msgid "# Moves in Function Calls" +msgstr "# Sposta nelle chiamate di funzione" + +#: src/ownership/moves-function-calls.md:3 +#, fuzzy +msgid "" +"When you pass a value to a function, the value is assigned to the function\n" +"parameter. This transfers ownership:" +msgstr "" +"Quando si passa un valore a una funzione, il valore viene assegnato alla funzione\n" +"parametro. Questo trasferisce la proprietà:" + +#: src/ownership/moves-function-calls.md:6 +msgid "" +"```rust,editable\n" +"fn say_hello(name: String) {\n" +" println!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let name = String::from(\"Alice\");\n" +" say_hello(name);\n" +" // say_hello(name);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:20 +#, fuzzy +msgid "" +"* With the first call to `say_hello`, `main` gives up ownership of `name`. Afterwards, `name` cannot be used anymore within `main`.\n" +"* The heap memory allocated for `name` will be freed at the end of the `say_hello` function.\n" +"* `main` can retain ownership if it passes `name` as a reference (`&name`) and if `say_hello` accepts a reference as a parameter.\n" +"* Alternatively, `main` can pass a clone of `name` in the first call (`name.clone()`).\n" +"* Rust makes it harder than C++ to inadvertently create copies by making move semantics the default, and by forcing programmers to make clones " +"explicit." +msgstr "" +"* Con la prima chiamata a `say_hello`, `main` rinuncia alla proprietà di `name`. Successivamente, `name` non può più essere utilizzato all'interno " +"di `main`.\n" +"* La memoria heap allocata per `name` verrà liberata alla fine della funzione `say_hello`.\n" +"* `main` può mantenere la proprietà se passa `name` come riferimento (`&name`) e se `say_hello` accetta un riferimento come parametro.\n" +"* In alternativa, `main` può passare un clone di `name` nella prima chiamata (`name.clone()`).\n" +"* Rust rende più difficile del C++ creare copie inavvertitamente rendendo la semantica di spostamento l'impostazione predefinita e costringendo i " +"programmatori a rendere espliciti i cloni." + +#: src/ownership/copy-clone.md:1 +#, fuzzy +msgid "# Copying and Cloning" +msgstr "# Copia e clonazione" + +#: src/ownership/copy-clone.md:3 +#, fuzzy +msgid "While move semantics are the default, certain types are copied by default:" +msgstr "Sebbene la semantica di spostamento sia l'impostazione predefinita, alcuni tipi vengono copiati per impostazione predefinita:" + +#: src/ownership/copy-clone.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = 42;\n" +" let y = x;\n" +" println!(\"x: {x}\");\n" +" println!(\"y: {y}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:14 +#, fuzzy +msgid "These types implement the `Copy` trait." +msgstr "Questi tipi implementano il tratto `Copy`." + +#: src/ownership/copy-clone.md:16 +#, fuzzy +msgid "You can opt-in your own types to use copy semantics:" +msgstr "Puoi acconsentire esplicitamente ai tuoi tipi per utilizzare la semantica della copia:" + +#: src/ownership/copy-clone.md:18 +msgid "" +"```rust,editable\n" +"#[derive(Copy, Clone, Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = p1;\n" +" println!(\"p1: {p1:?}\");\n" +" println!(\"p2: {p2:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:30 +#, fuzzy +msgid "" +"* After the assignment, both `p1` and `p2` own their own data.\n" +"* We can also use `p1.clone()` to explicitly copy the data." +msgstr "" +"* Dopo l'assegnazione, sia `p1` che `p2` possiedono i propri dati.\n" +"* Possiamo anche usare `p1.clone()` per copiare esplicitamente i dati." + +#: src/ownership/copy-clone.md:35 +#, fuzzy +msgid "Copying and cloning are not the same thing:" +msgstr "Copiare e clonare non sono la stessa cosa:" + +#: src/ownership/copy-clone.md:37 +#, fuzzy +msgid "" +"* Copying refers to bitwise copies of memory regions and does not work on arbitrary objects.\n" +"* Copying does not allow for custom logic (unlike copy constructors in C++).\n" +"* Cloning is a more general operation and also allows for custom behavior by implementing the `Clone` trait.\n" +"* Copying does not work on types that implement the `Drop` trait." +msgstr "" +"* La copia si riferisce a copie bit per bit di aree di memoria e non funziona su oggetti arbitrari.\n" +"* La copia non consente la logica personalizzata (a differenza dei costruttori di copia in C++).\n" +"* La clonazione è un'operazione più generale e consente anche un comportamento personalizzato implementando il tratto `Clone`.\n" +"* La copia non funziona sui tipi che implementano il tratto `Drop`." + +#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 +#, fuzzy +msgid "In the above example, try the following:" +msgstr "Nell'esempio precedente, prova quanto segue:" + +#: src/ownership/copy-clone.md:44 +#, fuzzy +msgid "" +"* Add a `String` field to `struct Point`. It will not compile because `String` is not a `Copy` type.\n" +"* Remove `Copy` from the `derive` attribute. The compiler error is now in the `println!` for `p1`.\n" +"* Show that it works if you clone `p1` instead." +msgstr "" +"* Aggiungi un campo `String` a `struct Point`. Non verrà compilato perché `String` non è un tipo `Copy`.\n" +"* Rimuovi `Copy` dall'attributo `derive`. L'errore del compilatore è ora in `println!` per `p1`.\n" +"* Dimostra che funziona se invece cloni `p1`." + +#: src/ownership/copy-clone.md:48 +#, fuzzy +msgid "" +"If students ask about `derive`, it is sufficient to say that this is a way to generate code in Rust\n" +"at compile time. In this case the default implementations of `Copy` and `Clone` traits are generated." +msgstr "" +"Se gli studenti chiedono informazioni su `derive`, è sufficiente dire che questo è un modo per generare codice in Rust\n" +"in fase di compilazione. In questo caso vengono generate le implementazioni predefinite dei tratti `Copy` e `Clone`." + +#: src/ownership/borrowing.md:1 +#, fuzzy +msgid "# Borrowing" +msgstr "# Prendere in prestito" + +#: src/ownership/borrowing.md:3 +#, fuzzy +msgid "" +"Instead of transferring ownership when calling a function, you can let a\n" +"function _borrow_ the value:" +msgstr "" +"Invece di trasferire la proprietà quando chiami una funzione, puoi lasciare che a\n" +"funzione _prende in prestito_ il valore:" + +#: src/ownership/borrowing.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn add(p1: &Point, p2: &Point) -> Point {\n" +" Point(p1.0 + p2.0, p1.1 + p2.1)\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/borrowing.md:22 +#, fuzzy +msgid "" +"* The `add` function _borrows_ two points and returns a new point.\n" +"* The caller retains ownership of the inputs." +msgstr "" +"* La funzione `add` _prende in prestito_ due punti e restituisce un nuovo punto.\n" +"* Il chiamante mantiene la proprietà degli ingressi." + +#: src/ownership/borrowing.md:27 +#, fuzzy +msgid "Notes on stack returns:" +msgstr "Note sui resi dello stack:" + +#: src/ownership/borrowing.md:28 +msgid "" +"* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy operation. Change the above code to print stack " +"addresses and run it on the [Playground]. In the \"DEBUG\" optimization level, the addresses should change, while they stay the same when changing " +"to the \"RELEASE\" setting:\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn add(p1: &Point, p2: &Point) -> Point {\n" +" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" +" println!(\"&p.0: {:p}\", &p.0);\n" +" p\n" +" }\n" +"\n" +" fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"&p3.0: {:p}\", &p3.0);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +" }\n" +" ```\n" +"* The Rust compiler can do return value optimization (RVO).\n" +"* In C++, copy elision has to be defined in the language specification because constructors can have side effects. In Rust, this is not an issue at " +"all. If RVO did not happen, Rust will always performs a simple and efficient `memcpy` copy." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:1 +#, fuzzy +msgid "# Shared and Unique Borrows" +msgstr "# Prestiti condivisi e unici" + +#: src/ownership/shared-unique-borrows.md:3 +#, fuzzy +msgid "Rust puts constraints on the ways you can borrow values:" +msgstr "Rust pone dei vincoli sui modi in cui puoi prendere in prestito i valori:" + +#: src/ownership/shared-unique-borrows.md:5 +#, fuzzy +msgid "" +"* You can have one or more `&T` values at any given time, _or_\n" +"* You can have exactly one `&mut T` value." +msgstr "" +"* Puoi avere uno o più valori `&T` in qualsiasi momento, _oppure_\n" +"* Puoi avere esattamente un valore `&mut T`." + +#: src/ownership/shared-unique-borrows.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let mut a: i32 = 10;\n" +" let b: &i32 = &a;\n" +"\n" +" {\n" +" let c: &mut i32 = &mut a;\n" +" *c = 20;\n" +" }\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:25 +#, fuzzy +msgid "" +"* The above code does not compile because `a` is borrowed as mutable (through `c`) and as immutable (through `b`) at the same time.\n" +"* Move the `println!` statement for `b` before the scope that introduces `c` to make the code compile.\n" +"* After that change, the compiler realizes that `b` is only ever used before the new mutable borrow of `a` through `c`. This is a feature of the " +"borrow checker called \"non-lexical lifetimes\"." +msgstr "" +"* Il codice precedente non viene compilato perché `a` è preso in prestito come mutabile (attraverso `c`) e come immutabile (attraverso `b`) allo " +"stesso tempo.\n" +"* Sposta l'istruzione `println!` per `b` prima dell'ambito che introduce `c` per far compilare il codice.\n" +"* Dopo tale modifica, il compilatore si rende conto che `b` è sempre e solo usato prima del nuovo prestito mutabile da `a` a `c`. Questa è una " +"caratteristica del controllo del prestito chiamata \"vita non lessicale\"." + +#: src/ownership/lifetimes.md:1 +#, fuzzy +msgid "# Lifetimes" +msgstr "# Vite" + +#: src/ownership/lifetimes.md:3 +#, fuzzy +msgid "A borrowed value has a _lifetime_:" +msgstr "Un valore preso in prestito ha una _durata_:" + +#: src/ownership/lifetimes.md:5 +msgid "" +"* The lifetime can be elided: `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." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:1 +#, fuzzy +msgid "# Lifetimes in Function Calls" +msgstr "# Durata delle chiamate di funzione" + +#: src/ownership/lifetimes-function-calls.md:3 +#, fuzzy +msgid "In addition to borrowing its arguments, a function can return a borrowed value:" +msgstr "Oltre a prendere in prestito i suoi argomenti, una funzione può restituire un valore preso in prestito:" + +#: src/ownership/lifetimes-function-calls.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p2: Point = Point(20, 20);\n" +" let p3: &Point = left_most(&p1, &p2);\n" +" println!(\"left-most point: {:?}\", p3);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:21 +#, fuzzy +msgid "" +"* `'a` is a generic parameter, it is inferred by the compiler.\n" +"* Lifetimes start with `'` and `'a` is a typical default name.\n" +"* Read `&'a Point` as \"a borrowed `Point` which is valid for at least the\n" +" lifetime `a`\".\n" +" * The _at least_ part is important when parameters are in different scopes." +msgstr "" +"* `'a` è un parametro generico, viene dedotto dal compilatore.\n" +"* Le durate iniziano con `'` e `'a` è un tipico nome predefinito.\n" +"* Leggi `&'a Point` come \"un `Punto` preso in prestito che è valido almeno per il\n" +" vita `a`\".\n" +" * La parte _almeno_ è importante quando i parametri si trovano in ambiti diversi." + +#: src/ownership/lifetimes-function-calls.md:31 +msgid "" +"* Move the declaration of `p2` and `p3` into a a new scope (`{ ... }`), resulting in the following code:\n" +" ```rust,ignore\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +" }\n" +"\n" +" fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p3: &Point;\n" +" {\n" +" let p2: Point = Point(20, 20);\n" +" p3 = left_most(&p1, &p2);\n" +" }\n" +" println!(\"left-most point: {:?}\", p3);\n" +" }\n" +" ```\n" +" Note how this does not compile since `p3` outlives `p2`.\n" +"\n" +"* Reset the workspace and change the function signature to `fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " +"because the relationship between the lifetimes `'a` and `'b` is unclear.\n" +"* Another way to explain it:\n" +" * 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" +" for longer than a variable from where the reference came from." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:1 +#, fuzzy +msgid "# Lifetimes in Data Structures" +msgstr "# Durata nelle strutture dati" + +#: src/ownership/lifetimes-data-structures.md:3 +#, fuzzy +msgid "If a data type stores borrowed data, it must be annotated with a lifetime:" +msgstr "Se un tipo di dati memorizza dati presi in prestito, deve essere annotato con una durata:" + +#: src/ownership/lifetimes-data-structures.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Highlight<'doc>(&'doc str);\n" +"\n" +"fn erase(text: String) {\n" +" println!(\"Bye {text}!\");\n" +"}\n" +"\n" +"fn main() {\n" +" let text = String::from(\"The quick brown fox jumps over the lazy dog.\");\n" +" let fox = Highlight(&text[4..19]);\n" +" let dog = Highlight(&text[35..43]);\n" +" // erase(text);\n" +" println!(\"{fox:?}\");\n" +" println!(\"{dog:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:25 +#, fuzzy +msgid "" +"* In the above example, the annotation on `Highlight` enforces that the data underlying the contained `&str` lives at least as long as any instance " +"of `Highlight` that uses that data.\n" +"* If `text` is consumed before the end of the lifetime of `fox` (or `dog`), the borrow checker throws an error.\n" +"* Types with borrowed data force users to hold on to the original data. This can be useful for creating lightweight views, but it generally makes " +"them somewhat harder to use.\n" +"* When possible, make data structures own their data directly.\n" +"* Some structs with multiple references inside can have more than one lifetime annotation. This can be necessary if there is a need to describe " +"lifetime relationships between the references themselves, in addition to the lifetime of the struct itself. Those are very advanced use cases." +msgstr "" +"* Nell'esempio precedente, l'annotazione su \"Highlight\" impone che i dati sottostanti a \"&str\" contenuti durino almeno quanto qualsiasi istanza " +"di \"Highlight\" che utilizza quei dati.\n" +"* Se `text` viene consumato prima della fine della vita di `fox` (o `dog`), il controllo del prestito genera un errore.\n" +"* I tipi con dati presi in prestito costringono gli utenti a conservare i dati originali. Questo può essere utile per creare viste leggere, ma in " +"genere le rende un po' più difficili da usare.\n" +"* Quando possibile, fare in modo che le strutture dati possiedano direttamente i propri dati.\n" +"* Alcune strutture con più riferimenti all'interno possono avere più di un'annotazione di durata. Ciò può essere necessario se è necessario " +"descrivere le relazioni di durata tra i riferimenti stessi, oltre alla durata della struttura stessa. Questi sono casi d'uso molto avanzati." + +#: src/exercises/day-1/afternoon.md:1 +#, fuzzy +msgid "# Day 1: Afternoon Exercises" +msgstr "# Giorno 1: Esercizi pomeridiani" + +#: src/exercises/day-1/afternoon.md:3 +#, fuzzy +msgid "We will look at two things:" +msgstr "Vedremo due cose:" + +#: src/exercises/day-1/afternoon.md:5 +#, fuzzy +msgid "" +"* A small book library,\n" +"\n" +"* Iterators and ownership (hard)." +msgstr "" +"* Una piccola biblioteca di libri,\n" +"\n" +"* Iteratori e proprietà (hard)." + +#: src/exercises/day-1/book-library.md:1 +#, fuzzy +msgid "# Designing a Library" +msgstr "# Progettare una libreria" + +#: src/exercises/day-1/book-library.md:3 +#, fuzzy +msgid "" +"We will learn much more about structs and the `Vec` type tomorrow. For now,\n" +"you just need to know part of its API:" +msgstr "" +"Impareremo molto di più sulle strutture e sul tipo `Vec` domani. Per adesso,\n" +"devi solo conoscere parte della sua API:" + +#: src/exercises/day-1/book-library.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut vec = vec![10, 20];\n" +" vec.push(30);\n" +" let midpoint = vec.len() / 2;\n" +" println!(\"middle value: {}\", vec[midpoint]);\n" +" for item in &vec {\n" +" println!(\"item: {item}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:18 +#, fuzzy +msgid "" +"Use this to create a library application. Copy the code below to\n" +" and update the types to make it compile:" +msgstr "" +"Usalo per creare un'applicazione libreria. Copia il codice qui sotto per\n" +" e aggiorna i tipi per farlo compilare:" + +#: src/exercises/day-1/book-library.md:21 +msgid "" +"```rust,should_panic\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// Implement the methods below. Update the `self` parameter to\n" +"// indicate the method's required level of ownership over the object:\n" +"//\n" +"// - `&self` for shared read-only access,\n" +"// - `&mut self` for unique and mutable access,\n" +"// - `self` for unique access by value.\n" +"impl Library {\n" +" fn new() -> Library {\n" +" todo!(\"Initialize and return a `Library` value\")\n" +" }\n" +"\n" +" //fn len(self) -> usize {\n" +" // todo!(\"Return the length of `self.books`\")\n" +" //}\n" +"\n" +" //fn is_empty(self) -> bool {\n" +" // todo!(\"Return `true` if `self.books` is empty\")\n" +" //}\n" +"\n" +" //fn add_book(self, book: Book) {\n" +" // todo!(\"Add a new book to `self.books`\")\n" +" //}\n" +"\n" +" //fn print_books(self) {\n" +" // todo!(\"Iterate over `self.books` and each book's title and year\")\n" +" //}\n" +"\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // todo!(\"Return a reference to the oldest book (if any)\")\n" +" //}\n" +"}\n" +"\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();\n" +"\n" +" //println!(\"The library is empty: {}\", library.is_empty());\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!(\"The oldest book is {book}\"),\n" +" // None => println!(\"The library is empty!\"),\n" +" //}\n" +" //\n" +" //println!(\"The library has {} books\", library.len());\n" +" //library.print_books();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/book-library.md:102 +#, fuzzy +msgid "[Solution](solutions-afternoon.md#designing-a-library)" +msgstr "[Soluzione](solutions-afternoon.md#designing-a-library)" + +#: src/exercises/day-1/iterators-and-ownership.md:1 +#, fuzzy +msgid "# Iterators and Ownership" +msgstr "# Iteratori e proprietà" + +#: src/exercises/day-1/iterators-and-ownership.md:3 +#, fuzzy +msgid "" +"The ownership model of Rust affects many APIs. An example of this is the\n" +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and\n" +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)\n" +"traits." +msgstr "" +"Il modello di proprietà di Rust influisce su molte API. Un esempio di questo è il\n" +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) e\n" +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)\n" +"tratti." + +#: src/exercises/day-1/iterators-and-ownership.md:8 +#, fuzzy +msgid "## `Iterator`" +msgstr "## `Iteratore`" + +#: src/exercises/day-1/iterators-and-ownership.md:10 +#, fuzzy +msgid "" +"Traits are like interfaces: they describe behavior (methods) for a type. The\n" +"`Iterator` trait simply says that you can call `next` until you get `None` back:" +msgstr "" +"I tratti sono come interfacce: descrivono il comportamento (metodi) per un tipo. IL\n" +"Il tratto \"Iterator\" dice semplicemente che puoi chiamare \"next\" fino a quando non ottieni \"Nessuno\":" + +#: src/exercises/day-1/iterators-and-ownership.md:13 +msgid "" +"```rust\n" +"pub trait Iterator {\n" +" type Item;\n" +" fn next(&mut self) -> Option;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:20 +#, fuzzy +msgid "You use this trait like this:" +msgstr "Usi questo tratto in questo modo:" + +#: src/exercises/day-1/iterators-and-ownership.md:22 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" println!(\"v[0]: {:?}\", iter.next());\n" +" println!(\"v[1]: {:?}\", iter.next());\n" +" println!(\"v[2]: {:?}\", iter.next());\n" +" println!(\"No more items: {:?}\", iter.next());\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:34 +#, fuzzy +msgid "What is the type returned by the iterator? Test your answer here:" +msgstr "Qual è il tipo restituito dall'iteratore? Metti alla prova la tua risposta qui:" + +#: src/exercises/day-1/iterators-and-ownership.md:36 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:46 +#, fuzzy +msgid "Why is this type used?" +msgstr "Perché viene utilizzato questo tipo?" + +#: src/exercises/day-1/iterators-and-ownership.md:48 +#, fuzzy +msgid "## `IntoIterator`" +msgstr "## `IntoIterator`" + +#: src/exercises/day-1/iterators-and-ownership.md:50 +#, fuzzy +msgid "" +"The `Iterator` trait tells you how to _iterate_ once you have created an\n" +"iterator. The related trait `IntoIterator` tells you how to create the iterator:" +msgstr "" +"Il tratto `Iterator` ti dice come _iterare_ una volta che hai creato un file\n" +"iteratore. Il tratto correlato `IntoIterator` ti dice come creare l'iteratore:" + +#: src/exercises/day-1/iterators-and-ownership.md:53 +msgid "" +"```rust\n" +"pub trait IntoIterator {\n" +" type Item;\n" +" type IntoIter: Iterator;\n" +"\n" +" fn into_iter(self) -> Self::IntoIter;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:62 +#, fuzzy +msgid "" +"The syntax here means that every implementation of `IntoIterator` must\n" +"declare two types:" +msgstr "" +"La sintassi qui significa che ogni implementazione di \"IntoIterator\" deve\n" +"dichiarare due tipi:" + +#: src/exercises/day-1/iterators-and-ownership.md:65 +#, fuzzy +msgid "" +"* `Item`: the type we iterate over, such as `i8`,\n" +"* `IntoIter`: the `Iterator` type returned by the `into_iter` method." +msgstr "" +"* `Item`: il tipo su cui iteriamo, come `i8`,\n" +"* `IntoIter`: il tipo `Iterator` restituito dal metodo `into_iter`." + +#: src/exercises/day-1/iterators-and-ownership.md:68 +#, fuzzy +msgid "" +"Note that `IntoIter` and `Item` are linked: the iterator must have the same\n" +"`Item` type, which means that it returns `Option`" +msgstr "" +"Nota che \"IntoIter\" e \"Item\" sono collegati: l'iteratore deve avere lo stesso\n" +"Tipo `Item`, che significa che restituisce `Option`" + +#: src/exercises/day-1/iterators-and-ownership.md:71 +#, fuzzy +msgid "Like before, what is the type returned by the iterator?" +msgstr "Come prima, qual è il tipo restituito dall'iteratore?" + +#: src/exercises/day-1/iterators-and-ownership.md:73 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];\n" +" let mut iter = v.into_iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:83 +#, fuzzy +msgid "## `for` Loops" +msgstr "## cicli `for`" + +#: src/exercises/day-1/iterators-and-ownership.md:85 +#, fuzzy +msgid "" +"Now that we know both `Iterator` and `IntoIterator`, we can build `for` loops.\n" +"They call `into_iter()` on an expression and iterates over the resulting\n" +"iterator:" +msgstr "" +"Ora che conosciamo sia `Iterator` che `IntoIterator`, possiamo creare cicli `for`.\n" +"Chiamano `into_iter()` su un'espressione e itera sul risultato\n" +"iteratore:" + +#: src/exercises/day-1/iterators-and-ownership.md:89 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];\n" +"\n" +" for word in &v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"\n" +" for word in v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/iterators-and-ownership.md:103 +#, fuzzy +msgid "What is the type of `word` in each loop?" +msgstr "Qual è il tipo di \"parola\" in ogni ciclo?" + +#: src/exercises/day-1/iterators-and-ownership.md:105 +#, fuzzy +msgid "" +"Experiment with the code above and then consult the documentation for [`impl\n" +"IntoIterator for\n" +"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E)\n" +"and [`impl IntoIterator for\n" +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-Vec%3CT%2C%20A%3E)\n" +"to check your answers." +msgstr "" +"Sperimenta con il codice sopra e poi consulta la documentazione per [`impl\n" +"IntoIteratore per\n" +"&Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E)\n" +"e [`impl IntoIterator for\n" +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-Vec%3CT%2C%20A%3E)\n" +"per controllare le tue risposte." + +#: src/welcome-day-2.md:1 +#, fuzzy +msgid "# Welcome to Day 2" +msgstr "# Benvenuto al giorno 2" + +#: src/welcome-day-2.md:3 +#, fuzzy +msgid "Now that we have seen a fair amount of Rust, we will continue with:" +msgstr "Ora che abbiamo visto una discreta quantità di ruggine, continueremo con:" + +#: src/welcome-day-2.md:5 +#, fuzzy +msgid "" +"* Structs, enums, methods.\n" +"\n" +"* Pattern matching: destructuring enums, structs, and arrays.\n" +"\n" +"* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and\n" +" `continue`.\n" +"\n" +"* The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, `Rc`\n" +" and `Arc`.\n" +"\n" +"* Modules: visibility, paths, and filesystem hierarchy." +msgstr "" +"* Struct, enum, metodi.\n" +"\n" +"* Pattern matching: destrutturazione di enum, struct e array.\n" +"\n" +"* Costrutti del flusso di controllo: `if`, `if let`, `while`, `while let`, `break` e\n" +" `continua`.\n" +"\n" +"* La libreria standard: `String`, `Option` e `Result`, `Vec`, `HashMap`, `Rc`\n" +" e \"Arco\".\n" +"\n" +"* Moduli: visibilità, percorsi e gerarchia del filesystem." + +#: src/structs.md:1 +#, fuzzy +msgid "# Structs" +msgstr "# Strutture" + +#: src/structs.md:3 +#, fuzzy +msgid "Like C and C++, Rust has support for custom structs:" +msgstr "Come C e C++, Rust supporta le strutture personalizzate:" + +#: src/structs.md:5 +msgid "" +"```rust,editable\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" peter.age = 28;\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" let jackie = Person {\n" +" name: String::from(\"Jackie\"),\n" +" ..peter\n" +" };\n" +" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" +"}\n" +"```" +msgstr "" + +#: src/structs.md:29 +#, fuzzy +msgid "" +"
\n" +"Key Points: " +msgstr "" +"\n" +"Punti chiave:" + +#: src/structs.md:32 +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" +" * Unlike in C++, there is no inheritance between structs.\n" +"* Methods are defined in an `impl` block, which we will see in following slides.\n" +"* This may be a good time to let people know there are different types of structs. \n" +" * Zero-sized structs `e.g., struct Foo;` might be used when implementing a trait on some type but don’t have any data that you want to store in " +"the value itself. \n" +" * The next slide will introduce Tuple structs, used when the field names are not important.\n" +"* The syntax `..peter` allows us to copy the majority of the fields from the old struct without having to explicitly type it all out. It must always " +"be the last element." +msgstr "" + +#: src/structs/tuple-structs.md:1 +#, fuzzy +msgid "# Tuple Structs" +msgstr "# Strutture di tuple" + +#: src/structs/tuple-structs.md:3 +#, fuzzy +msgid "If the field names are unimportant, you can use a tuple struct:" +msgstr "Se i nomi dei campi non sono importanti, puoi utilizzare una struttura di tupla:" + +#: src/structs/tuple-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p = Point(17, 23);\n" +" println!(\"({}, {})\", p.0, p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:14 +#, fuzzy +msgid "This is often used for single-field wrappers (called newtypes):" +msgstr "Questo è spesso usato per i wrapper a campo singolo (chiamati newtypes):" + +#: src/structs/tuple-structs.md:16 +msgid "" +"```rust,editable,compile_fail\n" +"struct PoundOfForce(f64);\n" +"struct Newtons(f64);\n" +"\n" +"fn compute_thruster_force() -> PoundOfForce {\n" +" todo!(\"Ask a rocket scientist at NASA\")\n" +"}\n" +"\n" +"fn set_thruster_force(force: Newtons) {\n" +" // ...\n" +"}\n" +"\n" +"fn main() {\n" +" let force = compute_thruster_force();\n" +" set_thruster_force(force);\n" +"}\n" +"\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:37 +#, fuzzy +msgid "" +"* Newtypes are a great way to encode additional information about the value in a primitive type, for example:\n" +" * The number is measured in some units: `Newtons` in the example above.\n" +" * The value passed some validation when it was created, so you no longer have to validate it again at every use: 'PhoneNumber(String)` or " +"`OddNumber(u32)`.\n" +"* Demonstrate how to add a `f64` value to a `Newtons` type by accessing the single field in the newtype.\n" +" * Rust generally doesn’t like inexplicit things, like automatic unwrapping or for instance using booleans as integers.\n" +" * Operator overloading is discussed on Day 3 (generics). " +msgstr "" +"* I newtype sono un ottimo modo per codificare informazioni aggiuntive sul valore in un tipo primitivo, ad esempio:\n" +" * Il numero è misurato in alcune unità: `Newton` nell'esempio precedente.\n" +" * Il valore ha superato una certa convalida quando è stato creato, quindi non è più necessario convalidarlo nuovamente a ogni utilizzo: 'Numero di " +"telefono (Stringa)` o `Numero dispari (u32)`.\n" +"* Dimostra come aggiungere un valore `f64` a un tipo `Newtons` accedendo al singolo campo nel newtype.\n" +" * A Rust in genere non piacciono le cose inesplicite, come l'unwrapping automatico o, ad esempio, l'uso di valori booleani come numeri interi.\n" +" * Il sovraccarico degli operatori viene discusso il giorno 3 (generici)." + +#: src/structs/field-shorthand.md:1 +#, fuzzy +msgid "# Field Shorthand Syntax" +msgstr "# Sintassi abbreviata dei campi" + +#: src/structs/field-shorthand.md:3 +#, fuzzy +msgid "" +"If you already have variables with the right names, then you can create the\n" +"struct using a shorthand:" +msgstr "" +"Se disponi già di variabili con i nomi corretti, puoi creare il file\n" +"struct usando una scorciatoia:" + +#: src/structs/field-shorthand.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn new(name: String, age: u8) -> Person {\n" +" Person { name, age }\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person::new(String::from(\"Peter\"), 27);\n" +" println!(\"{peter:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/structs/field-shorthand.md:27 +msgid "" +"* The `new` function could be written using `Self` as a type, as it is interchangeable with the struct type name\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Person {\n" +" fn new(name: String, age: u8) -> Self {\n" +" Self { name, age }\n" +" }\n" +" }\n" +" ``` \n" +"* Implement the `Default` trait for the struct. Define some fields and use the default values for the other fields.\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Default for Person {\n" +" fn default() -> Person {\n" +" Person {\n" +" name: \"Bot\".to_string(),\n" +" age: 0,\n" +" }\n" +" }\n" +" }\n" +" fn create_default() {\n" +" let tmp = Person {\n" +" ..Default::default()\n" +" };\n" +" let tmp = Person {\n" +" name: \"Sam\".to_string(),\n" +" ..Default::default()\n" +" };\n" +" }\n" +" ```\n" +"\n" +"* Methods are defined in the `impl` block.\n" +"* Use struct update syntax to define a new structure using `peter`. Note that the variable `peter` will no longer be accessible afterwards.\n" +"* Use `{:#?}` when printing structs to request the `Debug` representation." +msgstr "" + +#: src/enums.md:1 +#, fuzzy +msgid "# Enums" +msgstr "# Enum" + +#: src/enums.md:3 +#, fuzzy +msgid "" +"The `enum` keyword allows the creation of a type which has a few\n" +"different variants:" +msgstr "" +"La parola chiave `enum` consente la creazione di un tipo che ne ha alcuni\n" +"diverse varianti:" + +#: src/enums.md:6 +msgid "" +"```rust,editable\n" +"fn generate_random_number() -> i32 {\n" +" 4 // Chosen by fair dice roll. Guaranteed to be random.\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"enum CoinFlip {\n" +" Heads,\n" +" Tails,\n" +"}\n" +"\n" +"fn flip_coin() -> CoinFlip {\n" +" let random_number = generate_random_number();\n" +" if random_number % 2 == 0 {\n" +" return CoinFlip::Heads;\n" +" } else {\n" +" return CoinFlip::Tails;\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"You got: {:?}\", flip_coin());\n" +"}\n" +"```" +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 "Punti chiave:" + +#: src/enums.md:35 +#, fuzzy +msgid "" +"* Enumerations allow you to collect a set of values under one type\n" +"* This page offers an enum type `CoinFlip` with two variants `Heads` and `Tail`. You might note the namespace when using variants.\n" +"* This might be a good time to compare Structs and Enums:\n" +" * In both, you can have a simple version without fields (unit struct) or one with different types of fields (variant payloads). \n" +" * In both, associated functions are defined within an `impl` block.\n" +" * You could even implement the different variants of an enum with separate structs but then they wouldn’t be the same type as they would if they " +"were all defined in an enum. " +msgstr "" +"* Le enumerazioni consentono di raccogliere un insieme di valori in un unico tipo\n" +"* Questa pagina offre un tipo di enum `CoinFlip` con due varianti `Heads` e `Tail`. Potresti notare lo spazio dei nomi quando usi le varianti.\n" +"* Questo potrebbe essere un buon momento per confrontare Struct ed Enum:\n" +" * In entrambi, puoi avere una versione semplice senza campi (unit struct) o una con diversi tipi di campi (variant payload).\n" +" * In entrambi, le funzioni associate sono definite all'interno di un blocco `impl`.\n" +" * Potresti persino implementare le diverse varianti di un'enumerazione con strutture separate, ma non sarebbero dello stesso tipo che sarebbero se " +"fossero tutte definite in un'enumerazione." + +#: src/enums/variant-payloads.md:1 +#, fuzzy +msgid "# Variant Payloads" +msgstr "# Payload varianti" + +#: src/enums/variant-payloads.md:3 +#, fuzzy +msgid "" +"You can define richer enums where the variants carry data. You can then use the\n" +"`match` statement to extract the data from each variant:" +msgstr "" +"È possibile definire enumerazioni più ricche in cui le varianti contengono dati. È quindi possibile utilizzare il\n" +"istruzione `match` per estrarre i dati da ciascuna variante:" + +#: src/enums/variant-payloads.md:6 +msgid "" +"```rust,editable\n" +"enum WebEvent {\n" +" PageLoad, // Variant without payload\n" +" KeyPress(char), // Tuple struct variant\n" +" Click { x: i64, y: i64 }, // Full struct variant\n" +"}\n" +"\n" +"#[rustfmt::skip]\n" +"fn inspect(event: WebEvent) {\n" +" match event {\n" +" WebEvent::PageLoad => println!(\"page loaded\"),\n" +" WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" +" WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let load = WebEvent::PageLoad;\n" +" let press = WebEvent::KeyPress('x');\n" +" let click = WebEvent::Click { x: 20, y: 80 };\n" +"\n" +" inspect(load);\n" +" inspect(press);\n" +" inspect(click);\n" +"}\n" +"```" +msgstr "" + +#: src/enums/variant-payloads.md:35 +#, fuzzy +msgid "" +"* The values in the enum variants can only be accessed after being pattern matched. The pattern binds references to the fields in the \"match arm\" " +"after the `=>`.\n" +" * The expression is matched against the patterns from top to bottom. There is no fall-through like in C or C++.\n" +" * The match expression has a value. The value is the last expression in the match arm which was executed.\n" +" * Starting from the top we look for what pattern matches the value then run the code following the arrow. Once we find a match, we stop. \n" +"* Demonstrate what happens when the search is inexhaustive. Note the advantage the Rust compiler provides by confirming when all cases are " +"handled. \n" +"* `match` inspects a hidden discriminant field in the `enum`.\n" +"* It is possible to retrieve the discriminant by calling `std::mem::discriminant()`\n" +" * This is useful, for example, if implementing `PartialEq` for structs where comparing field values doesn't affect equality.\n" +"* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::Click(Click)` with a top level `struct Click { ... }`. The inlined version cannot " +"implement traits, for example. \n" +" " +msgstr "" +"* È possibile accedere ai valori nelle varianti enum solo dopo essere stati abbinati al modello. Il modello lega i riferimenti ai campi nel \"match " +"arm\" dopo il `=>`.\n" +" * L'espressione viene confrontata con i modelli dall'alto verso il basso. Non c'è fall-through come in C o C++.\n" +" * L'espressione di corrispondenza ha un valore. Il valore è l'ultima espressione nel braccio di corrispondenza che è stata eseguita.\n" +" * Partendo dall'alto cerchiamo quale modello corrisponde al valore, quindi eseguiamo il codice seguendo la freccia. Una volta trovata una " +"corrispondenza, ci fermiamo.\n" +"* Dimostrare cosa succede quando la ricerca è inesauribile. Nota il vantaggio fornito dal compilatore Rust confermando quando tutti i casi vengono " +"gestiti.\n" +"* `match` ispeziona un campo discriminante nascosto in `enum`.\n" +"* È possibile recuperare il discriminante chiamando `std::mem::discriminant()`\n" +" * Ciò è utile, ad esempio, se si implementa `PartialEq` per strutture in cui il confronto dei valori dei campi non influisce sull'uguaglianza.\n" +"* `WebEvent::Click { ... }` non è esattamente la stessa cosa di `WebEvent::Click(Click)` con una `struct Click { ... }` di primo livello. La " +"versione inline non può implementare tratti, per esempio.\n" +" " + +#: src/enums/sizes.md:1 +#, fuzzy +msgid "# Enum Sizes" +msgstr "# Enum Dimensioni" + +#: src/enums/sizes.md:3 +#, fuzzy +msgid "Rust enums are packed tightly, taking constraints due to alignment into account:" +msgstr "Gli enum di Rust sono imballati strettamente, tenendo conto dei vincoli dovuti all'allineamento:" + +#: src/enums/sizes.md:5 +msgid "" +"```rust,editable\n" +"use std::mem::{align_of, size_of};\n" +"\n" +"macro_rules! dbg_size {\n" +" ($t:ty) => {\n" +" println!(\"{}: size {} bytes, align: {} bytes\",\n" +" stringify!($t), size_of::<$t>(), align_of::<$t>());\n" +" };\n" +"}\n" +"\n" +"enum Foo {\n" +" A,\n" +" B,\n" +"}\n" +"\n" +"fn main() {\n" +" dbg_size!(Foo);\n" +"}\n" +"```" +msgstr "" + +#: src/enums/sizes.md:25 +#, fuzzy +msgid "* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout.html)." +msgstr "* Vedere il [riferimento Rust](https://doc.rust-lang.org/reference/type-layout.html)." + +#: src/enums/sizes.md:31 +msgid "" +" * Internally Rust is using a field (discriminant) to keep track of the enum variant.\n" +"\n" +" * You can control the discriminant if needed (e.g., for compatibility with C):\n" +" \n" +" ```rust,editable\n" +" #[repr(u32)]\n" +" enum Bar {\n" +" A, // 0\n" +" B = 10000,\n" +" C, // 10001\n" +" }\n" +" \n" +" fn main() {\n" +" println!(\"A: {}\", Bar::A as u32);\n" +" println!(\"B: {}\", Bar::B as u32);\n" +" println!(\"C: {}\", Bar::C as u32);\n" +" }\n" +" ```\n" +"\n" +" Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2\n" +" bytes.\n" +"\n" +"\n" +" * Try out other types such as\n" +" \n" +" * `dbg_size!(bool)`: size 1 bytes, align: 1 bytes,\n" +" * `dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche optimization, see below),\n" +" * `dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit machine),\n" +" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer optimization, see below).\n" +"\n" +" * Niche optimization: Rust will merge use unused bit patterns for the enum\n" +" discriminant.\n" +"\n" +" * Null pointer optimization: For [some\n" +" types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees\n" +" that `size_of::()` equals `size_of::>()`.\n" +"\n" +" Example code if you want to show how the bitwise representation *may* look like in practice.\n" +" It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally unsafe.\n" +"\n" +" ```rust,editable\n" +" use std::mem::transmute;\n" +"\n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" println!(\"Bitwise representation of bool\");\n" +" dbg_bits!(false, u8);\n" +" dbg_bits!(true, u8);\n" +"\n" +" println!(\"Bitwise representation of Option\");\n" +" dbg_bits!(None::, u8);\n" +" dbg_bits!(Some(false), u8);\n" +" dbg_bits!(Some(true), u8);\n" +"\n" +" println!(\"Bitwise representation of Option>\");\n" +" dbg_bits!(Some(Some(false)), u8);\n" +" dbg_bits!(Some(Some(true)), u8);\n" +" dbg_bits!(Some(None::), u8);\n" +" dbg_bits!(None::>, u8);\n" +"\n" +" println!(\"Bitwise representation of Option<&i32>\");\n" +" dbg_bits!(None::<&i32>, usize);\n" +" dbg_bits!(Some(&0i32), usize);\n" +" }\n" +" }\n" +" ```\n" +"\n" +" More complex example if you want to discuss what happens when we chain more than 256 `Option`s together.\n" +"\n" +" ```rust,editable\n" +" #![recursion_limit = \"1000\"]\n" +"\n" +" use std::mem::transmute;\n" +" \n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" // Macro to wrap a value in 2^n Some() where n is the number of \"@\" signs.\n" +" // Increasing the recursion limit is required to evaluate this macro.\n" +" macro_rules! many_options {\n" +" ($value:expr) => { Some($value) };\n" +" ($value:expr, @) => {\n" +" Some(Some($value))\n" +" };\n" +" ($value:expr, @ $($more:tt)+) => {\n" +" many_options!(many_options!($value, $($more)+), $($more)+)\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" assert_eq!(many_options!(false), Some(false));\n" +" assert_eq!(many_options!(false, @), Some(Some(false)));\n" +" assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));\n" +"\n" +" println!(\"Bitwise representation of a chain of 128 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" +" dbg_bits!(many_options!(true, @@@@@@@), u8);\n" +"\n" +" println!(\"Bitwise representation of a chain of 256 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(true, @@@@@@@@), u16);\n" +"\n" +" println!(\"Bitwise representation of a chain of 257 Option's.\");\n" +" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" +" }\n" +" }\n" +" ```" +msgstr "" + +#: src/methods.md:3 +#, fuzzy +msgid "" +"Rust allows you to associate functions with your new types. You do this with an\n" +"`impl` block:" +msgstr "" +"Rust ti consente di associare funzioni ai tuoi nuovi tipi. Lo fai con un\n" +"Blocco `impl`:" + +#: src/methods.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn say_hello(&self) {\n" +" println!(\"Hello, my name is {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" peter.say_hello();\n" +"}\n" +"```" +msgstr "" + +#: src/methods.md:31 +#, fuzzy +msgid "" +"* It can be helpful to introduce methods by comparing them to functions.\n" +" * Methods are called on an instance of a type (such as a struct or enum), the first parameter represents the instance as `self`.\n" +" * Developers may choose to use methods to take advantage of method receiver syntax and to help keep them more organized. By using methods we can " +"keep all the implementation code in one predictable place.\n" +"* Point out the use of the keyword `self`, a method receiver. \n" +" * Show that it is an abbreviated term for `self:&Self` and perhaps show how the struct name could also be used. \n" +" * Explain that `Self` is a type alias for the type the `impl` block is in and can be used elsewhere in the block.\n" +" * Note how `self` is used like other structs and dot notation can be used to refer to individual fields.\n" +" * This might be a good time to demonstrate how the `&self` differs from `self` by modifying the code and trying to run say_hello twice. \n" +"* We describe the distinction between method receivers next.\n" +" " +msgstr "" +"* Può essere utile introdurre metodi confrontandoli con funzioni.\n" +" * I metodi vengono chiamati su un'istanza di un tipo (come struct o enum), il primo parametro rappresenta l'istanza come `self`.\n" +" * Gli sviluppatori possono scegliere di utilizzare i metodi per sfruttare la sintassi del ricevitore del metodo e per mantenerli più organizzati. " +"Utilizzando i metodi possiamo mantenere tutto il codice di implementazione in un posto prevedibile.\n" +"* Sottolinea l'uso della parola chiave `self`, un ricevitore di metodo.\n" +" * Mostra che è un termine abbreviato per `self:&Self` e forse mostra come potrebbe essere usato anche il nome struct.\n" +" * Spiega che `Self` è un alias di tipo per il tipo in cui si trova il blocco `impl` e può essere utilizzato altrove nel blocco.\n" +" * Nota come `self` viene utilizzato come altre strutture e la notazione con punto può essere utilizzata per fare riferimento a singoli campi.\n" +" * Questo potrebbe essere un buon momento per dimostrare in che modo `&self` differisce da `self` modificando il codice e provando a eseguire " +"say_hello due volte.\n" +"* Di seguito descriviamo la distinzione tra ricevitori di metodi.\n" +" " + +#: src/methods/receiver.md:1 +#, fuzzy +msgid "# Method Receiver" +msgstr "# Ricevitore del metodo" + +#: src/methods/receiver.md:3 +#, fuzzy +msgid "" +"The `&self` above indicates that the method borrows the object immutably. There\n" +"are other possible receivers for a method:" +msgstr "" +"Il `&self` sopra indica che il metodo prende in prestito l'oggetto in modo immutabile. Là\n" +"sono altri possibili ricevitori per un metodo:" + +#: src/methods/receiver.md:6 +#, fuzzy +msgid "" +"* `&self`: borrows the object from the caller using a shared and immutable\n" +" reference. The object can be used again afterwards.\n" +"* `&mut self`: borrows the object from the caller using a unique and mutable\n" +" reference. The object can be used again afterwards.\n" +"* `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" +"* No receiver: this becomes a static method on the struct. Typically used to\n" +" create constructors which are called `new` by convention." +msgstr "" +"* `&self`: prende in prestito l'oggetto dal chiamante usando un oggetto condiviso e immutabile\n" +" riferimento. L'oggetto può essere riutilizzato in seguito.\n" +"* `&mut self`: prende in prestito l'oggetto dal chiamante usando un oggetto unico e mutabile\n" +" riferimento. L'oggetto può essere riutilizzato in seguito.\n" +"* `self`: assume la proprietà dell'oggetto e lo allontana dal chiamante. IL\n" +" metodo diventa il proprietario dell'oggetto. L'oggetto verrà eliminato (deallocato)\n" +" quando il metodo ritorna, a meno che la sua proprietà non sia esplicita\n" +" trasmesso.\n" +"* `mut self`: come sopra, ma mentre il metodo possiede l'oggetto, può farlo\n" +" muta anche questo. Proprietà completa non significa automaticamente mutabilità.\n" +"* Nessun ricevitore: questo diventa un metodo statico sulla struttura. Tipicamente utilizzato per\n" +" creare costruttori che sono chiamati \"nuovi\" per convenzione." + +#: src/methods/receiver.md:19 +#, fuzzy +msgid "" +"Beyond variants on `self`, there are also\n" +"[special wrapper types](https://doc.rust-lang.org/reference/special-types-and-traits.html)\n" +"allowed to be receiver types, such as `Box`." +msgstr "" +"Oltre alle varianti su \"self\", ci sono anche\n" +"[tipi di wrapper speciali](https://doc.rust-lang.org/reference/special-types-and-traits.html)\n" +"possono essere tipi di ricevitore, come `Box`." + +#: src/methods/receiver.md:25 +#, fuzzy +msgid "" +"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". These constraints always come\n" +"together in Rust due to borrow checker rules, and `self` is no exception. It isn't possible to\n" +"reference a struct from multiple locations and call a mutating (`&mut self`) method on it." +msgstr "" +"Prendi in considerazione l'enfasi su \"condiviso e immutabile\" e \"unico e mutevole\". Questi vincoli arrivano sempre\n" +"insieme in Rust a causa delle regole del correttore in prestito, e \"self\" non fa eccezione. Non è possibile\n" +"fare riferimento a una struttura da più posizioni e chiamare un metodo mutante (`&mut self`) su di essa." + +#: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 +#, fuzzy +msgid "# Example" +msgstr "# Esempio" + +#: src/methods/example.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Race {\n" +" name: String,\n" +" laps: Vec,\n" +"}\n" +"\n" +"impl Race {\n" +" fn new(name: &str) -> Race { // No receiver, a static method\n" +" Race { name: String::from(name), laps: Vec::new() }\n" +" }\n" +"\n" +" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write access to self\n" +" self.laps.push(lap);\n" +" }\n" +"\n" +" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" +" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" +" for (idx, lap) in self.laps.iter().enumerate() {\n" +" println!(\"Lap {idx}: {lap} sec\");\n" +" }\n" +" }\n" +"\n" +" fn finish(self) { // Exclusive ownership of self\n" +" let total = self.laps.iter().sum::();\n" +" println!(\"Race {} is finished, total lap time: {}\", self.name, total);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut race = Race::new(\"Monaco Grand Prix\");\n" +" race.add_lap(70);\n" +" race.add_lap(68);\n" +" race.print_laps();\n" +" race.add_lap(71);\n" +" race.print_laps();\n" +" race.finish();\n" +" // race.add_lap(42);\n" +"}\n" +"```" +msgstr "" + +#: src/methods/example.md:47 +#, fuzzy +msgid "" +"* All four methods here use a different method receiver.\n" +" * You can point out how that changes what the function can do with the variable values and if/how it can be used again in `main`.\n" +" * You can showcase the error that appears when trying to call `finish` twice.\n" +"* Note that although the method receivers are different, the non-static functions are called the same way in the main body. Rust enables automatic " +"referencing and dereferencing when calling methods. Rust automatically adds in the `&`, `*`, `muts` so that that object matches the method " +"signature.\n" +"* You might point out that `print_laps` is using a vector that is iterated over. We describe vectors in more detail in the afternoon. " +msgstr "" +"* Tutti e quattro i metodi qui usano un ricevitore metodo diverso.\n" +" * Puoi indicare come ciò cambia ciò che la funzione può fare con i valori delle variabili e se/come può essere riutilizzata in `main`.\n" +" * Puoi mostrare l'errore che appare quando provi a chiamare `finish` due volte.\n" +"* Si noti che sebbene i destinatari del metodo siano diversi, le funzioni non statiche sono chiamate allo stesso modo nel corpo principale. Rust " +"abilita la referenziazione e la dereferenziazione automatica quando si chiamano i metodi. Rust aggiunge automaticamente `&`, `*`, `muts` in modo che " +"quell'oggetto corrisponda alla firma del metodo.\n" +"* Potresti sottolineare che `print_laps` sta usando un vettore che viene iterato. Descriviamo i vettori in modo più dettagliato nel pomeriggio." + +#: src/pattern-matching.md:1 +#, fuzzy +msgid "# Pattern Matching" +msgstr "# Corrispondenza modello" + +#: src/pattern-matching.md:3 +#, fuzzy +msgid "" +"The `match` keyword let you match a value against one or more _patterns_. The\n" +"comparisons are done from top to bottom and the first match wins." +msgstr "" +"La parola chiave `match` ti consente di confrontare un valore con uno o più _pattern_. IL\n" +"i confronti vengono effettuati dall'alto verso il basso e vince la prima partita." + +#: src/pattern-matching.md:6 +#, fuzzy +msgid "The patterns can be simple values, similarly to `switch` in C and C++:" +msgstr "I modelli possono essere valori semplici, in modo simile a `switch` in C e C++:" + +#: src/pattern-matching.md:8 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let input = 'x';\n" +"\n" +" match input {\n" +" 'q' => println!(\"Quitting\"),\n" +" 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" +" '0'..='9' => println!(\"Number input\"),\n" +" _ => println!(\"Something else\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching.md:21 +#, fuzzy +msgid "The `_` pattern is a wildcard pattern which matches any value." +msgstr "Il modello `_` è un modello di caratteri jolly che corrisponde a qualsiasi valore." + +#: src/pattern-matching.md:26 +#, fuzzy +msgid "" +"* You might point out how some specific characters are being used when in a pattern\n" +" * `|` as an `or`\n" +" * `..` can expand as much as it needs to be\n" +" * `1..=5` represents an inclusive range\n" +" * `_` is a wild card\n" +"* It can be useful to show how binding works, by for instance replacing a wildcard character with a variable, or removing the quotes around `q`.\n" +"* You can demonstrate matching on a reference.\n" +"* This might be a good time to bring up the concept of irrefutable patterns, as the term can show up in error messages.\n" +" " +msgstr "" +"* Potresti sottolineare come vengono utilizzati alcuni caratteri specifici quando in uno schema\n" +" * `|` come `o`\n" +" * `..` può espandersi quanto deve essere\n" +" * `1..=5` rappresenta un intervallo inclusivo\n" +" * `_` è un carattere jolly\n" +"* Può essere utile mostrare come funziona l'associazione, ad esempio sostituendo un carattere jolly con una variabile o rimuovendo le virgolette " +"intorno a `q`.\n" +"* Puoi dimostrare la corrispondenza su un riferimento.\n" +"* Questo potrebbe essere un buon momento per far emergere il concetto di modelli inconfutabili, poiché il termine può apparire nei messaggi di " +"errore.\n" +" " + +#: src/pattern-matching/destructuring-enums.md:1 +#, fuzzy +msgid "# Destructuring Enums" +msgstr "# Destrutturazione delle enum" + +#: src/pattern-matching/destructuring-enums.md:3 +#, fuzzy +msgid "" +"Patterns can also be used to bind variables to parts of your values. This is how\n" +"you inspect the structure of your types. Let us start with a simple `enum` type:" +msgstr "" +"I modelli possono anche essere usati per associare variabili a parti dei tuoi valori. Questo è come\n" +"ispezioni la struttura dei tuoi tipi. Iniziamo con un semplice tipo `enum`:" + +#: src/pattern-matching/destructuring-enums.md:6 +msgid "" +"```rust,editable\n" +"enum Result {\n" +" Ok(i32),\n" +" Err(String),\n" +"}\n" +"\n" +"fn divide_in_two(n: i32) -> Result {\n" +" if n % 2 == 0 {\n" +" Result::Ok(n / 2)\n" +" } else {\n" +" Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let n = 100;\n" +" match divide_in_two(n) {\n" +" Result::Ok(half) => println!(\"{n} divided in two is {half}\"),\n" +" Result::Err(msg) => println!(\"sorry, an error happened: {msg}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:29 +#, fuzzy +msgid "" +"Here we have used the arms to _destructure_ the `Result` value. In the first\n" +"arm, `half` is bound to the value inside the `Ok` variant. In the second arm,\n" +"`msg` is bound to the error message." +msgstr "" +"Qui abbiamo usato le braccia per _destrutturare_ il valore `Result`. Nel primo\n" +"arm, \"half\" è legato al valore all'interno della variante \"Ok\". Nel secondo braccio,\n" +"`msg` è associato al messaggio di errore." + +#: src/pattern-matching/destructuring-enums.md:36 +#, fuzzy +msgid "" +"* The `if`/`else` expression is returning an enum that is later unpacked with a `match`.\n" +"* You can try adding a third variant to the enum definition and displaying the errors when running the code. Point out the places where your code is " +"now inexhaustive and how the compiler tries to give you hints." +msgstr "" +"* L'espressione `if`/`else` restituisce un enum che viene successivamente decompresso con un `match`.\n" +"* Puoi provare ad aggiungere una terza variante alla definizione enum e visualizzare gli errori durante l'esecuzione del codice. Indica i punti in " +"cui il tuo codice è ora inesausto e come il compilatore cerca di darti suggerimenti." + +#: src/pattern-matching/destructuring-structs.md:1 +#, fuzzy +msgid "# Destructuring Structs" +msgstr "# Strutture destrutturanti" + +#: src/pattern-matching/destructuring-structs.md:3 +#, fuzzy +msgid "You can also destructure `structs`:" +msgstr "Puoi anche destrutturare `structs`:" + +#: src/pattern-matching/destructuring-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Foo {\n" +" x: (u32, u32),\n" +" y: u32,\n" +"}\n" +"\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let foo = Foo { x: (1, 2), y: 3 };\n" +" match foo {\n" +" Foo { x: (1, b), y } => println!(\"x.0 = 1, b = {b}, y = {y}\"),\n" +" Foo { y: 2, x: i } => println!(\"y = 2, x = {i:?}\"),\n" +" Foo { y, .. } => println!(\"y = {y}, other fields were ignored\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md:23 +#, fuzzy +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.\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 "" +"* Cambia i valori letterali in `foo` in modo che corrispondano agli altri modelli.\n" +"* Aggiungi un nuovo campo a \"Foo\" e apporta le modifiche al modello secondo necessità.\n" +"* La distinzione tra una cattura e un'espressione costante può essere difficile da fare\n" +" macchiare. Prova a cambiare il \"2\" nel secondo braccio in una variabile e osservalo sottilmente\n" +" non funziona. Cambialo in un `const` e guardalo funzionare di nuovo." + +#: src/pattern-matching/destructuring-arrays.md:1 +#, fuzzy +msgid "# Destructuring Arrays" +msgstr "# Array destrutturanti" + +#: src/pattern-matching/destructuring-arrays.md:3 +#, fuzzy +msgid "You can destructure arrays, tuples, and slices by matching on their elements:" +msgstr "Puoi destrutturare array, tuple e slice abbinando i loro elementi:" + +#: src/pattern-matching/destructuring-arrays.md:5 +msgid "" +"```rust,editable\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let triple = [0, -2, 3];\n" +" println!(\"Tell me about {triple:?}\");\n" +" match triple {\n" +" [0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" [1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:21 +msgid "" +"* Destructuring of slices of unknown length also works with patterns of fixed length.\n" +"\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" inspect(&[0, -2, 3]);\n" +" inspect(&[0, -2, 3, 4]);\n" +" }\n" +"\n" +" #[rustfmt::skip]\n" +" fn inspect(slice: &[i32]) {\n" +" println!(\"Tell me about {slice:?}\");\n" +" match slice {\n" +" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +" }\n" +" ```\n" +" \n" +"* Create a new pattern using `_` to represent an element. \n" +"* Add more values to the array.\n" +"* Point out that how `..` will expand to account for different number of elements.\n" +"* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`" +msgstr "" + +#: src/pattern-matching/match-guards.md:1 +#, fuzzy +msgid "# Match Guards" +msgstr "# Partita Guardie" + +#: src/pattern-matching/match-guards.md:3 +#, fuzzy +msgid "" +"When matching, you can add a _guard_ to a pattern. This is an arbitrary Boolean\n" +"expression which will be executed if the pattern matches:" +msgstr "" +"Durante la corrispondenza, puoi aggiungere una _guard_ a un pattern. Questo è un booleano arbitrario\n" +"espressione che verrà eseguita se il modello corrisponde:" + +#: src/pattern-matching/match-guards.md:6 +msgid "" +"```rust,editable\n" +"#[rustfmt::skip]\n" +"fn main() {\n" +" let pair = (2, -2);\n" +" println!(\"Tell me about {pair:?}\");\n" +" match pair {\n" +" (x, y) if x == y => println!(\"These are twins\"),\n" +" (x, y) if x + y == 0 => println!(\"Antimatter, kaboom!\"),\n" +" (x, _) if x % 2 == 1 => println!(\"The first one is odd\"),\n" +" _ => println!(\"No correlation...\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/pattern-matching/match-guards.md:23 +#, fuzzy +msgid "" +"* Match guards as a separate syntax feature are important and necessary when we wish to concisely express more complex ideas than patterns alone " +"would allow.\n" +"* They are not the same as separate `if` expression inside of the match arm. An `if` expression inside of the branch block (after `=>`) happens " +"after the match arm is selected. Failing the `if` condition inside of that block won't result in other arms\n" +"of the original `match` expression being considered. \n" +"* You can use the variables defined in the pattern in your if expression.\n" +"* The condition defined in the guard applies to every expression in a pattern with an `|`." +msgstr "" +"* Le guardie di corrispondenza come caratteristica di sintassi separata sono importanti e necessarie quando desideriamo esprimere in modo conciso " +"idee più complesse di quanto i soli schemi consentirebbero.\n" +"* Non sono la stessa cosa dell'espressione `if` separata all'interno del braccio della corrispondenza. Un'espressione `if` all'interno del blocco di " +"diramazione (dopo `=>`) si verifica dopo che è stato selezionato il braccio di corrispondenza. Il fallimento della condizione \"if\" all'interno di " +"quel blocco non comporterà altre braccia\n" +"dell'espressione `match` originale considerata.\n" +"* È possibile utilizzare le variabili definite nel modello nell'espressione if.\n" +"* La condizione definita nella guardia si applica a ogni espressione in un modello con un `|`." + +#: src/exercises/day-2/morning.md:1 +#, fuzzy +msgid "# Day 2: Morning Exercises" +msgstr "# Giorno 2: Esercizi mattutini" + +#: src/exercises/day-2/morning.md:3 +#, fuzzy +msgid "We will look at implementing methods in two contexts:" +msgstr "Esamineremo i metodi di implementazione in due contesti:" + +#: src/exercises/day-2/morning.md:5 +#, fuzzy +msgid "" +"* Simple struct which tracks health statistics.\n" +"\n" +"* Multiple structs and enums for a drawing library." +msgstr "" +"* Struttura semplice che tiene traccia delle statistiche sulla salute.\n" +"\n" +"* Strutture multiple ed enum per una libreria di disegni." + +#: src/exercises/day-2/health-statistics.md:1 +#, fuzzy +msgid "# Health Statistics" +msgstr "# Statistiche sanitarie" + +#: src/exercises/day-2/health-statistics.md:3 +#, fuzzy +msgid "" +"You're working on implementing a health-monitoring system. As part of that, you\n" +"need to keep track of users' health statistics." +msgstr "" +"Stai lavorando all'implementazione di un sistema di monitoraggio sanitario. Come parte di questo, tu\n" +"necessità di tenere traccia delle statistiche sulla salute degli utenti." + +#: src/exercises/day-2/health-statistics.md:6 +#, fuzzy +msgid "" +"You'll start with some stubbed functions in an `impl` block as well as a `User`\n" +"struct definition. Your goal is to implement the stubbed out methods on the\n" +"`User` `struct` defined in the `impl` block." +msgstr "" +"Inizierai con alcune funzioni stubbed in un blocco `impl` così come in un `User`\n" +"definizione di struttura. Il tuo obiettivo è implementare i metodi eliminati sul file\n" +"`User` `struct` definito nel blocco `impl`." + +#: src/exercises/day-2/health-statistics.md:10 +#, fuzzy +msgid "" +"Copy the code below to and fill in the missing\n" +"methods:" +msgstr "" +"Copia il codice qui sotto in e inserisci quello mancante\n" +"metodi:" + +#: src/exercises/day-2/health-statistics.md:13 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"struct User {\n" +" name: String,\n" +" age: u32,\n" +" weight: f32,\n" +"}\n" +"\n" +"impl User {\n" +" pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn name(&self) -> &str {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn age(&self) -> u32 {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn weight(&self) -> f32 {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn set_age(&mut self, new_age: u32) {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn set_weight(&mut self, new_weight: f32) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_weight() {\n" +" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.weight(), 155.2);\n" +"}\n" +"\n" +"#[test]\n" +"fn test_set_age() {\n" +" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.age(), 32);\n" +" bob.set_age(33);\n" +" assert_eq!(bob.age(), 33);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:1 +#, fuzzy +msgid "# Polygon Struct" +msgstr "# Struttura poligonale" + +#: src/exercises/day-2/points-polygons.md:3 +#, fuzzy +msgid "" +"We will create a `Polygon` struct which contain some points. Copy the code below\n" +"to and fill in the missing methods to make the\n" +"tests pass:" +msgstr "" +"Creeremo una struttura `Polygon` che contiene alcuni punti. Copia il codice qui sotto\n" +"a e inserire i metodi mancanti per rendere il file\n" +"i test superano:" + +#: src/exercises/day-2/points-polygons.md:7 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub struct Point {\n" +" // add fields\n" +"}\n" +"\n" +"impl Point {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Polygon {\n" +" // add fields\n" +"}\n" +"\n" +"impl Polygon {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Circle {\n" +" // add fields\n" +"}\n" +"\n" +"impl Circle {\n" +" // add methods\n" +"}\n" +"\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/points-polygons.md:117 +#, fuzzy +msgid "" +"Since the method signatures are missing from the problem statements, the key part\n" +"of the exercise is to specify those correctly. You don't have to modify the tests." +msgstr "" +"Poiché le firme del metodo mancano nelle dichiarazioni del problema, la parte chiave\n" +"dell'esercizio è specificarli correttamente. Non è necessario modificare i test." + +#: src/exercises/day-2/points-polygons.md:120 +#, fuzzy +msgid "Other interesting parts of the exercise:" +msgstr "Altre parti interessanti dell'esercizio:" + +#: src/exercises/day-2/points-polygons.md:122 +#, fuzzy +msgid "" +"* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their arguments.\n" +"* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". Note that we do not discuss generics until Day 3." +msgstr "" +"* Deriva un tratto `Copy` per alcune strutture, poiché nei test i metodi a volte non prendono in prestito i loro argomenti.\n" +"* Scopri che il tratto `Add` deve essere implementato affinché due oggetti possano essere aggiunti tramite \"+\". Si noti che non discuteremo di " +"farmaci generici fino al giorno 3." + +#: src/control-flow.md:1 +#, fuzzy +msgid "# Control Flow" +msgstr "# Flusso di controllo" + +#: src/control-flow.md:3 +#, fuzzy +msgid "" +"As we have seen, `if` is an expression in Rust. It is used to conditionally\n" +"evaluate one of two blocks, but the blocks can have a value which then becomes\n" +"the value of the `if` expression. Other control flow expressions work similarly\n" +"in Rust." +msgstr "" +"Come abbiamo visto, \"if\" è un'espressione in Rust. È usato in modo condizionale\n" +"valutare uno dei due blocchi, ma i blocchi possono avere un valore che poi diventa\n" +"il valore dell'espressione \"if\". Altre espressioni del flusso di controllo funzionano in modo simile\n" +"a Ruggine." + +#: src/control-flow/blocks.md:1 +#, fuzzy +msgid "# Blocks" +msgstr "# Blocchi" + +#: src/control-flow/blocks.md:3 +#, fuzzy +msgid "" +"A block in Rust has a value and a type: the value is the last expression of the\n" +"block:" +msgstr "" +"Un blocco in Rust ha un valore e un tipo: il valore è l'ultima espressione del\n" +"bloccare:" + +#: src/control-flow/blocks.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = {\n" +" let y = 10;\n" +" println!(\"y: {y}\");\n" +" let z = {\n" +" let w = {\n" +" 3 + 4\n" +" };\n" +" println!(\"w: {w}\");\n" +" y * w\n" +" };\n" +" println!(\"z: {z}\");\n" +" z - y\n" +" };\n" +" println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:25 +#, fuzzy +msgid "" +"The same rule is used for functions: the value of the function body is the\n" +"return value:" +msgstr "" +"La stessa regola viene utilizzata per le funzioni: il valore del corpo della funzione è the\n" +"valore di ritorno:" + +#: src/control-flow/blocks.md:28 +msgid "" +"```rust,editable\n" +"fn double(x: i32) -> i32 {\n" +" x + x\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"doubled: {}\", double(7));\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:38 +msgid "However if the last expression ends with `;`, then the resulting value and type is `()`." +msgstr "" + +#: src/control-flow/blocks.md:43 +#, fuzzy +msgid "" +"* The point of this slide is to show that blocks have a type and value in Rust. \n" +"* You can show how the value of the block changes by changing the last line in the block. For instance, adding/removing a semicolon or using a " +"`return`.\n" +" " +msgstr "" +"* Lo scopo di questa diapositiva è mostrare che i blocchi hanno un tipo e un valore in Rust.\n" +"* Puoi mostrare come cambia il valore del blocco cambiando l'ultima riga nel blocco. Ad esempio, aggiungendo/rimuovendo un punto e virgola o " +"utilizzando un `return`.\n" +" " + +#: src/control-flow/if-expressions.md:1 +#, fuzzy +msgid "# `if` expressions" +msgstr "# Espressioni `if`" + +#: src/control-flow/if-expressions.md:3 +#, fuzzy +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 "" +"Tu usi [`if`\n" +"espressioni](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-expressions)\n" +"esattamente come le dichiarazioni `if` in altre lingue:" + +#: src/control-flow/if-expressions.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" if x % 2 == 0 {\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:18 +#, fuzzy +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 "" +"Inoltre, puoi usare \"if\" come espressione. L'ultima espressione di ciascuno\n" +"block diventa il valore dell'espressione `if`:" + +#: src/control-flow/if-expressions.md:22 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:35 +msgid "" +"Because `if` is an expression and must have a particular type, both of its branch blocks must have the same type. Consider showing what happens if " +"you add `;` after `x / 2` in the second example." +msgstr "" + +#: src/control-flow/if-let-expressions.md:1 +#, fuzzy +msgid "# `if let` expressions" +msgstr "# Espressioni `if let`" + +#: src/control-flow/if-let-expressions.md:3 +#, fuzzy +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 "" +"Il [`se lasciato`\n" +"espressione](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-let-expressions)\n" +"ti consente di eseguire codice diverso a seconda che un valore corrisponda a un modello:" + +#: src/control-flow/if-let-expressions.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let arg = std::env::args().next();\n" +" if let Some(value) = arg {\n" +" println!(\"Program name: {value}\");\n" +" } else {\n" +" println!(\"Missing name?\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-let-expressions.md:18 src/control-flow/while-let-expressions.md:21 src/control-flow/match-expressions.md:23 +#, fuzzy +msgid "" +"See [pattern matching](../pattern-matching.md) for more details on patterns in\n" +"Rust." +msgstr "" +"Vedi [pattern matching](../pattern-matching.md) per maggiori dettagli sui pattern in\n" +"Ruggine." + +#: 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" +"* A common usage is handling `Some` values when working with `Option`.\n" +"* Unlike `match`, `if let` does not support guard clauses for pattern matching.\n" +"* Since 1.65, a similar [let-else](https://doc.rust-lang.org/rust-by-example/flow_control/let_else.html) construct allows to do a destructuring " +"assignment, or if it fails, have a non-returning block branch (panic/return/break/continue):\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" println!(\"{:?}\", second_word_to_upper(\"foo bar\"));\n" +" }\n" +" \n" +" fn second_word_to_upper(s: &str) -> Option {\n" +" let mut it = s.split(' ');\n" +" let (Some(_), Some(item)) = (it.next(), it.next()) else {\n" +" return None;\n" +" };\n" +" Some(item.to_uppercase())\n" +" }" +msgstr "" + +#: src/control-flow/while-expressions.md:1 +#, fuzzy +msgid "# `while` loops" +msgstr "# `while` si ripete" + +#: src/control-flow/while-expressions.md:3 +#, fuzzy +msgid "" +"The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)\n" +"works very similar to other languages:" +msgstr "" +"La [parola chiave `while`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)\n" +"funziona in modo molto simile ad altre lingue:" + +#: src/control-flow/while-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" while x != 1 {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/while-let-expressions.md:1 +#, fuzzy +msgid "# `while let` loops" +msgstr "# `while let` va in loop" + +#: src/control-flow/while-let-expressions.md:3 +#, fuzzy +msgid "" +"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 "" +"Come con `if let`, c'è un [`while let`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-pattern-loops)\n" +"variante che verifica ripetutamente un valore rispetto a un modello:" + +#: src/control-flow/while-let-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +"\n" +" while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/while-let-expressions.md:17 +#, fuzzy +msgid "" +"Here the iterator returned by `v.iter()` will return a `Option` on every\n" +"call to `next()`. It returns `Some(x)` until it is done, after which it will\n" +"return `None`. The `while let` lets us keep iterating through all items." +msgstr "" +"Qui l'iteratore restituito da `v.iter()` restituirà una `Option` su ogni\n" +"chiamata a `next()`. Restituisce `Some(x)` finché non è finito, dopodiché lo farà\n" +"restituire \"Nessuno\". Il `while let` ci consente di continuare a scorrere tutti gli elementi." + +#: 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" +"* You could rewrite the `while let` loop as an infinite loop with an if statement that breaks when there is no value to unwrap for `iter.next()`. " +"The `while let` provides syntactic sugar for the above scenario.\n" +" " +msgstr "" +"* Fai notare che il ciclo `while let` continuerà finché il valore corrisponde al modello.\n" +"* Potresti riscrivere il ciclo `while let` come un ciclo infinito con un'istruzione if che si interrompe quando non c'è alcun valore da scartare per " +"`iter.next()`. Il `while let` fornisce lo zucchero sintattico per lo scenario di cui sopra.\n" +" " + +#: src/control-flow/for-expressions.md:1 +#, fuzzy +msgid "# `for` loops" +msgstr "# Cicli `for`" + +#: src/control-flow/for-expressions.md:3 +#, fuzzy +msgid "" +"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 "" +"Il [ciclo `for`](https://doc.rust-lang.org/std/keyword.for.html) è strettamente\n" +"relativo al [ciclo `while let`](while-let-expression.md). Lo farà\n" +"chiama automaticamente `into_iter()` sull'espressione e quindi itera su di essa:" + +#: src/control-flow/for-expressions.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +"\n" +" for x in v {\n" +" println!(\"x: {x}\");\n" +" }\n" +" \n" +" for i in (0..10).step_by(2) {\n" +" println!(\"i: {i}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/for-expressions.md:21 +#, fuzzy +msgid "You can use `break` and `continue` here as usual." +msgstr "Puoi usare `break` e `continue` qui come al solito." + +#: src/control-flow/for-expressions.md:25 +#, fuzzy +msgid "" +"* Index iteration is not a special syntax in Rust for just that case.\n" +"* `(0..10)` is a range that implements an `Iterator` trait. \n" +"* `step_by` is a method that returns another `Iterator` that skips every other element. \n" +"* Modify the elements in the vector and explain the compiler errors. Change vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." +msgstr "" +"* L'iterazione dell'indice non è una sintassi speciale in Rust solo per quel caso.\n" +"* `(0..10)` è un intervallo che implementa un tratto `Iterator`.\n" +"* `step_by` è un metodo che restituisce un altro `Iterator` che salta ogni altro elemento.\n" +"* Modifica gli elementi nel vettore e spiega gli errori del compilatore. Cambia il vettore `v` in modo che sia mutabile e il ciclo for in `for x in " +"v.iter_mut()`." + +#: src/control-flow/loop-expressions.md:1 +#, fuzzy +msgid "# `loop` expressions" +msgstr "# Espressioni `loop`" + +#: src/control-flow/loop-expressions.md:3 +#, fuzzy +msgid "" +"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 "" +"Infine, c'è una [parola chiave `loop`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#infinite-loops)\n" +"che crea un loop infinito." + +#: src/control-flow/loop-expressions.md:6 +#, fuzzy +msgid "Here you must either `break` or `return` to stop the loop:" +msgstr "Qui devi \"break\" o \"return\" per interrompere il ciclo:" + +#: src/control-flow/loop-expressions.md:8 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" loop {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" if x == 1 {\n" +" break;\n" +" }\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/loop-expressions.md:27 +#, fuzzy +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 "" +"* Interrompi il `loop` con un valore (ad es. `break 8`) e stampalo.\n" +"* Si noti che `loop` è l'unico costrutto di ciclo che restituisce un valore non banale\n" +" valore. Questo perché è garantito che venga inserito almeno una volta (a differenza di\n" +" cicli `while` e `for`)." + +#: src/control-flow/match-expressions.md:1 +#, fuzzy +msgid "# `match` expressions" +msgstr "# Espressioni `match`" + +#: src/control-flow/match-expressions.md:3 +#, fuzzy +msgid "" +"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 "" +"La [parola chiave `match`](https://doc.rust-lang.org/reference/expressions/match-expr.html)\n" +"viene utilizzato per confrontare un valore con uno o più modelli. In questo senso funziona\n" +"come una serie di espressioni `if let`:" + +#: src/control-flow/match-expressions.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" match std::env::args().next().as_deref() {\n" +" Some(\"cat\") => println!(\"Will do cat things\"),\n" +" Some(\"ls\") => println!(\"Will ls some files\"),\n" +" Some(\"mv\") => println!(\"Let's move some files\"),\n" +" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" +" None => println!(\"Hmm, no program name?\"),\n" +" _ => println!(\"Unknown program name!\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/match-expressions.md:20 +#, fuzzy +msgid "" +"Like `if let`, each match arm must have the same type. The type is the last\n" +"expression of the block, if any. In the example above, the type is `()`." +msgstr "" +"Come `if let`, ogni braccio di corrispondenza deve avere lo stesso tipo. Il tipo è l'ultimo\n" +"espressione del blocco, se esiste. Nell'esempio precedente, il tipo è `()`." + +#: src/control-flow/match-expressions.md:28 +#, fuzzy +msgid "" +"* Save the match expression to a variable and print it out.\n" +"* Remove `.as_deref()` and explain the error.\n" +" * `std::env::args().next()` returns an `Option`, but we cannot match against `String`.\n" +" * `as_deref()` transforms an `Option` to `Option<&T::Target>`. In our case, this turns `Option` into `Option<&str>`.\n" +" * We can now use pattern matching to match against the `&str` inside `Option`." +msgstr "" +"* Salva l'espressione di corrispondenza in una variabile e stampala.\n" +"* Rimuovi `.as_deref()` e spiega l'errore.\n" +" * `std::env::args().next()` restituisce un `Option`, ma non possiamo confrontare `String`.\n" +" * `as_deref()` trasforma una `Opzione` in `Opzione<&T::Target>`. Nel nostro caso, questo trasforma `Option` in `Option<&str>`.\n" +" * Ora possiamo usare il pattern matching per confrontare con `&str` all'interno di `Option`." + +#: src/control-flow/break-continue.md:1 +#, fuzzy +msgid "# `break` and `continue`" +msgstr "# `interrompi` e `continua`" + +#: src/control-flow/break-continue.md:3 +#, fuzzy +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 "" +"- Se vuoi uscire prima da un ciclo, usa [`break`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions),\n" +"- Se vuoi iniziare subito\n" +"l'iterazione successiva usa [`continue`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)." + +#: src/control-flow/break-continue.md:7 +#, fuzzy +msgid "" +"Both `continue` and `break` can optionally take a label argument which is used\n" +"to break out of nested loops:" +msgstr "" +"Sia `continue` che `break` possono facoltativamente accettare un argomento label che viene utilizzato\n" +"per uscire dai cicli nidificati:" + +#: src/control-flow/break-continue.md:10 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +" 'outer: while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" let mut i = 0;\n" +" while i < x {\n" +" println!(\"x: {x}, i: {i}\");\n" +" i += 1;\n" +" if i == 3 {\n" +" break 'outer;\n" +" }\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/break-continue.md:28 +#, fuzzy +msgid "In this case we break the outer loop after 3 iterations of the inner loop." +msgstr "In questo caso interrompiamo il ciclo esterno dopo 3 iterazioni del ciclo interno." + +#: src/std.md:1 +#, fuzzy +msgid "# Standard Library" +msgstr "# Libreria standard" + +#: src/std.md:3 +#, fuzzy +msgid "" +"Rust comes with a standard library which helps establish a set of common types\n" +"used by Rust library and programs. This way, two libraries can work together\n" +"smoothly because they both use the same `String` type." +msgstr "" +"Rust viene fornito con una libreria standard che aiuta a stabilire un insieme di tipi comuni\n" +"utilizzato dalla libreria e dai programmi Rust. In questo modo, due librerie possono lavorare insieme\n" +"senza problemi perché entrambi usano lo stesso tipo `Stringa`." + +#: src/std.md:7 +#, fuzzy +msgid "The common vocabulary types include:" +msgstr "I tipi di vocabolario comuni includono:" + +#: src/std.md:9 +#, fuzzy +msgid "" +"* [`Option` and `Result`](std/option-result.md) types: used for optional values\n" +" and [error handling](error-handling.md).\n" +"\n" +"* [`String`](std/string.md): the default string type used for owned data.\n" +"\n" +"* [`Vec`](std/vec.md): a standard extensible vector.\n" +"\n" +"* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" +" algorithm.\n" +"\n" +"* [`Box`](std/box.md): an owned pointer for heap-allocated data.\n" +"\n" +"* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated data." +msgstr "" +"* [Tipi `Option` e `Result`](std/option-result.md): usati per valori facoltativi\n" +" e [gestione degli errori](error-handling.md).\n" +"\n" +"* [`String`](std/string.md): il tipo di stringa predefinito utilizzato per i dati di proprietà.\n" +"\n" +"* [`Vec`](std/vec.md): un vettore estensibile standard.\n" +"\n" +"* [`HashMap`](std/hashmap.md): un tipo di mappa hash con un hash configurabile\n" +" algoritmo.\n" +"\n" +"* [`Box`](std/box.md): un puntatore di proprietà per i dati allocati nell'heap.\n" +"\n" +"* [`Rc`](std/rc.md): un puntatore con conteggio dei riferimenti condiviso per i dati allocati nell'heap." + +#: src/std.md:25 +#, fuzzy +msgid "" +" * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. \n" +" * `core` includes the most basic types and functions that don't depend on `libc`, allocator or\n" +" even the presence of an operating system. \n" +" * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`.\n" +" * Embedded Rust applications often only use `core`, and sometimes `alloc`." +msgstr "" +" * Infatti, Rust contiene diversi strati della Libreria Standard: `core`, `alloc` e `std`.\n" +" * `core` include i tipi e le funzioni più basilari che non dipendono da `libc`, allocator o\n" +" anche la presenza di un sistema operativo.\n" +" * `alloc` include tipi che richiedono un allocatore heap globale, come `Vec`, `Box` e `Arc`.\n" +" * Le applicazioni embedded di Rust spesso usano solo `core` e talvolta `alloc`." + +#: src/std/option-result.md:1 +#, fuzzy +msgid "# `Option` and `Result`" +msgstr "# `Opzione` e `Risultato`" + +#: src/std/option-result.md:3 +#, fuzzy +msgid "The types represent optional data:" +msgstr "I tipi rappresentano dati facoltativi:" + +#: src/std/option-result.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let numbers = vec![10, 20, 30];\n" +" let first: Option<&i8> = numbers.first();\n" +" println!(\"first: {first:?}\");\n" +"\n" +" let idx: Result = numbers.binary_search(&10);\n" +" println!(\"idx: {idx:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/option-result.md:18 +#, fuzzy +msgid "" +"* `Option` and `Result` are widely used not just in the standard library.\n" +"* `Option<&T>` has zero space overhead compared to `&T`.\n" +"* `Result` is the standard type to implement error handling as we will see on Day 3.\n" +"* `binary_search` returns `Result`.\n" +" * If found, `Result::Ok` holds the index where the element is found.\n" +" * Otherwise, `Result::Err` contains the index where such an element should be inserted." +msgstr "" +"* `Option` e `Result` sono ampiamente usati non solo nella libreria standard.\n" +"* `Option<&T>` ha un sovraccarico di spazio pari a zero rispetto a `&T`.\n" +"* `Result` è il tipo standard per implementare la gestione degli errori, come vedremo il giorno 3.\n" +"* `binary_search` restituisce `Result`.\n" +" * Se trovato, `Result::Ok` contiene l'indice in cui si trova l'elemento.\n" +" * Altrimenti, `Result::Err` contiene l'indice in cui tale elemento dovrebbe essere inserito." + +#: src/std/string.md:1 +#, fuzzy +msgid "# String" +msgstr "# Corda" + +#: src/std/string.md:3 +#, fuzzy +msgid "[`String`][1] is the standard heap-allocated growable UTF-8 string buffer:" +msgstr "[`String`][1] è il buffer di stringa UTF-8 espandibile allocato nell'heap standard:" + +#: src/std/string.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut s1 = String::new();\n" +" s1.push_str(\"Hello\");\n" +" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());\n" +"\n" +" let mut s2 = String::with_capacity(s1.len() + 1);\n" +" s2.push_str(&s1);\n" +" s2.push('!');\n" +" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());\n" +"\n" +" let s3 = String::from(\"🇨🇭\");\n" +" println!(\"s3: len = {}, number of chars = {}\", s3.len(),\n" +" s3.chars().count());\n" +"}\n" +"```" +msgstr "" + +#: src/std/string.md:22 +#, fuzzy +msgid "" +"`String` implements [`Deref`][2], which means that you can call all\n" +"`str` methods on a `String`." +msgstr "" +"`String` implementa [`Deref`][2], il che significa che puoi chiamare tutti\n" +"metodi `str` su una `stringa`." + +#: src/std/string.md:30 +msgid "" +"* `String::new` returns a new empty string, use `String::with_capacity` when you know how much data you want to push to the string.\n" +"* `String::len` returns the size of the `String` in bytes (which can be different from its length in characters).\n" +"* `String::chars` returns an iterator over the actual characters. Note that a `char` can be different from what a human will consider a " +"\"character\" due to [grapheme clusters](https://docs.rs/unicode-segmentation/latest/unicode_segmentation/struct.Graphemes.html).\n" +"* When people refer to strings they could either be talking about `&str` or `String`. \n" +"* When a type implements `Deref`, the compiler will let you transparently call methods from `T`.\n" +" * `String` implements `Deref` which transparently gives it access to `str`'s methods.\n" +" * 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`:\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 +#, fuzzy +msgid "# `Vec`" +msgstr "# `Vec`" + +#: src/std/vec.md:3 +#, fuzzy +msgid "[`Vec`][1] is the standard resizable heap-allocated buffer:" +msgstr "[`Vec`][1] è il buffer ridimensionabile allocato nell'heap standard:" + +#: src/std/vec.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut v1 = Vec::new();\n" +" v1.push(42);\n" +" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());\n" +"\n" +" let mut v2 = Vec::with_capacity(v1.len() + 1);\n" +" v2.extend(v1.iter());\n" +" v2.push(9999);\n" +" println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());\n" +"\n" +" // Canonical macro to initialize a vector with elements.\n" +" let mut v3 = vec![0, 0, 1, 2, 3, 4];\n" +"\n" +" // Retain only the even elements.\n" +" v3.retain(|x| x % 2 == 0);\n" +" println!(\"{v3:?}\");\n" +"\n" +" // Remove consecutive duplicates.\n" +" v3.dedup();\n" +" println!(\"{v3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/vec.md:29 +#, fuzzy +msgid "" +"`Vec` implements [`Deref`][2], which means that you can call slice\n" +"methods on a `Vec`." +msgstr "" +"`Vec` implementa [`Deref`][2], il che significa che puoi chiamare slice\n" +"metodi su un `Vec`." + +#: src/std/vec.md:37 +msgid "" +"* `Vec` is a type of collection, along with `String` and `HashMap`. The data it contains is stored\n" +" on the heap. This means the amount of data doesn't need to be known at compile time. It can grow\n" +" or shrink at runtime.\n" +"* Notice how `Vec` is a generic type too, but you don't have to specify `T` explicitly. As always\n" +" with Rust type inference, the `T` was established during the first `push` call.\n" +"* `vec![...]` is a canonical macro to use instead of `Vec::new()` and it supports adding initial\n" +" elements to the vector.\n" +"* To index the vector you use `[` `]`, but they will panic if out of bounds. Alternatively, using\n" +" `get` will return an `Option`. The `pop` function will remove the last element.\n" +"* Show iterating over a vector and mutating the value:\n" +" `for e in &mut v { *e += 50; }`" +msgstr "" + +#: src/std/hashmap.md:1 +#, fuzzy +msgid "# `HashMap`" +msgstr "# `Mappa hash`" + +#: src/std/hashmap.md:3 +#, fuzzy +msgid "Standard hash map with protection against HashDoS attacks:" +msgstr "Mappa hash standard con protezione dagli attacchi HashDoS:" + +#: src/std/hashmap.md:5 +msgid "" +"```rust,editable\n" +"use std::collections::HashMap;\n" +"\n" +"fn main() {\n" +" let mut page_counts = HashMap::new();\n" +" page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), 207);\n" +" page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" +" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);\n" +"\n" +" if !page_counts.contains_key(\"Les Misérables\") {\n" +" println!(\"We know about {} books, but not Les Misérables.\",\n" +" page_counts.len());\n" +" }\n" +"\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" +" match page_counts.get(book) {\n" +" Some(count) => println!(\"{book}: {count} pages\"),\n" +" None => println!(\"{book} is unknown.\")\n" +" }\n" +" }\n" +"\n" +" // Use the .entry() method to insert a value if nothing is found.\n" +" for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" +" let page_count: &mut i32 = page_counts.entry(book.to_string()).or_insert(0);\n" +" *page_count += 1;\n" +" }\n" +"\n" +" println!(\"{page_counts:#?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/hashmap.md:38 +msgid "" +"* `HashMap` is not defined in the prelude and needs to be brought into scope.\n" +"* Try the following lines of code. The first line will see if a book is in the hashmap and if not return an alternative value. The second line will " +"insert the alternative value in the hashmap if the book is not found.\n" +"\n" +" ```rust,ignore\n" +" let pc1 = page_counts\n" +" .get(\"Harry Potter and the Sorcerer's Stone \")\n" +" .unwrap_or(&336);\n" +" let pc2 = page_counts\n" +" .entry(\"The Hunger Games\".to_string())\n" +" .or_insert(374);\n" +" ```\n" +"* Unlike `vec!`, there is unfortunately no standard `hashmap!` macro.\n" +" * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], which allows us to easily initialize a hash map from a literal array:\n" +"\n" +" ```rust,ignore\n" +" let page_counts = HashMap::from([\n" +" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" +" (\"The Hunger Games\".to_string(), 374),\n" +" ]);\n" +" ```\n" +"\n" +" * Alternatively HashMap can be built from any `Iterator` which yields key-value tuples.\n" +"* We are showing `HashMap`, and avoid using `&str` as key to make examples easier. Using references in collections can, of course, be " +"done,\n" +" but it can lead into complications with the borrow checker.\n" +" * Try removing `to_string()` from the example above and see if it still compiles. Where do you think we might run into issues?" +msgstr "" + +#: src/std/box.md:1 +#, fuzzy +msgid "# `Box`" +msgstr "# `Scatola`" + +#: src/std/box.md:3 +#, fuzzy +msgid "[`Box`][1] is an owned pointer to data on the heap:" +msgstr "[`Box`][1] è un puntatore di proprietà ai dati sull'heap:" + +#: src/std/box.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let five = Box::new(5);\n" +" println!(\"five: {}\", *five);\n" +"}\n" +"```" +msgstr "" + +#: src/std/box.md:13 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - -. .- - - - - - -.\n" +": : : :\n" +": five : : :\n" +": +-----+ : : +-----+ :\n" +": | o---|---+-----+-->| 5 | :\n" +": +-----+ : : +-----+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - -' `- - - - - - -'\n" +"```" +msgstr "" + +#: src/std/box.md:26 +#, fuzzy +msgid "" +"`Box` implements `Deref`, which means that you can [call methods\n" +"from `T` directly on a `Box`][2]." +msgstr "" +"`Box` implementa `Deref`, il che significa che puoi [chiamare metodi\n" +"da `T` direttamente su un `Box`][2]." + +#: src/std/box.md:34 +#, fuzzy +msgid "" +"* `Box` is like `std::unique_ptr` in C++, except that it's guaranteed to be not null. \n" +"* In the above example, you can even leave out the `*` in the `println!` statement thanks to `Deref`. \n" +"* A `Box` can be useful when you:\n" +" * have a type whose size that can't be known at compile time, but the Rust compiler wants to know an exact size.\n" +" * want to transfer ownership of a large amount of data. To avoid copying large amounts of data on the stack, instead store the data on the heap " +"in a `Box` so only the pointer is moved." +msgstr "" +"* `Box` è come `std::unique_ptr` in C++, tranne per il fatto che è garantito che non sia nullo.\n" +"* Nell'esempio sopra, puoi anche tralasciare `*` nell'istruzione `println!` grazie a `Deref`.\n" +"* Una `Box` può essere utile quando:\n" +" * hanno un tipo la cui dimensione non può essere conosciuta in fase di compilazione, ma il compilatore Rust vuole conoscere una dimensione " +"esatta.\n" +" * desidera trasferire la proprietà di una grande quantità di dati. Per evitare di copiare grandi quantità di dati nello stack, archivia invece i " +"dati nell'heap in un \"Box\" in modo che venga spostato solo il puntatore." + +#: src/std/box-recursive.md:1 +#, fuzzy +msgid "# Box with Recursive Data Structures" +msgstr "# Box con strutture dati ricorsive" + +#: src/std/box-recursive.md:3 +#, fuzzy +msgid "Recursive data types or data types with dynamic sizes need to use a `Box`:" +msgstr "I tipi di dati ricorsivi o i tipi di dati con dimensioni dinamiche devono utilizzare un `Box`:" + +#: src/std/box-recursive.md:5 src/std/box-niche.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"enum List {\n" +" Cons(T, Box>),\n" +" Nil,\n" +"}\n" +"\n" +"fn main() {\n" +" let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));\n" +" println!(\"{list:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/box-recursive.md:18 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": list : : :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----+ :\n" +": | Cons | 1 | o--+----+-----+--->| Cons | 2 | o--+--->| Nil | // | // | :\n" +": +------+----+----+ : : +------+----+----+ +------+----+----+ :\n" +": : : :\n" +": : : :\n" +"'- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/std/box-recursive.md:33 +#, fuzzy +msgid "" +"* If the `Box` was not used here and we attempted to embed a `List` directly into the `List`,\n" +"the compiler would not compute a fixed size of the struct in memory, it would look infinite.\n" +"\n" +"* `Box` solves this problem as it has the same size as a regular pointer and just points at the next\n" +"element of the `List` in the heap.\n" +"\n" +"* Remove the `Box` in the List definition and show the compiler error. \"Recursive with indirection\" is a hint you might want to use a Box or " +"reference of some kind, instead of storing a value directly. \n" +" " +msgstr "" +"* Se la `Box` non è stata utilizzata qui e abbiamo tentato di incorporare una `Lista` direttamente nella `Lista`,\n" +"il compilatore non calcolerebbe una dimensione fissa della struttura in memoria, sembrerebbe infinita.\n" +"\n" +"* `Box` risolve questo problema poiché ha le stesse dimensioni di un normale puntatore e punta solo al successivo\n" +"elemento della \"Lista\" nell'heap.\n" +"\n" +"* Rimuovi il `Box` nella definizione dell'elenco e mostra l'errore del compilatore. \"Ricorsivo con indiretto\" è un suggerimento che potresti voler " +"utilizzare un Box o un riferimento di qualche tipo, invece di memorizzare direttamente un valore.\n" +" " + +#: src/std/box-niche.md:1 +#, fuzzy +msgid "# Niche Optimization" +msgstr "# Ottimizzazione di nicchia" + +#: src/std/box-niche.md:16 +#, fuzzy +msgid "" +"A `Box` cannot be empty, so the pointer is always valid and non-`null`. This\n" +"allows the compiler to optimize the memory layout:" +msgstr "" +"Un `Box` non può essere vuoto, quindi il puntatore è sempre valido e non `null`. Questo\n" +"consente al compilatore di ottimizzare il layout della memoria:" + +#: src/std/box-niche.md:19 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": list : : :\n" +": +----+----+ : : +----+----+ +----+------+ :\n" +": | 1 | o--+-----------+-----+--->| 2 | o--+--->| // | null | :\n" +": +----+----+ : : +----+----+ +----+------+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/std/rc.md:1 +#, fuzzy +msgid "# `Rc`" +msgstr "# `Rc`" + +#: src/std/rc.md:3 +#, fuzzy +msgid "" +"[`Rc`][1] is a reference-counted shared pointer. Use this when you need to refer\n" +"to the same data from multiple places:" +msgstr "" +"[`Rc`][1] è un puntatore condiviso con conteggio dei riferimenti. Usalo quando hai bisogno di fare riferimento\n" +"agli stessi dati da più posizioni:" + +#: src/std/rc.md:6 +msgid "" +"```rust,editable\n" +"use std::rc::Rc;\n" +"\n" +"fn main() {\n" +" let mut a = Rc::new(10);\n" +" let mut b = Rc::clone(&a);\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/std/rc.md:18 +#, fuzzy +msgid "" +"* If you need to mutate the data inside an `Rc`, you will need to wrap the data in\n" +" a type such as [`Cell` or `RefCell`][2].\n" +"* See [`Arc`][3] if you are in a multi-threaded context.\n" +"* You can *downgrade* a shared pointer into a [`Weak`][4] pointer to create cycles\n" +" that will get dropped." +msgstr "" +"* Se hai bisogno di mutare i dati all'interno di un `Rc`, dovrai racchiudere i dati\n" +" un tipo come [`Cell` o `RefCell`][2].\n" +"* Vedere [`Arc`][3] se ci si trova in un contesto multi-thread.\n" +"* Puoi *declassare* un puntatore condiviso in un puntatore [`Weak`][4] per creare cicli\n" +" che verrà abbandonato." + +#: src/std/rc.md:31 +#, fuzzy +msgid "" +"* `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" +"* `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" +"* `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 "" +"* Il conteggio di `Rc` assicura che il suo valore contenuto sia valido finché ci sono riferimenti.\n" +"* Come `std::shared_ptr` di C++.\n" +"* `Rc::clone` è economico: crea un puntatore alla stessa allocazione e aumenta il conteggio dei riferimenti. Non crea un clone profondo e " +"generalmente può essere ignorato quando si cercano problemi di prestazioni nel codice.\n" +"* `make_mut` in realtà clona il valore interno se necessario (\"clone-on-write\") e restituisce un riferimento mutabile.\n" +"* Usa `Rc::strong_count` per controllare il conteggio dei riferimenti.\n" +"* Confronta i diversi tipi di dati menzionati. `Box` abilita i prestiti (im)mutabili che vengono applicati in fase di compilazione. `RefCell` " +"abilita i prestiti (im)mutabili che vengono applicati in fase di esecuzione e andranno in panico se falliscono in fase di esecuzione.\n" +"* `Rc::downgrade` fornisce un oggetto *debolmente contato* a\n" +" creare cicli che verranno eliminati correttamente (probabilmente in combinazione con\n" +" `RefCella`)." + +#: src/std/rc.md:41 +msgid "" +"```rust,editable\n" +"use std::rc::{Rc, Weak};\n" +"use std::cell::RefCell;\n" +"\n" +"#[derive(Debug)]\n" +"struct Node {\n" +" value: i64,\n" +" parent: Option>>,\n" +" children: Vec>>,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut root = Rc::new(RefCell::new(Node {\n" +" value: 42,\n" +" parent: None,\n" +" children: vec![],\n" +" }));\n" +" let child = Rc::new(RefCell::new(Node {\n" +" value: 43,\n" +" children: vec![],\n" +" parent: Some(Rc::downgrade(&root))\n" +" }));\n" +" root.borrow_mut().children.push(child);\n" +"\n" +" println!(\"graph: {root:#?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/modules.md:1 +#, fuzzy +msgid "# Modules" +msgstr "# Moduli" + +#: src/modules.md:3 +#, fuzzy +msgid "We have seen how `impl` blocks let us namespace functions to a type." +msgstr "Abbiamo visto come i blocchi `impl` ci permettono di utilizzare lo spazio dei nomi per un tipo." + +#: src/modules.md:5 +#, fuzzy +msgid "Similarly, `mod` lets us namespace types and functions:" +msgstr "Allo stesso modo, `mod` ci consente tipi e funzioni dello spazio dei nomi:" + +#: src/modules.md:7 +msgid "" +"```rust,editable\n" +"mod foo {\n" +" pub fn do_something() {\n" +" println!(\"In the foo module\");\n" +" }\n" +"}\n" +"\n" +"mod bar {\n" +" pub fn do_something() {\n" +" println!(\"In the bar module\");\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" foo::do_something();\n" +" bar::do_something();\n" +"}\n" +"```" +msgstr "" + +#: src/modules.md:28 +#, fuzzy +msgid "" +"* Packages provide functionality and include a `Cargo.toml` file that describes how to build a bundle of 1+ crates.\n" +"* Crates are a tree of modules, where a binary crate creates an executable and a library crate compiles to a library.\n" +"* Modules define organization, scope, and are the focus of this section." +msgstr "" +"* I pacchetti forniscono funzionalità e includono un file `Cargo.toml` che descrive come costruire un pacchetto di 1+ casse.\n" +"* I crate sono un albero di moduli, in cui un crate binario crea un eseguibile e un crate di libreria viene compilato in una libreria.\n" +"* I moduli definiscono l'organizzazione, l'ambito e sono il fulcro di questa sezione." + +#: src/modules/visibility.md:1 +#, fuzzy +msgid "# Visibility" +msgstr "# Visibilità" + +#: src/modules/visibility.md:3 +#, fuzzy +msgid "Modules are a privacy boundary:" +msgstr "I moduli sono un limite di privacy:" + +#: src/modules/visibility.md:5 +#, fuzzy +msgid "" +"* Module items are private by default (hides implementation details).\n" +"* Parent and sibling items are always visible.\n" +"* In other words, if an item is visible in module `foo`, it's visible in all the\n" +" descendants of `foo`." +msgstr "" +"* Gli elementi del modulo sono privati per impostazione predefinita (nasconde i dettagli di implementazione).\n" +"* Gli elementi dei genitori e dei fratelli sono sempre visibili.\n" +"* In altre parole, se un elemento è visibile nel modulo `foo`, è visibile in tutti i file\n" +" discendenti di `foo`." + +#: src/modules/visibility.md:10 +msgid "" +"```rust,editable\n" +"mod outer {\n" +" fn private() {\n" +" println!(\"outer::private\");\n" +" }\n" +"\n" +" pub fn public() {\n" +" println!(\"outer::public\");\n" +" }\n" +"\n" +" mod inner {\n" +" fn private() {\n" +" println!(\"outer::inner::private\");\n" +" }\n" +"\n" +" pub fn public() {\n" +" println!(\"outer::inner::public\");\n" +" super::private();\n" +" }\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" outer::public();\n" +"}\n" +"```" +msgstr "" + +#: src/modules/visibility.md:39 +#, fuzzy +msgid "* Use the `pub` keyword to make modules public." +msgstr "* Usa la parola chiave `pub` per rendere pubblici i moduli." + +#: src/modules/visibility.md:41 +#, fuzzy +msgid "Additionally, there are advanced `pub(...)` specifiers to restrict the scope of public visibility." +msgstr "Inoltre, ci sono specificatori avanzati `pub(...)` per restringere l'ambito della visibilità pubblica." + +#: src/modules/visibility.md:43 +#, fuzzy +msgid "" +"* See the [Rust Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself).\n" +"* Configuring `pub(crate)` visibility is a common pattern.\n" +"* Less commonly, you can give visibility to a specific path.\n" +"* In any case, visibility must be granted to an ancestor module (and all of its descendants)." +msgstr "" +"* Vedere il [riferimento Rust](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself).\n" +"* La configurazione della visibilità di `pub(crate)` è un modello comune.\n" +"* Meno comunemente, puoi dare visibilità a un percorso specifico.\n" +"* In ogni caso, la visibilità deve essere concessa a un modulo predecessore (ea tutti i suoi discendenti)." + +#: src/modules/paths.md:1 +#, fuzzy +msgid "# Paths" +msgstr "# Percorsi" + +#: src/modules/paths.md:3 +#, fuzzy +msgid "Paths are resolved as follows:" +msgstr "I percorsi sono risolti come segue:" + +#: src/modules/paths.md:5 +#, fuzzy +msgid "" +"1. As a relative path:\n" +" * `foo` or `self::foo` refers to `foo` in the current module,\n" +" * `super::foo` refers to `foo` in the parent module.\n" +"\n" +"2. As an absolute path:\n" +" * `crate::foo` refers to `foo` in the root of the current crate,\n" +" * `bar::foo` refers to `foo` in the `bar` crate." +msgstr "" +"1. Come percorso relativo:\n" +" * `foo` o `self::foo` si riferisce a `foo` nel modulo corrente,\n" +" * `super::foo` fa riferimento a `foo` nel modulo genitore.\n" +"\n" +"2. Come percorso assoluto:\n" +" * `crate::foo` fa riferimento a `foo` nella radice del crate corrente,\n" +" * `bar::foo` si riferisce a `foo` nella cassa `bar`." + +#: src/modules/paths.md:13 +#, fuzzy +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 "" +"Un modulo può portare i simboli di un altro modulo nell'ambito con `use`.\n" +"In genere vedrai qualcosa di simile nella parte superiore di ogni modulo:" + +#: 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" +msgstr "# Gerarchia del file system" + +#: src/modules/filesystem.md:3 +#, fuzzy +msgid "The module content can be omitted:" +msgstr "Il contenuto del modulo può essere omesso:" + +#: src/modules/filesystem.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"mod garden;\n" +"```" +msgstr "" + +#: src/modules/filesystem.md:9 +#, fuzzy +msgid "The `garden` module content is found at:" +msgstr "Il contenuto del modulo `garden` si trova in:" + +#: src/modules/filesystem.md:11 +#, fuzzy +msgid "" +"* `src/garden.rs` (modern Rust 2018 style)\n" +"* `src/garden/mod.rs` (older Rust 2015 style)" +msgstr "" +"* `src/garden.rs` (moderno stile Rust 2018)\n" +"* `src/garden/mod.rs` (vecchio stile Rust 2015)" + +#: src/modules/filesystem.md:14 +#, fuzzy +msgid "Similarly, a `garden::vegetables` module can be found at:" +msgstr "Allo stesso modo, un modulo `garden::vegetables` può essere trovato in:" + +#: src/modules/filesystem.md:16 +#, fuzzy +msgid "" +"* `src/garden/vegetables.rs` (modern Rust 2018 style)\n" +"* `src/garden/vegetables/mod.rs` (older Rust 2015 style)" +msgstr "" +"* `src/garden/vegetables.rs` (moderno stile Rust 2018)\n" +"* `src/garden/vegetables/mod.rs` (vecchio stile Rust 2015)" + +#: src/modules/filesystem.md:19 +#, fuzzy +msgid "The `crate` root is in:" +msgstr "La radice di `crate` è in:" + +#: src/modules/filesystem.md:21 +#, fuzzy +msgid "" +"* `src/lib.rs` (for a library crate)\n" +"* `src/main.rs` (for a binary crate)" +msgstr "" +"* `src/lib.rs` (per un crate di libreria)\n" +"* `src/main.rs` (per una cassa binaria)" + +#: src/modules/filesystem.md:24 +#, fuzzy +msgid "" +"Modules defined in files can be documented, too, using \"inner doc comments\".\n" +"These document the item that contains them -- in this case, a module." +msgstr "" +"Anche i moduli definiti nei file possono essere documentati utilizzando \"commenti interni al documento\".\n" +"Questi documentano l'elemento che li contiene, in questo caso un modulo." + +#: src/modules/filesystem.md:27 +msgid "" +"```rust,editable,compile_fail\n" +"//! This module implements the garden, including a highly performant germination\n" +"//! implementation.\n" +"\n" +"// Re-export types from this module.\n" +"pub use seeds::SeedPacket;\n" +"pub use garden::Garden;\n" +"\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:44 +msgid "" +"* The change from `module/mod.rs` to `module.rs` doesn't preclude the use of submodules in Rust 2018.\n" +" (It was mandatory in Rust 2015.)\n" +"\n" +" The following is valid:\n" +"\n" +" ```ignore\n" +" src/\n" +" ├── main.rs\n" +" ├── top_module.rs\n" +" └── top_module/\n" +" └── sub_module.rs\n" +" ```\n" +"\n" +"* The main reason for the change is to prevent many files named `mod.rs`, which can be hard\n" +" to distinguish in IDEs.\n" +"\n" +"* Rust will look for modules in `modulename/mod.rs` and `modulename.rs`, but this can be changed\n" +" with a compiler directive:\n" +"\n" +" ```rust,ignore\n" +" #[path = \"some/path.rs\"]\n" +" mod some_module { }\n" +" ```\n" +"\n" +" This is useful, for example, if you would like to place tests for a module in a file named\n" +" `some_module_test.rs`, similar to the convention in Go." +msgstr "" + +#: src/exercises/day-2/afternoon.md:1 +#, fuzzy +msgid "# Day 2: Afternoon Exercises" +msgstr "# Giorno 2: Esercizi pomeridiani" + +#: src/exercises/day-2/afternoon.md:3 +#, fuzzy +msgid "The exercises for this afternoon will focus on strings and iterators." +msgstr "Gli esercizi di questo pomeriggio si concentreranno su stringhe e iteratori." + +#: src/exercises/day-2/luhn.md:1 +#, fuzzy +msgid "# Luhn Algorithm" +msgstr "# Algoritmo di Luhn" + +#: src/exercises/day-2/luhn.md:3 +#, fuzzy +msgid "" +"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used to\n" +"validate credit card numbers. The algorithm takes a string as input and does the\n" +"following to validate the credit card number:" +msgstr "" +"L'[algoritmo di Luhn](https://en.wikipedia.org/wiki/Luhn_algorithm) viene utilizzato per\n" +"convalidare i numeri di carta di credito. L'algoritmo prende una stringa come input e fa il\n" +"seguente per convalidare il numero della carta di credito:" + +#: src/exercises/day-2/luhn.md:7 +#, fuzzy +msgid "" +"* Ignore all spaces. Reject number with less than two digits.\n" +"\n" +"* Moving from right to left, double every second digit: for the number `1234`,\n" +" we double `3` and `1`.\n" +"\n" +"* After doubling a digit, sum the digits. So doubling `7` becomes `14` which\n" +" becomes `5`.\n" +"\n" +"* Sum all the undoubled and doubled digits.\n" +"\n" +"* The credit card number is valid if the sum ends with `0`." +msgstr "" +"* Ignora tutti gli spazi. Rifiuta il numero con meno di due cifre.\n" +"\n" +"* Spostandoti da destra a sinistra, raddoppia ogni seconda cifra: per il numero `1234`,\n" +" raddoppiamo \"3\" e \"1\".\n" +"\n" +"* Dopo aver raddoppiato una cifra, somma le cifre. Quindi raddoppiando \"7\" diventa \"14\" which\n" +" diventa \"5\".\n" +"\n" +"* Somma tutte le cifre non raddoppiate e raddoppiate.\n" +"\n" +"* Il numero della carta di credito è valido se la somma termina con `0`." + +#: src/exercises/day-2/luhn.md:19 +#, fuzzy +msgid "" +"Copy the following code to and implement the\n" +"function:" +msgstr "" +"Copia il seguente codice in e implementa il file\n" +"funzione:" + +#: src/exercises/day-2/luhn.md:23 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:1 +#, fuzzy +msgid "# Strings and Iterators" +msgstr "# Stringhe e iteratori" + +#: src/exercises/day-2/strings-iterators.md:3 +#, fuzzy +msgid "" +"In this exercise, you are implementing a routing component of a web server. The\n" +"server is configured with a number of _path prefixes_ which are matched against\n" +"_request paths_. The path prefixes can contain a wildcard character which\n" +"matches a full segment. See the unit tests below." +msgstr "" +"In questo esercizio, implementerai un componente di instradamento di un server web. IL\n" +"il server è configurato con un numero di _prefissi di percorso_ che vengono confrontati\n" +"_percorsi di richiesta_. I prefissi di percorso possono contenere un carattere jolly che\n" +"corrisponde a un segmento completo. Vedere i test unitari di seguito." + +#: src/exercises/day-2/strings-iterators.md:8 +#, fuzzy +msgid "" +"Copy the following code to and make the tests\n" +"pass. Try avoiding allocating a `Vec` for your intermediate results:" +msgstr "" +"Copia il seguente codice in ed esegui i test\n" +"passaggio. Prova a evitare di assegnare un `Vec` per i tuoi risultati intermedi:" + +#: src/exercises/day-2/strings-iterators.md:12 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"```" +msgstr "" + +#: src/welcome-day-3.md:1 +#, fuzzy +msgid "# Welcome to Day 3" +msgstr "# Benvenuto al giorno 3" + +#: src/welcome-day-3.md:3 +#, fuzzy +msgid "Today, we will cover some more advanced topics of Rust:" +msgstr "Oggi tratteremo alcuni argomenti più avanzati di Rust:" + +#: src/welcome-day-3.md:5 +#, fuzzy +msgid "" +"* Traits: deriving traits, default methods, and important standard library\n" +" traits.\n" +"\n" +"* Generics: generic data types, generic methods, monomorphization, and trait\n" +" objects.\n" +"\n" +"* Error handling: panics, `Result`, and the try operator `?`.\n" +"\n" +"* Testing: unit tests, documentation tests, and integration tests.\n" +"\n" +"* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" +" functions." +msgstr "" +"* Tratti: tratti derivati, metodi predefiniti e importante libreria standard\n" +" tratti.\n" +"\n" +"* Generici: tipi di dati generici, metodi generici, monomorfizzazione e tratto\n" +" oggetti.\n" +"\n" +"* Gestione degli errori: panic, `Result` e l'operatore try `?`.\n" +"\n" +"* Test: unit test, test di documentazione e test di integrazione.\n" +"\n" +"* Unsafe Rust: puntatori grezzi, variabili statiche, funzioni non sicure ed extern\n" +" funzioni." + +#: src/generics.md:1 +#, fuzzy +msgid "# Generics" +msgstr "# Generici" + +#: src/generics.md:3 +#, fuzzy +msgid "" +"Rust support generics, which lets you abstract an algorithm (such as sorting)\n" +"over the types used in the algorithm." +msgstr "" +"Rust supporta i generici, che ti consentono di astrarre un algoritmo (come l'ordinamento)\n" +"sui tipi utilizzati nell'algoritmo." + +#: src/generics/data-types.md:1 +#, fuzzy +msgid "# Generic Data Types" +msgstr "# Tipi di dati generici" + +#: src/generics/data-types.md:3 +#, fuzzy +msgid "You can use generics to abstract over the concrete field type:" +msgstr "Puoi utilizzare i generici per astrarre sul tipo di campo concreto:" + +#: src/generics/data-types.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point {\n" +" x: T,\n" +" y: T,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Point { x: 5, y: 10 };\n" +" let float = Point { x: 1.0, y: 4.0 };\n" +" println!(\"{integer:?} and {float:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/generics/data-types.md:21 +msgid "" +"* Try declaring a new variable `let p = Point { x: 5, y: 10.0 };`.\n" +"\n" +"* Fix the code to allow points that have elements of different types." +msgstr "" + +#: src/generics/methods.md:1 +#, fuzzy +msgid "# Generic Methods" +msgstr "# Metodi generici" + +#: src/generics/methods.md:3 +#, fuzzy +msgid "You can declare a generic type on your `impl` block:" +msgstr "Puoi dichiarare un tipo generico sul tuo blocco `impl`:" + +#: src/generics/methods.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(T, T);\n" +"\n" +"impl Point {\n" +" fn x(&self) -> &T {\n" +" &self.0 // + 10\n" +" }\n" +"\n" +" // fn set_x(&mut self, x: T)\n" +"}\n" +"\n" +"fn main() {\n" +" let p = Point(5, 10);\n" +" println!(\"p.x = {}\", p.x());\n" +"}\n" +"```" +msgstr "" + +#: src/generics/methods.md:25 +#, fuzzy +msgid "" +"* *Q:* Why `T` is specified twice in `impl Point {}`? Isn't that redundant?\n" +" * This is because it is a generic implementation section for generic type. They are independently generic.\n" +" * It means these methods are defined for any `T`.\n" +" * It is possible to write `impl Point { .. }`. \n" +" * `Point` is still generic and you can use `Point`, but methods in this block will only be available for `Point`." +msgstr "" +"* *D:* Perché `T` è specificato due volte in `impl Point {}`? Non è ridondante?\n" +" * Questo perché si tratta di una sezione di implementazione generica per un tipo generico. Sono indipendentemente generici.\n" +" * Significa che questi metodi sono definiti per qualsiasi `T`.\n" +" * È possibile scrivere `impl Point { .. }`.\n" +" * `Point` è ancora generico e puoi usare `Point`, ma i metodi in questo blocco saranno disponibili solo per `Point`." + +#: src/generics/monomorphization.md:1 +#, fuzzy +msgid "# Monomorphization" +msgstr "# Monomorfizzazione" + +#: src/generics/monomorphization.md:3 +#, fuzzy +msgid "Generic code is turned into non-generic code based on the call sites:" +msgstr "Il codice generico viene trasformato in codice non generico in base ai siti di chiamata:" + +#: src/generics/monomorphization.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let integer = Some(5);\n" +" let float = Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:12 +#, fuzzy +msgid "behaves as if you wrote" +msgstr "si comporta come se scrivessi" + +#: src/generics/monomorphization.md:14 +msgid "" +"```rust,editable\n" +"enum Option_i32 {\n" +" Some(i32),\n" +" None,\n" +"}\n" +"\n" +"enum Option_f64 {\n" +" Some(f64),\n" +" None,\n" +"}\n" +"\n" +"fn main() {\n" +" let integer = Option_i32::Some(5);\n" +" let float = Option_f64::Some(5.0);\n" +"}\n" +"```" +msgstr "" + +#: src/generics/monomorphization.md:31 +#, fuzzy +msgid "" +"This is a zero-cost abstraction: you get exactly the same result as if you had\n" +"hand-coded the data structures without the abstraction." +msgstr "" +"Questa è un'astrazione a costo zero: ottieni esattamente lo stesso risultato che se avessi\n" +"codificato a mano le strutture dati senza l'astrazione." + +#: src/traits.md:1 +#, fuzzy +msgid "# Traits" +msgstr "# Tratti" + +#: src/traits.md:3 +#, fuzzy +msgid "Rust lets you abstract over types with traits. They're similar to interfaces:" +msgstr "Rust ti consente di astrarre sui tipi con tratti. Sono simili alle interfacce:" + +#: src/traits.md:5 +msgid "" +"```rust,editable\n" +"trait Pet {\n" +" fn name(&self) -> String;\n" +"}\n" +"\n" +"struct Dog {\n" +" name: String,\n" +"}\n" +"\n" +"struct Cat;\n" +"\n" +"impl Pet for Dog {\n" +" fn name(&self) -> String {\n" +" self.name.clone()\n" +" }\n" +"}\n" +"\n" +"impl Pet for Cat {\n" +" fn name(&self) -> String {\n" +" String::from(\"The cat\") // No name, cats won't respond to it anyway.\n" +" }\n" +"}\n" +"\n" +"fn greet(pet: &P) {\n" +" println!(\"Who's a cutie? {} is!\", pet.name());\n" +"}\n" +"\n" +"fn main() {\n" +" let fido = Dog { name: \"Fido\".into() };\n" +" greet(&fido);\n" +"\n" +" let captain_floof = Cat;\n" +" greet(&captain_floof);\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-objects.md:1 +#, fuzzy +msgid "# Trait Objects" +msgstr "# Oggetti tratto" + +#: src/traits/trait-objects.md:3 +#, fuzzy +msgid "Trait objects allow for values of different types, for instance in a collection:" +msgstr "Gli oggetti tratto consentono valori di tipi diversi, ad esempio in una raccolta:" + +#: src/traits/trait-objects.md:5 +msgid "" +"```rust,editable\n" +"trait Pet {\n" +" fn name(&self) -> String;\n" +"}\n" +"\n" +"struct Dog {\n" +" name: String,\n" +"}\n" +"\n" +"struct Cat;\n" +"\n" +"impl Pet for Dog {\n" +" fn name(&self) -> String {\n" +" self.name.clone()\n" +" }\n" +"}\n" +"\n" +"impl Pet for Cat {\n" +" fn name(&self) -> String {\n" +" String::from(\"The cat\") // No name, cats won't respond to it anyway.\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let pets: Vec> = vec![\n" +" Box::new(Cat),\n" +" Box::new(Dog { name: String::from(\"Fido\") }),\n" +" ];\n" +" for pet in pets {\n" +" println!(\"Hello {}!\", pet.name());\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-objects.md:40 +#, fuzzy +msgid "Memory layout after allocating `pets`:" +msgstr "Layout della memoria dopo l'allocazione di \"animali domestici\":" + +#: src/traits/trait-objects.md:42 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": pets : : :\n" +": +-----------+-------+ : : +-----+-----+ :\n" +": | ptr | o---+---+-----+-->| o o | o o | :\n" +": | len | 2 | : : +-|-|-+-|-|-+ :\n" +": | capacity | 2 | : : | | | | +---------------+ :\n" +": +-----------+-------+ : : | | | '-->| name: \"Fido\" | :\n" +": : : | | | +---------------+ :\n" +"`- - - - - - - - - - - - - -' : | | | :\n" +" : | | | +----------------------+ : \n" +" : | | '---->| \"::name\" | :\n" +" : | | +----------------------+ : \n" +" : | | : \n" +" : | | +-+ : \n" +" : | '-->|\\| : \n" +" : | +-+ : \n" +" : | : \n" +" : | +----------------------+ : \n" +" : '---->| \"::name\" | : \n" +" : +----------------------+ :\n" +" : :\n" +" '- - - - - - - - - - - - - - - - - - - - - - -'\n" +"\n" +"```" +msgstr "" + +#: src/traits/trait-objects.md:72 +msgid "" +"* Types that implement a given trait may be of different sizes. This makes it impossible to have things like `Vec` in the example above.\n" +"* `dyn Pet` is a way to tell the compiler about a dynamically sized type that implements `Pet`.\n" +"* In the example, `pets` holds *fat pointers* to objects that implement `Pet`. The fat pointer consists of two components, a pointer to the actual " +"object and a pointer to the virtual method table for the `Pet` implementation of that particular object.\n" +"* Compare these outputs in the above example:\n" +" ```rust,ignore\n" +" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::());\n" +" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n" +" println!(\"{}\", std::mem::size_of::<&dyn Pet>());\n" +" println!(\"{}\", std::mem::size_of::>());\n" +" ```" +msgstr "" + +#: src/traits/deriving-traits.md:1 +#, fuzzy +msgid "# Deriving Traits" +msgstr "# Tratti derivati" + +#: src/traits/deriving-traits.md:3 +#, fuzzy +msgid "You can let the compiler derive a number of traits:" +msgstr "Puoi lasciare che il compilatore derivi una serie di tratti:" + +#: src/traits/deriving-traits.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Clone, PartialEq, Eq, Default)]\n" +"struct Player {\n" +" name: String,\n" +" strength: u8,\n" +" hit_points: u8,\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Player::default();\n" +" let p2 = p1.clone();\n" +" println!(\"Is {:?}\\nequal to {:?}?\\nThe answer is {}!\", &p1, &p2,\n" +" if p1 == p2 { \"yes\" } else { \"no\" });\n" +"}\n" +"```" +msgstr "" + +#: src/traits/default-methods.md:1 +#, fuzzy +msgid "# Default Methods" +msgstr "# Metodi predefiniti" + +#: src/traits/default-methods.md:3 +#, fuzzy +msgid "Traits can implement behavior in terms of other trait methods:" +msgstr "I tratti possono implementare il comportamento in termini di altri metodi di tratto:" + +#: src/traits/default-methods.md:5 +msgid "" +"```rust,editable\n" +"trait Equals {\n" +" fn equal(&self, other: &Self) -> bool;\n" +" fn not_equal(&self, other: &Self) -> bool {\n" +" !self.equal(other)\n" +" }\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"struct Centimeter(i16);\n" +"\n" +"impl Equals for Centimeter {\n" +" fn equal(&self, other: &Centimeter) -> bool {\n" +" self.0 == other.0\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let a = Centimeter(10);\n" +" let b = Centimeter(20);\n" +" println!(\"{a:?} equals {b:?}: {}\", a.equal(&b));\n" +" println!(\"{a:?} not_equals {b:?}: {}\", a.not_equal(&b));\n" +"}\n" +"```" +msgstr "" + +#: src/traits/default-methods.md:32 +#, fuzzy +msgid "" +"* Traits may specify pre-implemented (default) methods and methods that users are required to\n" +" implement themselves. Methods with default implementations can rely on required methods.\n" +"\n" +"* Move method `not_equal` to a new trait `NotEqual`.\n" +"\n" +"* Make `NotEqual` a super trait for `Equal`.\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`." +msgstr "" +"* I tratti possono specificare metodi pre-implementati (predefiniti) e metodi richiesti agli utenti\n" +" implementare se stessi. I metodi con implementazioni predefinite possono fare affidamento sui metodi richiesti.\n" +"\n" +"* Sposta il metodo `not_equal` in un nuovo tratto `NotEqual`.\n" +"\n" +"* Rendi `NotEqual` un super tratto per `Equal`.\n" +"\n" +"* Fornire un'implementazione globale di \"NotEqual\" per \"Equal\".\n" +" * Con l'implementazione coperta, non hai più bisogno di \"NotEqual\" come super tratto per \"Equal\"." + +#: src/traits/trait-bounds.md:1 +#, fuzzy +msgid "# Trait Bounds" +msgstr "# Limiti dei tratti" + +#: src/traits/trait-bounds.md:3 +#, fuzzy +msgid "" +"When working with generics, you often want to require the types to implement\n" +"some trait, so that you can call this trait's methods." +msgstr "" +"Quando si lavora con i generici, spesso si desidera richiedere i tipi da implementare\n" +"qualche tratto, in modo da poter chiamare i metodi di questo tratto." + +#: src/traits/trait-bounds.md:6 +#, fuzzy +msgid "You can do this with `T: Trait` or `impl Trait`:" +msgstr "Puoi farlo con `T: Trait` o `impl Trait`:" + +#: src/traits/trait-bounds.md:8 +msgid "" +"```rust,editable\n" +"fn duplicate(a: T) -> (T, T) {\n" +" (a.clone(), a.clone())\n" +"}\n" +"\n" +"// Syntactic sugar for:\n" +"// fn add_42_millions>(x: T) -> i32 {\n" +"fn add_42_millions(x: impl Into) -> i32 {\n" +" x.into() + 42_000_000\n" +"}\n" +"\n" +"// struct NotClonable;\n" +"\n" +"fn main() {\n" +" let foo = String::from(\"foo\");\n" +" let pair = duplicate(foo);\n" +" println!(\"{pair:?}\");\n" +"\n" +" let many = add_42_millions(42_i8);\n" +" println!(\"{many}\");\n" +" let many_more = add_42_millions(10_000_000);\n" +" println!(\"{many_more}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-bounds.md:35 +#, fuzzy +msgid "Show a `where` clause, students will encounter it when reading code." +msgstr "Mostra una clausola `where`, gli studenti la incontreranno durante la lettura del codice." + +#: src/traits/trait-bounds.md:37 +msgid "" +"```rust,ignore\n" +"fn duplicate(a: T) -> (T, T)\n" +"where\n" +" T: Clone,\n" +"{\n" +" (a.clone(), a.clone())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/trait-bounds.md:46 +#, fuzzy +msgid "" +"* It declutters the function signature if you have many parameters.\n" +"* It has additional features making it more powerful.\n" +" * If someone asks, the extra feature is that the type on the left of \":\" can be arbitrary, like `Option`.\n" +" " +msgstr "" +"* Riordina la firma della funzione se hai molti parametri.\n" +"* Ha funzionalità aggiuntive che lo rendono più potente.\n" +" * Se qualcuno lo chiede, la caratteristica extra è che il tipo a sinistra di \":\" può essere arbitrario, come `Option`.\n" +" " + +#: src/traits/impl-trait.md:1 +#, fuzzy +msgid "# `impl Trait`" +msgstr "# `Impl Tratto`" + +#: src/traits/impl-trait.md:3 +#, fuzzy +msgid "" +"Similar to trait bounds, an `impl Trait` syntax can be used in function\n" +"arguments and return values:" +msgstr "" +"Simile ai limiti dei tratti, in funzione può essere utilizzata una sintassi `impl Trait`\n" +"argomenti e valori restituiti:" + +#: src/traits/impl-trait.md:6 +msgid "" +"```rust,editable\n" +"use std::fmt::Display;\n" +"\n" +"fn get_x(name: impl Display) -> impl Display {\n" +" format!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let x = get_x(\"foo\");\n" +" println!(\"{x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/impl-trait.md:19 +#, fuzzy +msgid "* `impl Trait` allows you to work with types which you cannot name." +msgstr "* `impl Trait` ti permette di lavorare con tipi che non puoi nominare." + +#: src/traits/impl-trait.md:23 +#, fuzzy +msgid "The meaning of `impl Trait` is a bit different in the different positions." +msgstr "Il significato di \"impl Trait\" è leggermente diverso nelle diverse posizioni." + +#: src/traits/impl-trait.md:25 +#, fuzzy +msgid "" +"* For a parameter, `impl Trait` is like an anonymous generic parameter with a trait bound.\n" +"\n" +"* For a return type, it means that the return type is some concrete type that implements the trait,\n" +" without naming the type. This can be useful when you don't want to expose the concrete type in a\n" +" public API.\n" +"\n" +" Inference is hard in return position. A function returning `impl Foo` picks\n" +" the concrete type it returns, without writing it out in the source. A function\n" +" returning a generic type like `collect() -> B` can return any type\n" +" satisfying `B`, and the caller may need to choose one, such as with `let x:\n" +" Vec<_> = foo.collect()` or with the turbofish, `foo.collect::>()`." +msgstr "" +"* Per un parametro, `impl Trait` è come un parametro generico anonimo con un tratto associato.\n" +"\n" +"* Per un tipo restituito, significa che il tipo restituito è un tipo concreto che implementa il tratto,\n" +" senza nominare il tipo. Questo può essere utile quando non vuoi esporre il tipo concreto in a\n" +" API pubblica.\n" +"\n" +" L'inferenza è difficile nella posizione di ritorno. Una funzione che restituisce le scelte `impl Foo`\n" +" il tipo concreto che restituisce, senza scriverlo nella fonte. Una funzione\n" +" restituire un tipo generico come `collect() -> B` può restituire qualsiasi tipo\n" +" soddisfacente `B`, e il chiamante potrebbe aver bisogno di sceglierne uno, come con `let x:\n" +" Vec<_> = foo.collect()` o con il turbofish, `foo.collect::>()`." + +#: src/traits/impl-trait.md:37 +#, fuzzy +msgid "" +"This example is great, because it uses `impl Display` twice. It helps to explain that\n" +"nothing here enforces that it is _the same_ `impl Display` type. If we used a single \n" +"`T: Display`, it would enforce the constraint that input `T` and return `T` type are the same type.\n" +"It would not work for this particular function, as the type we expect as input is likely not\n" +"what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two\n" +"independent generic parameters." +msgstr "" +"Questo esempio è fantastico, perché utilizza `impl Display` due volte. Aiuta a spiegarlo\n" +"nulla qui impone che sia _lo stesso_ tipo `impl Display`. Se usiamo un singolo\n" +"`T: Display`, imporrebbe il vincolo secondo cui l'input `T` e il tipo restituito `T` sono dello stesso tipo.\n" +"Non funzionerebbe per questa particolare funzione, poiché probabilmente non lo è il tipo che ci aspettiamo come input\n" +"quale `formato!` restituisce. Se volessimo fare lo stesso tramite la sintassi `: Display`, ne avremmo bisogno di due\n" +"parametri generici indipendenti." + +#: src/traits/important-traits.md:1 +#, fuzzy +msgid "# Important Traits" +msgstr "# Tratti importanti" + +#: src/traits/important-traits.md:3 +#, fuzzy +msgid "We will now look at some of the most common traits of the Rust standard library:" +msgstr "Vedremo ora alcuni dei tratti più comuni della libreria standard di Rust:" + +#: src/traits/important-traits.md:5 +#, fuzzy +msgid "" +"* [`Iterator`][1] and [`IntoIterator`][2] used in `for` loops,\n" +"* [`From`][3] and [`Into`][4] used to convert values,\n" +"* [`Read`][5] and [`Write`][6] used for IO,\n" +"* [`Add`][7], [`Mul`][8], ... used for operator overloading, and\n" +"* [`Drop`][9] used for defining destructors.\n" +"* [`Default`][10] used to construct a default instance of a type." +msgstr "" +"* [`Iterator`][1] e [`IntoIterator`][2] usati nei cicli `for`,\n" +"* [`From`][3] e [`Into`][4] utilizzati per convertire i valori,\n" +"* [`Read`][5] e [`Write`][6] usati per IO,\n" +"* [`Add`][7], [`Mul`][8], ... utilizzato per l'overload degli operatori e\n" +"* [`Drop`][9] usato per definire i distruttori.\n" +"* [`Default`][10] utilizzato per costruire un'istanza predefinita di un tipo." + +#: src/traits/iterator.md:1 +#, fuzzy +msgid "# Iterators" +msgstr "# Iteratori" + +#: src/traits/iterator.md:3 +#, fuzzy +msgid "You can implement the [`Iterator`][1] trait on your own types:" +msgstr "Puoi implementare il tratto [`Iterator`][1] sui tuoi tipi:" + +#: src/traits/iterator.md:5 +msgid "" +"```rust,editable\n" +"struct Fibonacci {\n" +" curr: u32,\n" +" next: u32,\n" +"}\n" +"\n" +"impl Iterator for Fibonacci {\n" +" type Item = u32;\n" +"\n" +" fn next(&mut self) -> Option {\n" +" let new_next = self.curr + self.next;\n" +" self.curr = self.next;\n" +" self.next = new_next;\n" +" Some(self.curr)\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let fib = Fibonacci { curr: 0, next: 1 };\n" +" for (i, n) in fib.enumerate().take(5) {\n" +" println!(\"fib({i}): {n}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/traits/iterator.md:32 +#, fuzzy +msgid "" +"* The `Iterator` trait implements many common functional programming operations over collections \n" +" (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can find all the documentation\n" +" about them. In Rust these functions should produce the code as efficient as equivalent imperative\n" +" implementations.\n" +" \n" +"* `IntoIterator` is the trait that makes for loops work. It is implemented by collection types such as\n" +" `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also implement it. This is why\n" +" you can iterate over a vector with `for i in some_vec { .. }` but\n" +" `some_vec.next()` doesn't exist." +msgstr "" +"* Il tratto `Iterator` implementa molte comuni operazioni di programmazione funzionale sulle raccolte\n" +" (ad es. `map`, `filter`, `reduce`, ecc.). Questo è il tratto in cui puoi trovare tutta la documentazione\n" +" su di loro. In Rust queste funzioni dovrebbero produrre il codice tanto efficiente quanto imperativo equivalente\n" +" implementazioni.\n" +" \n" +"* `IntoIterator` è la caratteristica che fa funzionare i cicli for. È implementato da tipi di raccolta come\n" +" `Vec` e riferimenti ad essi come `&Vec` e `&[T]`. Anche le gamme lo implementano. Ecco perché\n" +" puoi iterare su un vettore con `for i in some_vec { .. }` ma\n" +" `some_vec.next()` non esiste." + +#: src/traits/from-iterator.md:1 +#, fuzzy +msgid "# FromIterator" +msgstr "# FromIterator" + +#: src/traits/from-iterator.md:3 +#, fuzzy +msgid "[`FromIterator`][1] lets you build a collection from an [`Iterator`][2]." +msgstr "[`FromIterator`][1] consente di creare una raccolta da un [`Iterator`][2]." + +#: src/traits/from-iterator.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let primes = vec![2, 3, 5, 7];\n" +" let prime_squares = primes\n" +" .into_iter()\n" +" .map(|prime| prime * prime)\n" +" .collect::>();\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-iterator.md:17 +#, fuzzy +msgid "" +"`Iterator` implements\n" +"`fn collect(self) -> B\n" +"where\n" +" B: FromIterator,\n" +" Self: Sized`" +msgstr "" +"Implementa `Iterator`\n" +"`fn collect(self) -> B\n" +"Dove\n" +" B: FromIterator,\n" +" Sé: dimensionato`" + +#: src/traits/from-iterator.md:23 +#, fuzzy +msgid "" +"There are also implementations which let you do cool things like convert an\n" +"`Iterator>` into a `Result, E>`." +msgstr "" +"Ci sono anche implementazioni che ti permettono di fare cose interessanti come convertire un file\n" +"`Iterator>` in un `Result, E>`." + +#: src/traits/from-into.md:1 +#, fuzzy +msgid "# `From` and `Into`" +msgstr "# `Da` e `Into`" + +#: src/traits/from-into.md:3 +#, fuzzy +msgid "Types implement [`From`][1] and [`Into`][2] to facilitate type conversions:" +msgstr "I tipi implementano [`From`][1] e [`Into`][2] per facilitare le conversioni di tipo:" + +#: src/traits/from-into.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s = String::from(\"hello\");\n" +" let addr = std::net::Ipv4Addr::from([127, 0, 0, 1]);\n" +" let one = i16::from(true);\n" +" let bigger = i32::from(123i16);\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-into.md:15 +#, fuzzy +msgid "[`Into`][2] is automatically implemented when [`From`][1] is implemented:" +msgstr "[`Into`][2] viene implementato automaticamente quando [`From`][1] è implementato:" + +#: src/traits/from-into.md:17 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s: String = \"hello\".into();\n" +" let addr: std::net::Ipv4Addr = [127, 0, 0, 1].into();\n" +" let one: i16 = true.into();\n" +" let bigger: i32 = 123i16.into();\n" +" println!(\"{s}, {addr}, {one}, {bigger}\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/from-into.md:29 +#, fuzzy +msgid "" +"* That's why it is common to only implement `From`, as your type will get `Into` implementation too.\n" +"* When declaring a function argument input type like \"anything that can be converted into a `String`\", the rule is opposite, you should use " +"`Into`.\n" +" Your function will accept types that implement `From` and those that _only_ implement `Into`.\n" +" " +msgstr "" +"* Ecco perché è comune implementare solo `From`, poiché anche il tuo tipo otterrà l'implementazione di `Into`.\n" +"* Quando si dichiara un tipo di input per l'argomento di una funzione come \"qualsiasi cosa che può essere convertita in una `Stringa`\", la regola " +"è opposta, si dovrebbe usare `Into`.\n" +" La tua funzione accetterà tipi che implementano `From` e quelli che _solo_ implementano `Into`.\n" +" " + +#: src/traits/read-write.md:1 +#, fuzzy +msgid "# `Read` and `Write`" +msgstr "# `Leggi` e `Scrivi`" + +#: src/traits/read-write.md:3 +#, fuzzy +msgid "Using [`Read`][1] and [`BufRead`][2], you can abstract over `u8` sources:" +msgstr "Usando [`Read`][1] e [`BufRead`][2], puoi astrarre su fonti `u8`:" + +#: src/traits/read-write.md:5 +msgid "" +"```rust,editable\n" +"use std::io::{BufRead, BufReader, Read, Result};\n" +"\n" +"fn count_lines(reader: R) -> usize {\n" +" let buf_reader = BufReader::new(reader);\n" +" buf_reader.lines().count()\n" +"}\n" +"\n" +"fn main() -> Result<()> {\n" +" let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" +" println!(\"lines in slice: {}\", count_lines(slice));\n" +"\n" +" let file = std::fs::File::open(std::env::current_exe()?)?;\n" +" println!(\"lines in file: {}\", count_lines(file));\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/read-write.md:23 +#, fuzzy +msgid "Similarly, [`Write`][3] lets you abstract over `u8` sinks:" +msgstr "Allo stesso modo, [`Write`][3] ti consente di astrarre sui sink `u8`:" + +#: src/traits/read-write.md:25 +msgid "" +"```rust,editable\n" +"use std::io::{Result, Write};\n" +"\n" +"fn log(writer: &mut W, msg: &str) -> Result<()> {\n" +" writer.write_all(msg.as_bytes())?;\n" +" writer.write_all(\"\\n\".as_bytes())\n" +"}\n" +"\n" +"fn main() -> Result<()> {\n" +" let mut buffer = Vec::new();\n" +" log(&mut buffer, \"Hello\")?;\n" +" log(&mut buffer, \"World\")?;\n" +" println!(\"Logged: {:?}\", buffer);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/traits/drop.md:1 +#, fuzzy +msgid "# The `Drop` Trait" +msgstr "# Il tratto `Drop`" + +#: src/traits/drop.md:3 +#, fuzzy +msgid "Values which implement [`Drop`][1] can specify code to run when they go out of scope:" +msgstr "I valori che implementano [`Drop`][1] possono specificare il codice da eseguire quando escono dall'ambito:" + +#: src/traits/drop.md:5 +msgid "" +"```rust,editable\n" +"struct Droppable {\n" +" name: &'static str,\n" +"}\n" +"\n" +"impl Drop for Droppable {\n" +" fn drop(&mut self) {\n" +" println!(\"Dropping {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let a = Droppable { name: \"a\" };\n" +" {\n" +" let b = Droppable { name: \"b\" };\n" +" {\n" +" let c = Droppable { name: \"c\" };\n" +" let d = Droppable { name: \"d\" };\n" +" println!(\"Exiting block B\");\n" +" }\n" +" println!(\"Exiting block A\");\n" +" }\n" +" drop(a);\n" +" println!(\"Exiting main\");\n" +"}\n" +"```" +msgstr "" + +#: src/traits/drop.md:34 src/traits/operators.md:26 +#, fuzzy +msgid "Discussion points:" +msgstr "Punti di discussione:" + +#: src/traits/drop.md:36 +#, fuzzy +msgid "" +"* Why doesn't `Drop::drop` take `self`?\n" +" * Short-answer: If it did, `std::mem::drop` would be called at the end of\n" +" the block, resulting in another call to `Drop::drop`, and a stack\n" +" overflow!\n" +"* Try replacing `drop(a)` with `a.drop()`." +msgstr "" +"* Perché `Drop::drop` non accetta `self`?\n" +" * Risposta breve: se così fosse, `std::mem::drop` verrebbe chiamato alla fine di\n" +" il blocco, risultando in un'altra chiamata a `Drop::drop` e uno stack\n" +" traboccare!\n" +"* Prova a sostituire `drop(a)` con `a.drop()`." + +#: src/traits/default.md:1 +#, fuzzy +msgid "# The `Default` Trait" +msgstr "# Il tratto `Predefinito`" + +#: src/traits/default.md:3 +#, fuzzy +msgid "[`Default`][1] trait provides a default implementation of a trait." +msgstr "Il tratto [`Default`][1] fornisce un'implementazione predefinita di un tratto." + +#: src/traits/default.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Default)]\n" +"struct Derived {\n" +" x: u32,\n" +" y: String,\n" +" z: Implemented,\n" +"}\n" +"\n" +"#[derive(Debug)]\n" +"struct Implemented(String);\n" +"\n" +"impl Default for Implemented {\n" +" fn default() -> Self {\n" +" Self(\"John Smith\".into())\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let default_struct: Derived = Default::default();\n" +" println!(\"{default_struct:#?}\");\n" +"\n" +" let almost_default_struct = Derived {\n" +" y: \"Y is set!\".into(),\n" +" ..Default::default()\n" +" };\n" +" println!(\"{almost_default_struct:#?}\");\n" +"\n" +" let nothing: Option = None;\n" +" println!(\"{:#?}\", nothing.unwrap_or_default());\n" +"}\n" +"\n" +"```" +msgstr "" + +#: src/traits/default.md:40 +#, fuzzy +msgid "" +" * It can be implemented directly or it can be derived via `#[derive(Default)]`.\n" +" * Derived implementation will produce an instance where all fields are set to their default values.\n" +" * This means all types in the struct must implement `Default` too.\n" +" * Standard Rust types often implement `Default` with reasonable values (e.g. `0`, `\"\"`, etc).\n" +" * The partial struct copy works nicely with default.\n" +" * Rust standard library is aware that types can implement `Default` and provides convenience methods that use it." +msgstr "" +" * Può essere implementato direttamente o può essere derivato tramite `#[derive(Default)]`.\n" +" * L'implementazione derivata produrrà un'istanza in cui tutti i campi sono impostati sui valori predefiniti.\n" +" * Ciò significa che anche tutti i tipi nella struttura devono implementare `Default`.\n" +" * I tipi Rust standard spesso implementano `Default` con valori ragionevoli (ad esempio `0`, `\"\"`, ecc.).\n" +" * La copia parziale della struttura funziona bene con default.\n" +" * La libreria standard di Rust sa che i tipi possono implementare `Default` e fornisce comodi metodi che lo utilizzano." + +#: src/traits/operators.md:1 +#, fuzzy +msgid "# `Add`, `Mul`, ..." +msgstr "# `Aggiungi`, `Mul`, ..." + +#: src/traits/operators.md:3 +#, fuzzy +msgid "Operator overloading is implemented via traits in [`std::ops`][1]:" +msgstr "L'overload degli operatori è implementato tramite i tratti in [`std::ops`][1]:" + +#: src/traits/operators.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug, Copy, Clone)]\n" +"struct Point { x: i32, y: i32 }\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self {\n" +" Self {x: self.x + other.x, y: self.y + other.y}\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point { x: 10, y: 20 };\n" +" let p2 = Point { x: 100, y: 200 };\n" +" println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" +"}\n" +"```" +msgstr "" + +#: src/traits/operators.md:28 +#, fuzzy +msgid "" +"* You could implement `Add` for `&Point`. In which situations is that useful? \n" +" * Answer: `Add:add` consumes `self`. If type `T` for which you are\n" +" 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" +" associated types (like `Output`) are controlled by the implementor of a\n" +" trait." +msgstr "" +"* Puoi implementare `Aggiungi` per `&Punto`. In quali situazioni è utile?\n" +" * Risposta: `Add:add` consuma `self`. Se digita \"T\" per cui sei\n" +" l'overloading dell'operatore non è `Copy`, dovresti considerare l'overloading\n" +" anche l'operatore per `&T`. Ciò evita inutili clonazioni sul file\n" +" sito di chiamata.\n" +"* Perché `Output` è un tipo associato? Potrebbe essere reso un parametro di tipo?\n" +" * Risposta breve: i parametri di tipo sono controllati dal chiamante, ma\n" +" i tipi associati (come `Output`) sono controllati dall'implementatore di a\n" +" tratto." + +#: src/traits/closures.md:1 +#, fuzzy +msgid "# Closures" +msgstr "# Chiusure" + +#: src/traits/closures.md:3 +#, fuzzy +msgid "" +"Closures or lambda expressions have types which cannot be named. However, they\n" +"implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:" +msgstr "" +"Le chiusure o le espressioni lambda hanno tipi che non possono essere nominati. Tuttavia, loro\n" +"implementare speciali [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html) e\n" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) caratteristiche:" + +#: src/traits/closures.md:8 +msgid "" +"```rust,editable\n" +"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" +" println!(\"Calling function on {input}\");\n" +" func(input)\n" +"}\n" +"\n" +"fn main() {\n" +" let add_3 = |x| x + 3;\n" +" let mul_5 = |x| x * 5;\n" +"\n" +" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" +" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" +"}\n" +"```" +msgstr "" + +#: src/traits/closures.md:25 +#, fuzzy +msgid "If you have an `FnOnce`, you may only call it once. It might consume captured values." +msgstr "Se hai un `FnOnce`, puoi chiamarlo solo una volta. Potrebbe consumare i valori acquisiti." + +#: src/traits/closures.md:27 +#, fuzzy +msgid "An `FnMut` might mutate captured values, so you can call it multiple times but not concurrently." +msgstr "Un `FnMut` potrebbe mutare i valori catturati, quindi puoi chiamarlo più volte ma non contemporaneamente." + +#: src/traits/closures.md:29 +#, fuzzy +msgid "" +"An `Fn` neither consumes nor mutates captured values, or perhaps captures nothing at all, so it can\n" +"be called multiple times concurrently." +msgstr "" +"Un \"Fn\" non consuma né muta i valori acquisiti, o forse non cattura nulla, quindi può farlo\n" +"essere chiamato più volte contemporaneamente." + +#: src/traits/closures.md:32 +#, fuzzy +msgid "" +"`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. I.e. you can use an\n" +"`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever an `FnMut` or `FnOnce`\n" +"is called for." +msgstr "" +"\"FnMut\" è un sottotipo di \"FnOnce\". \"Fn\" è un sottotipo di \"FnMut\" e \"FnOnce\". Cioè. puoi usare un\n" +"`FnMut` ovunque sia richiesto un `FnOnce` e puoi usare un `Fn` ovunque sia `FnMut` o `FnOnce`\n" +"è richiesto." + +#: src/traits/closures.md:36 +#, fuzzy +msgid "`move` closures only implement `FnOnce`." +msgstr "Le chiusure `move` implementano solo `FnOnce`." + +#: src/exercises/day-3/morning.md:1 +#, fuzzy +msgid "# Day 3: Morning Exercises" +msgstr "# Giorno 3: Esercizi mattutini" + +#: src/exercises/day-3/morning.md:3 +#, fuzzy +msgid "We will design a classical GUI library traits and trait objects." +msgstr "Progetteremo una libreria GUI classica di tratti e oggetti di tratto." + +#: src/exercises/day-3/simple-gui.md:1 +#, fuzzy +msgid "# A Simple GUI Library" +msgstr "# Una semplice libreria GUI" + +#: src/exercises/day-3/simple-gui.md:3 +#, fuzzy +msgid "" +"Let us design a classical GUI library using our new knowledge of traits and\n" +"trait objects." +msgstr "" +"Progettiamo una libreria GUI classica utilizzando la nostra nuova conoscenza dei tratti e\n" +"oggetti di tratto." + +#: src/exercises/day-3/simple-gui.md:6 +#, fuzzy +msgid "We will have a number of widgets in our library:" +msgstr "Avremo una serie di widget nella nostra libreria:" + +#: src/exercises/day-3/simple-gui.md:8 +#, fuzzy +msgid "" +"* `Window`: has a `title` and contains other widgets.\n" +"* `Button`: has a `label` and a callback function which is invoked when the\n" +" button is pressed.\n" +"* `Label`: has a `label`." +msgstr "" +"* `Window`: ha un `title` e contiene altri widget.\n" +"* `Button`: ha una `label` e una funzione di callback che viene richiamata quando il\n" +" pulsante viene premuto.\n" +"* `Etichetta`: ha una `etichetta`." + +#: src/exercises/day-3/simple-gui.md:13 +#, fuzzy +msgid "The widgets will implement a `Widget` trait, see below." +msgstr "I widget implementeranno un tratto `Widget`, vedi sotto." + +#: src/exercises/day-3/simple-gui.md:15 +#, fuzzy +msgid "" +"Copy the code below to , fill in the missing\n" +"`draw_into` methods so that you implement the `Widget` trait:" +msgstr "" +"Copia il codice qui sotto in , inserisci i campi mancanti\n" +"metodi `draw_into` in modo da implementare il tratto `Widget`:" + +#: src/exercises/day-3/simple-gui.md:18 +msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"\n" +" fn inner_width(&self) -> usize {\n" +" std::cmp::max(\n" +" self.title.chars().count(),\n" +" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +" )\n" +" }\n" +"}\n" +"\n" +"\n" +"impl Widget for Label {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Widget for Button {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" unimplemented!()\n" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:130 +#, fuzzy +msgid "The output of the above program can be something simple like this:" +msgstr "L'output del programma sopra può essere qualcosa di semplice come questo:" + +#: src/exercises/day-3/simple-gui.md:132 +msgid "" +"```text\n" +"========\n" +"Rust GUI Demo 1.23\n" +"========\n" +"\n" +"This is a small text GUI demo.\n" +"\n" +"| Click me! |\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:142 +#, fuzzy +msgid "" +"If you want to draw aligned text, you can use the\n" +"[fill/alignment](https://doc.rust-lang.org/std/fmt/index.html#fillalignment)\n" +"formatting operators. In particular, notice how you can pad with different\n" +"characters (here a `'/'`) and how you can control alignment:" +msgstr "" +"Se vuoi disegnare un testo allineato, puoi usare il\n" +"[fill/alignment](https://doc.rust-lang.org/std/fmt/index.html#fillalignment)\n" +"operatori di formattazione. In particolare, nota come puoi riempire con diversi\n" +"caratteri (qui un `'/'`) e come puoi controllare l'allineamento:" + +#: src/exercises/day-3/simple-gui.md:147 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let width = 10;\n" +" println!(\"left aligned: |{:/width$}|\", \"foo\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:156 +#, fuzzy +msgid "Using such alignment tricks, you can for example produce output like this:" +msgstr "Usando tali trucchi di allineamento, puoi ad esempio produrre un output come questo:" + +#: src/exercises/day-3/simple-gui.md:158 +msgid "" +"```text\n" +"+--------------------------------+\n" +"| Rust GUI Demo 1.23 |\n" +"+================================+\n" +"| This is a small text GUI demo. |\n" +"| +-----------+ |\n" +"| | Click me! | |\n" +"| +-----------+ |\n" +"+--------------------------------+\n" +"```" +msgstr "" + +#: src/error-handling.md:1 +#, fuzzy +msgid "# Error Handling" +msgstr "# Gestione degli errori" + +#: src/error-handling.md:3 +#, fuzzy +msgid "Error handling in Rust is done using explicit control flow:" +msgstr "La gestione degli errori in Rust viene eseguita utilizzando un flusso di controllo esplicito:" + +#: src/error-handling.md:5 +#, fuzzy +msgid "" +"* Functions that can have errors list this in their return type,\n" +"* There are no exceptions." +msgstr "" +"* Le funzioni che possono avere errori lo elencano nel loro tipo di ritorno,\n" +"* Non ci sono eccezioni." + +#: src/error-handling/panics.md:1 +#, fuzzy +msgid "# Panics" +msgstr "# Panico" + +#: src/error-handling/panics.md:3 +#, fuzzy +msgid "Rust will trigger a panic if a fatal error happens at runtime:" +msgstr "Rust attiverà un panico se si verifica un errore fatale in fase di esecuzione:" + +#: src/error-handling/panics.md:5 +msgid "" +"```rust,editable,should_panic\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" println!(\"v[100]: {}\", v[100]);\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/panics.md:12 +#, fuzzy +msgid "" +"* Panics are for unrecoverable and unexpected errors.\n" +" * Panics are symptoms of bugs in the program.\n" +"* Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." +msgstr "" +"* I panico sono per errori irrecuperabili e imprevisti.\n" +" * I panici sono sintomi di bug nel programma.\n" +"* Usa API senza panico (come `Vec::get`) se il crash non è accettabile." + +#: src/error-handling/panic-unwind.md:1 +#, fuzzy +msgid "# Catching the Stack Unwinding" +msgstr "# Catturare lo srotolamento della pila" + +#: src/error-handling/panic-unwind.md:3 +#, fuzzy +msgid "By default, a panic will cause the stack to unwind. The unwinding can be caught:" +msgstr "Per impostazione predefinita, un panico causerà lo srotolamento dello stack. Lo svolgimento può essere catturato:" + +#: src/error-handling/panic-unwind.md:5 +msgid "" +"```rust,editable\n" +"use std::panic;\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" println!(\"hello!\");\n" +"});\n" +"assert!(result.is_ok());\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" panic!(\"oh no!\");\n" +"});\n" +"assert!(result.is_err());\n" +"```" +msgstr "" + +#: src/error-handling/panic-unwind.md:19 +#, fuzzy +msgid "" +"* This can be useful in servers which should keep running even if a single\n" +" request crashes.\n" +"* This does not work if `panic = 'abort'` is set in your `Cargo.toml`." +msgstr "" +"* Questo può essere utile nei server che dovrebbero continuare a funzionare anche se un singolo\n" +" la richiesta va in crash.\n" +"* Questo non funziona se `panic = 'abort'` è impostato nel tuo `Cargo.toml`." + +#: src/error-handling/result.md:1 +#, fuzzy +msgid "# Structured Error Handling with `Result`" +msgstr "# Gestione strutturata degli errori con `Result`" + +#: src/error-handling/result.md:3 +#, fuzzy +msgid "" +"We have already seen the `Result` enum. This is used pervasively when errors are\n" +"expected as part of normal operation:" +msgstr "" +"Abbiamo già visto l'enumerazione `Result`. Questo è usato in modo pervasivo quando ci sono errori\n" +"previsto come parte del normale funzionamento:" + +#: src/error-handling/result.md:6 +msgid "" +"```rust,editable\n" +"use std::fs::File;\n" +"use std::io::Read;\n" +"\n" +"fn main() {\n" +" let file = File::open(\"diary.txt\");\n" +" match file {\n" +" Ok(mut file) => {\n" +" let mut contents = String::new();\n" +" file.read_to_string(&mut contents);\n" +" println!(\"Dear diary: {contents}\");\n" +" },\n" +" Err(err) => {\n" +" println!(\"The diary could not be opened: {err}\");\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/result.md:27 +#, fuzzy +msgid "" +" * As with `Option`, the successful value sits inside of `Result`, forcing the developer to\n" +" explicitly extract it. This encourages error checking. In the case where an error should never happen,\n" +" `unwrap()` or `expect()` can be called, and this is a signal of the developer intent too. \n" +" * `Result` documentation is a recommended read. Not during the course, but it is worth mentioning. \n" +" It contains a lot of convenience methods and functions that help functional-style programming. \n" +" " +msgstr "" +" * Come con `Option`, il valore riuscito si trova all'interno di `Result`, costringendo lo sviluppatore a farlo\n" +" estrarlo esplicitamente. Questo incoraggia il controllo degli errori. Nel caso in cui non dovesse mai verificarsi un errore,\n" +" È possibile chiamare `unwrap()` o `expect()`, e anche questo è un segnale dell'intenzione dello sviluppatore.\n" +" * La documentazione `Result` è una lettura consigliata. Non durante il corso, ma vale la pena menzionarlo.\n" +" Contiene molti metodi e funzioni utili che aiutano la programmazione in stile funzionale.\n" +" " + +#: src/error-handling/try-operator.md:1 +#, fuzzy +msgid "# Propagating Errors with `?`" +msgstr "# Propagazione degli errori con `?`" + +#: src/error-handling/try-operator.md:3 +#, fuzzy +msgid "" +"The try-operator `?` is used to return errors to the caller. It lets you turn\n" +"the common" +msgstr "" +"L'operatore try `?` viene utilizzato per restituire errori al chiamante. Ti fa girare\n" +"il comune" + +#: src/error-handling/try-operator.md:6 +msgid "" +"```rust,ignore\n" +"match some_expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(err),\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:13 +#, fuzzy +msgid "into the much simpler" +msgstr "nel molto più semplice" + +#: src/error-handling/try-operator.md:15 +msgid "" +"```rust,ignore\n" +"some_expression?\n" +"```" +msgstr "" + +#: src/error-handling/try-operator.md:19 +#, fuzzy +msgid "We can use this to simplify our error handing code:" +msgstr "Possiamo usarlo per semplificare il nostro codice di gestione degli errori:" + +#: src/error-handling/try-operator.md:21 +msgid "" +"```rust,editable\n" +"use std::fs;\n" +"use std::io::{self, Read};\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let username_file_result = fs::File::open(path);\n" +" let mut username_file = match username_file_result {\n" +" Ok(file) => file,\n" +" Err(err) => return Err(err),\n" +" };\n" +"\n" +" let mut username = String::new();\n" +" match username_file.read_to_string(&mut username) {\n" +" Ok(_) => Ok(username),\n" +" Err(err) => Err(err),\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"alice\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" +msgstr "" + +#: 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" +"* Use the `fs::write` call to test out the different scenarios: no file, empty file, file with username." +msgstr "" +"* La variabile `username` può essere `Ok(string)` o `Err(error)`.\n" +"* Usa la chiamata `fs::write` per testare i diversi scenari: nessun file, file vuoto, file con nome utente." + +#: src/error-handling/converting-error-types.md:1 src/error-handling/converting-error-types-example.md:1 +#, fuzzy +msgid "# Converting Error Types" +msgstr "# Conversione dei tipi di errore" + +#: src/error-handling/converting-error-types.md:3 +#, fuzzy +msgid "The effective expansion of `?` is a little more complicated than previously indicated:" +msgstr "L'effettiva espansione di `?` è un po' più complicata di quanto precedentemente indicato:" + +#: src/error-handling/converting-error-types.md:5 +msgid "" +"```rust,ignore\n" +"expression?\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types.md:9 +#, fuzzy +msgid "works the same as" +msgstr "funziona allo stesso modo di" + +#: src/error-handling/converting-error-types.md:11 +msgid "" +"```rust,ignore\n" +"match expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(From::from(err)),\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types.md:18 +#, fuzzy +msgid "" +"The `From::from` call here means we attempt to convert the error type to the\n" +"type returned by the function:" +msgstr "" +"La chiamata `From::from` qui significa che tentiamo di convertire il tipo di errore in\n" +"tipo restituito dalla funzione:" + +#: src/error-handling/converting-error-types-example.md:3 +msgid "" +"```rust,editable\n" +"use std::error::Error;\n" +"use std::fmt::{self, Display, Formatter};\n" +"use std::fs::{self, File};\n" +"use std::io::{self, Read};\n" +"\n" +"#[derive(Debug)]\n" +"enum ReadUsernameError {\n" +" IoError(io::Error),\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"impl Error for ReadUsernameError {}\n" +"\n" +"impl Display for ReadUsernameError {\n" +" fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" +" match self {\n" +" Self::IoError(e) => write!(f, \"IO error: {e}\"),\n" +" Self::EmptyUsername(filename) => write!(f, \"Found no username in {filename}\"),\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl From for ReadUsernameError {\n" +" fn from(err: io::Error) -> ReadUsernameError {\n" +" ReadUsernameError::IoError(err)\n" +" }\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:55 +#, fuzzy +msgid "" +"It is good practice for all error types to implement `std::error::Error`, which requires `Debug` and\n" +"`Display`. It's generally helpful for them to implement `Clone` and `Eq` too where possible, to make\n" +"life easier for tests and consumers of your library. In this case we can't easily do so, because\n" +"`io::Error` doesn't implement them." +msgstr "" +"È buona pratica per tutti i tipi di errore implementare `std::error::Error`, che richiede `Debug` e\n" +"`Display`. In genere è utile per loro implementare anche `Clone` e `Eq`, ove possibile, per fare\n" +"vita più facile per i test e i consumatori della tua libreria. In questo caso non possiamo farlo facilmente, perché\n" +"`io::Error` non li implementa." + +#: src/error-handling/deriving-error-enums.md:1 +#, fuzzy +msgid "# Deriving Error Enums" +msgstr "# Derivazione delle enumerazioni degli errori" + +#: src/error-handling/deriving-error-enums.md:3 +#, fuzzy +msgid "" +"The [thiserror](https://docs.rs/thiserror/) crate is a popular way to create an\n" +"error enum like we did on the previous page:" +msgstr "" +"Il crate [thiserror](https://docs.rs/thiserror/) è un modo popolare per creare un\n" +"error enum come abbiamo fatto nella pagina precedente:" + +#: src/error-handling/deriving-error-enums.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"\n" +"#[derive(Debug, Error)]\n" +"enum ReadUsernameError {\n" +" #[error(\"Could not read: {0}\")]\n" +" IoError(#[from] io::Error),\n" +" #[error(\"Found no username in {0}\")]\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:39 +#, fuzzy +msgid "" +"`thiserror`'s derive macro automatically implements `std::error::Error`, and optionally `Display`\n" +"(if the `#[error(...)]` attributes are provided) and `From` (if the `#[from]` attribute is added).\n" +"It also works for structs." +msgstr "" +"La macro deriva di `thiserror` implementa automaticamente `std::error::Error` e facoltativamente `Display`\n" +"(se vengono forniti gli attributi `#[error(...)]`) e `From` (se viene aggiunto l'attributo `#[from]`).\n" +"Funziona anche per le strutture." + +#: src/error-handling/deriving-error-enums.md:43 +#, fuzzy +msgid "It doesn't affect your public API, which makes it good for libraries." +msgstr "Non influisce sulla tua API pubblica, il che lo rende utile per le librerie." + +#: src/error-handling/dynamic-errors.md:1 +#, fuzzy +msgid "# Dynamic Error Types" +msgstr "# Tipi di errori dinamici" + +#: src/error-handling/dynamic-errors.md:3 +#, fuzzy +msgid "" +"Sometimes we want to allow any type of error to be returned without writing our own enum covering\n" +"all the different possibilities. `std::error::Error` makes this easy." +msgstr "" +"A volte vogliamo consentire la restituzione di qualsiasi tipo di errore senza scrivere la nostra copertura enum\n" +"tutte le diverse possibilità. `std::error::Error` lo rende facile." + +#: src/error-handling/dynamic-errors.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use std::fs::{self, File};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"use std::error::Error;\n" +"\n" +"#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" +"#[error(\"Found no username in {0}\")]\n" +"struct EmptyUsernameError(String);\n" +"\n" +"fn read_username(path: &str) -> Result> {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(EmptyUsernameError(String::from(path)).into());\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/dynamic-errors.md:36 +#, fuzzy +msgid "" +"This saves on code, but gives up the ability to cleanly handle different error cases differently in\n" +"the program. As such it's generally not a good idea to use `Box` in the public API of a\n" +"library, but it can be a good option in a program where you just want to display the error message\n" +"somewhere." +msgstr "" +"Ciò consente di risparmiare sul codice, ma rinuncia alla possibilità di gestire in modo pulito diversi casi di errore in modo diverso\n" +"il programma. Pertanto, generalmente non è una buona idea utilizzare `Box` nell'API pubblica di a\n" +"library, ma può essere una buona opzione in un programma in cui si desidera solo visualizzare il messaggio di errore\n" +"in qualche luogo." + +#: src/error-handling/error-contexts.md:1 +#, fuzzy +msgid "# Adding Context to Errors" +msgstr "# Aggiunta di contesto agli errori" + +#: src/error-handling/error-contexts.md:3 +#, fuzzy +msgid "" +"The widely used [anyhow](https://docs.rs/anyhow/) crate can help you add\n" +"contextual information to your errors and allows you to have fewer\n" +"custom error types:" +msgstr "" +"La cassa ampiamente utilizzata [comunque](https://docs.rs/anyhow/) può aiutarti ad aggiungere\n" +"informazioni contestuali ai tuoi errori e ti permette di averne meno\n" +"tipi di errore personalizzati:" + +#: src/error-handling/error-contexts.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use anyhow::{Context, Result, bail};\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)\n" +" .with_context(|| format!(\"Failed to open {path}\"))?\n" +" .read_to_string(&mut username)\n" +" .context(\"Failed to read\")?;\n" +" if username.is_empty() {\n" +" bail!(\"Found no username in {path}\");\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err:?}\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/error-handling/error-contexts.md:35 +#, fuzzy +msgid "" +"* `anyhow::Result` is a type alias for `Result`.\n" +"* `anyhow::Error` is essentially a wrapper around `Box`. As such it's again generally not\n" +" a good choice for the public API of a library, but is widely used in applications.\n" +"* Actual error type inside of it can be extracted for examination if necessary.\n" +"* Functionality provided by `anyhow::Result` may be familiar to Go developers, as it provides\n" +" similar usage patterns and ergonomics to `(T, error)` from Go." +msgstr "" +"* `comunque::Risultato` è un alias di tipo per `Risultato`.\n" +"* `anyhow::Error` è essenzialmente un wrapper attorno a `Box`. In quanto tale, generalmente non lo è\n" +" una buona scelta per l'API pubblica di una libreria, ma è ampiamente utilizzata nelle applicazioni.\n" +"* Il tipo di errore effettivo all'interno di esso può essere estratto per l'esame, se necessario.\n" +"* La funzionalità fornita da `anyhow::Result` potrebbe essere familiare agli sviluppatori Go, in quanto fornisce\n" +" modelli di utilizzo ed ergonomia simili a `(T, errore)` di Go." + +#: src/testing.md:1 +#, fuzzy +msgid "# Testing" +msgstr "# Test" + +#: src/testing.md:3 +#, fuzzy +msgid "Rust and Cargo come with a simple unit test framework:" +msgstr "Rust e Cargo sono dotati di un semplice framework di unit test:" + +#: src/testing.md:5 +#, fuzzy +msgid "" +"* Unit tests are supported throughout your code.\n" +"\n" +"* Integration tests are supported via the `tests/` directory." +msgstr "" +"* I test unitari sono supportati in tutto il codice.\n" +"\n" +"* I test di integrazione sono supportati tramite la directory `tests/`." + +#: src/testing/unit-tests.md:1 +#, fuzzy +msgid "# Unit Tests" +msgstr "# Test unitari" + +#: src/testing/unit-tests.md:3 +#, fuzzy +msgid "Mark unit tests with `#[test]`:" +msgstr "Contrassegna i test unitari con `#[test]`:" + +#: src/testing/unit-tests.md:5 +msgid "" +"```rust,editable,ignore\n" +"fn first_word(text: &str) -> &str {\n" +" match text.find(' ') {\n" +" Some(idx) => &text[..idx],\n" +" None => &text,\n" +" }\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty() {\n" +" assert_eq!(first_word(\"\"), \"\");\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_word() {\n" +" assert_eq!(first_word(\"Hello\"), \"Hello\");\n" +"}\n" +"\n" +"#[test]\n" +"fn test_multiple_words() {\n" +" assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/testing/unit-tests.md:29 +#, fuzzy +msgid "Use `cargo test` to find and run the unit tests." +msgstr "Usa `cargo test` per trovare ed eseguire i test unitari." + +#: src/testing/test-modules.md:1 +#, fuzzy +msgid "# Test Modules" +msgstr "# Moduli di prova" + +#: src/testing/test-modules.md:3 +#, fuzzy +msgid "" +"Unit tests are often put in a nested module (run tests on the\n" +"[Playground](https://play.rust-lang.org/)):" +msgstr "" +"I test unitari vengono spesso inseriti in un modulo nidificato (esegui test sul file\n" +"[Parco giochi](https://play.rust-lang.org/)):" + +#: src/testing/test-modules.md:6 +msgid "" +"```rust,editable\n" +"fn helper(a: &str, b: &str) -> String {\n" +" format!(\"{a} {b}\")\n" +"}\n" +"\n" +"pub fn main() {\n" +" println!(\"{}\", helper(\"Hello\", \"World\"));\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" #[test]\n" +" fn test_helper() {\n" +" assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/testing/test-modules.md:26 +#, fuzzy +msgid "" +"* This lets you unit test private helpers.\n" +"* The `#[cfg(test)]` attribute is only active when you run `cargo test`." +msgstr "" +"* Questo ti consente di testare unitamente gli aiutanti privati.\n" +"* L'attributo `#[cfg(test)]` è attivo solo quando esegui `cargo test`." + +#: src/testing/doc-tests.md:1 +#, fuzzy +msgid "# Documentation Tests" +msgstr "# Test di documentazione" + +#: src/testing/doc-tests.md:3 +#, fuzzy +msgid "Rust has built-in support for documentation tests:" +msgstr "Rust ha il supporto integrato per i test di documentazione:" + +#: src/testing/doc-tests.md:5 +msgid "" +"```rust\n" +"/// Shortens a string to the given length.\n" +"///\n" +"/// ```\n" +"/// use playground::shorten_string;\n" +"/// assert_eq!(shorten_string(\"Hello World\", 5), \"Hello\");\n" +"/// assert_eq!(shorten_string(\"Hello World\", 20), \"Hello World\");\n" +"/// ```\n" +"pub fn shorten_string(s: &str, length: usize) -> &str {\n" +" &s[..std::cmp::min(length, s.len())]\n" +"}\n" +"```" +msgstr "" + +#: src/testing/doc-tests.md:18 +#, fuzzy +msgid "" +"* Code blocks in `///` comments are automatically seen as Rust code.\n" +"* The code will be compiled and executed as part of `cargo test`.\n" +"* Test the above code on the [Rust Playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." +msgstr "" +"* I blocchi di codice nei commenti `///` sono visti automaticamente come codice Rust.\n" +"* Il codice verrà compilato ed eseguito come parte di `cargo test`.\n" +"* Prova il codice precedente su [Rust Playground](https://play.rust-lang.org/?" +"version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." + +#: src/testing/integration-tests.md:1 +#, fuzzy +msgid "# Integration Tests" +msgstr "# Test di integrazione" + +#: src/testing/integration-tests.md:3 +#, fuzzy +msgid "If you want to test your library as a client, use an integration test." +msgstr "Se desideri testare la tua libreria come client, utilizza un test di integrazione." + +#: src/testing/integration-tests.md:5 +#, fuzzy +msgid "Create a `.rs` file under `tests/`:" +msgstr "Crea un file `.rs` in `tests/`:" + +#: src/testing/integration-tests.md:7 +msgid "" +"```rust,ignore\n" +"use my_library::init;\n" +"\n" +"#[test]\n" +"fn test_init() {\n" +" assert!(init().is_ok());\n" +"}\n" +"```" +msgstr "" + +#: src/testing/integration-tests.md:16 +#, fuzzy +msgid "These tests only have access to the public API of your crate." +msgstr "Questi test hanno accesso solo all'API pubblica del tuo crate." + +#: src/unsafe.md:1 +#, fuzzy +msgid "# Unsafe Rust" +msgstr "# Ruggine non sicura" + +#: src/unsafe.md:3 +#, fuzzy +msgid "The Rust language has two parts:" +msgstr "Il linguaggio Rust ha due parti:" + +#: src/unsafe.md:5 +#, fuzzy +msgid "" +"* **Safe Rust:** memory safe, no undefined behavior possible.\n" +"* **Unsafe Rust:** can trigger undefined behavior if preconditions are violated." +msgstr "" +"* **Safe Rust:** memoria sicura, nessun comportamento indefinito possibile.\n" +"* **Unsafe Rust:** può attivare un comportamento indefinito se vengono violate le precondizioni." + +#: src/unsafe.md:8 +#, fuzzy +msgid "" +"We will be seeing mostly safe Rust in this course, but it's important to know\n" +"what Unsafe Rust is." +msgstr "" +"Vedremo Rust per lo più sicuro in questo corso, ma è importante saperlo\n" +"cos'è Unsafe Rust." + +#: src/unsafe.md:11 +#, fuzzy +msgid "" +"Unsafe code is usually small and isolated, and its correctness should be carefully\n" +"documented. It is usually wrapped in a safe abstraction layer." +msgstr "" +"Il codice non sicuro è solitamente piccolo e isolato e la sua correttezza dovrebbe essere attentamente\n" +"documentato. Di solito è racchiuso in uno strato di astrazione sicuro." + +#: src/unsafe.md:14 +#, fuzzy +msgid "Unsafe Rust gives you access to five new capabilities:" +msgstr "Unsafe Rust ti dà accesso a cinque nuove funzionalità:" + +#: src/unsafe.md:16 +#, fuzzy +msgid "" +"* Dereference raw pointers.\n" +"* Access or modify mutable static variables.\n" +"* Access `union` fields.\n" +"* Call `unsafe` functions, including `extern` functions.\n" +"* Implement `unsafe` traits." +msgstr "" +"* Dereferenzia i puntatori grezzi.\n" +"* Accedi o modifica variabili statiche mutabili.\n" +"* Accedi ai campi `union`.\n" +"* Richiama funzioni `non sicure`, comprese le funzioni `extern`.\n" +"* Implementa i tratti \"non sicuri\"." + +#: src/unsafe.md:22 +#, fuzzy +msgid "" +"We will briefly cover unsafe capabilities next. For full details, please see\n" +"[Chapter 19.1 in the Rust Book](https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html)\n" +"and the [Rustonomicon](https://doc.rust-lang.org/nomicon/)." +msgstr "" +"Tratteremo brevemente le capacità non sicure in seguito. Per tutti i dettagli, vedere\n" +"[Capitolo 19.1 nel Rust Book](https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html)\n" +"e il [Rustonomicon](https://doc.rust-lang.org/nomicon/)." + +#: src/unsafe.md:28 +#, fuzzy +msgid "" +"Unsafe Rust does not mean the code is incorrect. It means that developers have\n" +"turned off the compiler safety features and have to write correct code by\n" +"themselves. It means the compiler no longer enforces Rust's memory-safety rules." +msgstr "" +"Unsafe Rust non significa che il codice non sia corretto. Significa che gli sviluppatori hanno\n" +"ha disattivato le funzionalità di sicurezza del compilatore e deve scrivere il codice corretto\n" +"loro stessi. Significa che il compilatore non applica più le regole di sicurezza della memoria di Rust." + +#: src/unsafe/raw-pointers.md:1 +#, fuzzy +msgid "# Dereferencing Raw Pointers" +msgstr "# Dereferenziazione dei puntatori grezzi" + +#: src/unsafe/raw-pointers.md:3 +#, fuzzy +msgid "Creating pointers is safe, but dereferencing them requires `unsafe`:" +msgstr "La creazione di puntatori è sicura, ma la loro dereferenziazione richiede `unsafe`:" + +#: src/unsafe/raw-pointers.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut num = 5;\n" +"\n" +" 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\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" +" *r1 = 10;\n" +" println!(\"r2 is: {}\", *r2);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: 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" +"`unsafe` block explaining how the code inside it satisfies the safety requirements of the unsafe\n" +"operations it is doing." +msgstr "" +"È buona norma (e richiesto dalla guida allo stile di Android Rust) scrivere un commento per ciascuno\n" +"Blocco `unsafe` che spiega come il codice al suo interno soddisfi i requisiti di sicurezza dell'unsafe\n" +"operazioni che sta compiendo." + +#: src/unsafe/raw-pointers.md:31 +#, fuzzy +msgid "" +"In the case of pointer dereferences, this means that the pointers must be\n" +"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), i.e.:" +msgstr "" +"Nel caso di dereferenze puntatore, ciò significa che i puntatori devono essere\n" +"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), ovvero:" + +#: src/unsafe/raw-pointers.md:34 +#, fuzzy +msgid "" +" * The pointer must be non-null.\n" +" * The pointer must be _dereferenceable_ (within the bounds of a single allocated object).\n" +" * The object must not have been deallocated.\n" +" * There must not be concurrent accesses to the same location.\n" +" * If the pointer was obtained by casting a reference, the underlying object must be live and no\n" +" reference may be used to access the memory." +msgstr "" +" * Il puntatore deve essere diverso da null.\n" +" * Il puntatore deve essere _dereferenceable_ (entro i limiti di un singolo oggetto allocato).\n" +" * L'oggetto non deve essere stato deallocato.\n" +" * Non devono esserci accessi contemporanei alla stessa posizione.\n" +" * Se il puntatore è stato ottenuto lanciando un riferimento, l'oggetto sottostante deve essere live e no\n" +" riferimento può essere utilizzato per accedere alla memoria." + +#: src/unsafe/raw-pointers.md:41 +#, fuzzy +msgid "In most cases the pointer must also be properly aligned." +msgstr "Nella maggior parte dei casi anche il puntatore deve essere correttamente allineato." + +#: src/unsafe/mutable-static-variables.md:1 +#, fuzzy +msgid "# Mutable Static Variables" +msgstr "# Variabili statiche mutabili" + +#: src/unsafe/mutable-static-variables.md:3 +#, fuzzy +msgid "It is safe to read an immutable static variable:" +msgstr "È sicuro leggere una variabile statica immutabile:" + +#: src/unsafe/mutable-static-variables.md:5 +msgid "" +"```rust,editable\n" +"static HELLO_WORLD: &str = \"Hello, world!\";\n" +"\n" +"fn main() {\n" +" println!(\"HELLO_WORLD: {HELLO_WORLD}\");\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:13 +#, fuzzy +msgid "" +"However, since data races can occur, it is unsafe to read and write mutable\n" +"static variables:" +msgstr "" +"Tuttavia, poiché possono verificarsi corse di dati, non è sicuro leggere e scrivere mutabili\n" +"variabili statiche:" + +#: src/unsafe/mutable-static-variables.md:16 +msgid "" +"```rust,editable\n" +"static mut COUNTER: u32 = 0;\n" +"\n" +"fn add_to_counter(inc: u32) {\n" +" unsafe { COUNTER += inc; } // Potential data race!\n" +"}\n" +"\n" +"fn main() {\n" +" add_to_counter(42);\n" +"\n" +" unsafe { println!(\"COUNTER: {COUNTER}\"); } // Potential data race!\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:32 +#, fuzzy +msgid "" +"Using a mutable static is generally a bad idea, but there are some cases where it might make sense\n" +"in low-level `no_std` code, such as implementing a heap allocator or working with some C APIs." +msgstr "" +"L'uso di una statica mutabile è generalmente una cattiva idea, ma ci sono alcuni casi in cui potrebbe avere senso\n" +"nel codice `no_std` di basso livello, come implementare un allocatore di heap o lavorare con alcune API C." + +#: src/unsafe/unions.md:1 +#, fuzzy +msgid "# Unions" +msgstr "# Sindacati" + +#: src/unsafe/unions.md:3 +#, fuzzy +msgid "Unions are like enums, but you need to track the active field yourself:" +msgstr "Le unioni sono come le enum, ma devi monitorare tu stesso il campo attivo:" + +#: src/unsafe/unions.md:5 +msgid "" +"```rust,editable\n" +"#[repr(C)]\n" +"union MyUnion {\n" +" i: u8,\n" +" b: bool,\n" +"}\n" +"\n" +"fn main() {\n" +" let u = MyUnion { i: 42 };\n" +" println!(\"int: {}\", unsafe { u.i });\n" +" println!(\"bool: {}\", unsafe { u.b }); // Undefined behavior!\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/unions.md:21 +#, fuzzy +msgid "" +"Unions are very rarely needed in Rust as you can usually use an enum. They are occasionally needed\n" +"for interacting with C library APIs." +msgstr "" +"Le unioni sono molto raramente necessarie in Rust poiché di solito puoi usare un enum. Occasionalmente sono necessari\n" +"per interagire con le API della libreria C." + +#: src/unsafe/unions.md:24 +#, fuzzy +msgid "" +"If you just want to reinterpret bytes as a different type, you probably want\n" +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn.transmute.html) or a safe\n" +"wrapper such as the [`zerocopy`](https://crates.io/crates/zerocopy) crate." +msgstr "" +"Se vuoi solo reinterpretare i byte come un tipo diverso, probabilmente lo vuoi\n" +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn.transmute.html) o una cassaforte\n" +"wrapper come la cassa [`zerocopy`](https://crates.io/crates/zerocopy)." + +#: src/unsafe/calling-unsafe-functions.md:1 +#, fuzzy +msgid "# Calling Unsafe Functions" +msgstr "# Chiamata di funzioni non sicure" + +#: src/unsafe/calling-unsafe-functions.md:3 +#, fuzzy +msgid "" +"A function or method can be marked `unsafe` if it has extra preconditions you\n" +"must uphold to avoid undefined behaviour:" +msgstr "" +"Una funzione o un metodo può essere contrassegnato come \"non sicuro\" se ha precondizioni aggiuntive\n" +"deve sostenere per evitare comportamenti indefiniti:" + +#: src/unsafe/calling-unsafe-functions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let emojis = \"🗻∈🌏\";\n" +"\n" +" // Safe because the indices are in the correct order, within the bounds of\n" +" // the string slice, and lie on UTF-8 sequence boundaries.\n" +" unsafe {\n" +" println!(\"emoji: {}\", emojis.get_unchecked(0..4));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(4..7));\n" +" println!(\"emoji: {}\", emojis.get_unchecked(7..11));\n" +" }\n" +"\n" +" println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..7) }));\n" +"\n" +" // Not upholding the UTF-8 encoding requirement breaks memory safety!\n" +" // println!(\"emoji: {}\", unsafe { emojis.get_unchecked(0..3) });\n" +" // println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..3) }));\n" +"}\n" +"\n" +"fn count_chars(s: &str) -> usize {\n" +" s.chars().map(|_| 1).sum()\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:1 +#, fuzzy +msgid "# Writing Unsafe Functions" +msgstr "# Scrittura di funzioni non sicure" + +#: src/unsafe/writing-unsafe-functions.md:3 +#, fuzzy +msgid "" +"You can mark your own functions as `unsafe` if they require particular conditions to avoid undefined\n" +"behaviour." +msgstr "" +"Puoi contrassegnare le tue funzioni come \"non sicure\" se richiedono condizioni particolari per evitare undefined\n" +"comportamento." + +#: src/unsafe/writing-unsafe-functions.md:6 +msgid "" +"```rust,editable\n" +"/// Swaps the values pointed to by the given pointers.\n" +"///\n" +"/// # Safety\n" +"///\n" +"/// The pointers must be valid and properly aligned.\n" +"unsafe fn swap(a: *mut u8, b: *mut u8) {\n" +" let temp = *a;\n" +" *a = *b;\n" +" *b = temp;\n" +"}\n" +"\n" +"fn main() {\n" +" let mut a = 42;\n" +" let mut b = 66;\n" +"\n" +" // Safe because ...\n" +" unsafe {\n" +" swap(&mut a, &mut b);\n" +" }\n" +"\n" +" println!(\"a = {}, b = {}\", a, b);\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:33 +#, fuzzy +msgid "We wouldn't actually use pointers for this because it can be done safely with references." +msgstr "In realtà non useremmo i puntatori per questo perché può essere fatto in sicurezza con i riferimenti." + +#: src/unsafe/writing-unsafe-functions.md:35 +#, fuzzy +msgid "" +"Note that unsafe code is allowed within an unsafe function without an `unsafe` block. We can\n" +"prohibit this with `#[deny(unsafe_op_in_unsafe_fn)]`. Try adding it and see what happens." +msgstr "" +"Si noti che il codice non sicuro è consentito all'interno di una funzione non sicura senza un blocco `unsafe`. Noi possiamo\n" +"proibiscilo con `#[deny(unsafe_op_in_unsafe_fn)]`. Prova ad aggiungerlo e guarda cosa succede." + +#: src/unsafe/extern-functions.md:1 +#, fuzzy +msgid "# Calling External Code" +msgstr "# Chiamata codice esterno" + +#: src/unsafe/extern-functions.md:3 +#, fuzzy +msgid "" +"Functions from other languages might violate the guarantees of Rust. Calling\n" +"them is thus unsafe:" +msgstr "" +"Le funzioni di altri linguaggi potrebbero violare le garanzie di Rust. Chiamata\n" +"loro è quindi pericoloso:" + +#: src/unsafe/extern-functions.md:6 +msgid "" +"```rust,editable\n" +"extern \"C\" {\n" +" fn abs(input: i32) -> i32;\n" +"}\n" +"\n" +"fn main() {\n" +" unsafe {\n" +" // Undefined behavior if abs misbehaves.\n" +" println!(\"Absolute value of -3 according to C: {}\", abs(-3));\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/unsafe/extern-functions.md:21 +#, fuzzy +msgid "" +"This is usually only a problem for extern functions which do things with pointers which might\n" +"violate Rust's memory model, but in general any C function might have undefined behaviour under any\n" +"arbitrary circumstances." +msgstr "" +"Questo di solito è solo un problema per le funzioni esterne che fanno cose con i puntatori che potrebbero\n" +"violare il modello di memoria di Rust, ma in generale qualsiasi funzione C potrebbe avere un comportamento indefinito sotto qualsiasi\n" +"circostanze arbitrarie." + +#: src/unsafe/extern-functions.md:25 +msgid "" +"The `\"C\"` in this example is the ABI;\n" +"[other ABIs are available too](https://doc.rust-lang.org/reference/items/external-blocks.html)." +msgstr "" + +#: src/unsafe/unsafe-traits.md:1 +#, fuzzy +msgid "# Implementing Unsafe Traits" +msgstr "# Implementazione di tratti non sicuri" + +#: src/unsafe/unsafe-traits.md:3 +#, fuzzy +msgid "" +"Like with functions, you can mark a trait as `unsafe` if the implementation must guarantee\n" +"particular conditions to avoid undefined behaviour." +msgstr "" +"Come con le funzioni, puoi contrassegnare un tratto come \"non sicuro\" se l'implementazione deve garantire\n" +"condizioni particolari per evitare comportamenti indefiniti." + +#: src/unsafe/unsafe-traits.md:6 +#, fuzzy +msgid "" +"For example, the `zerocopy` crate has an unsafe trait that looks\n" +"[something like this](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" +msgstr "" +"Ad esempio, la cassa \"zerocopy\" ha un tratto non sicuro che sembra\n" +"[qualcosa del genere](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" + +#: src/unsafe/unsafe-traits.md:9 +msgid "" +"```rust,editable\n" +"use std::mem::size_of_val;\n" +"use std::slice;\n" +"\n" +"/// ...\n" +"/// # Safety\n" +"/// The type must have a defined representation and no padding.\n" +"pub unsafe trait AsBytes {\n" +" fn as_bytes(&self) -> &[u8] {\n" +" unsafe {\n" +" slice::from_raw_parts(self as *const Self as *const u8, size_of_val(self))\n" +" }\n" +" }\n" +"}\n" +"\n" +"// Safe because u32 has a defined representation and no padding.\n" +"unsafe impl AsBytes for u32 {}\n" +"```" +msgstr "" + +#: src/unsafe/unsafe-traits.md:30 +#, fuzzy +msgid "" +"There should be a `# Safety` section on the Rustdoc for the trait explaining the requirements for\n" +"the trait to be safely implemented." +msgstr "" +"Dovrebbe esserci una sezione `# Safety` su Rustdoc per il tratto che spiega i requisiti per\n" +"il tratto da implementare in modo sicuro." + +#: src/unsafe/unsafe-traits.md:33 +#, fuzzy +msgid "The actual safety section for `AsBytes` is rather longer and more complicated." +msgstr "L'attuale sezione sulla sicurezza per `AsBytes` è piuttosto lunga e complicata." + +#: src/unsafe/unsafe-traits.md:35 +#, fuzzy +msgid "The built-in `Send` and `Sync` traits are unsafe." +msgstr "I tratti incorporati \"Invia\" e \"Sincronizza\" non sono sicuri." + +#: src/exercises/day-3/afternoon.md:1 +#, fuzzy +msgid "# Day 3: Afternoon Exercises" +msgstr "# Giorno 3: Esercizi pomeridiani" + +#: src/exercises/day-3/afternoon.md:3 +#, fuzzy +msgid "Let us build a safe wrapper for reading directory content!" +msgstr "Costruiamo un wrapper sicuro per leggere il contenuto della directory!" + +#: src/exercises/day-3/afternoon.md:7 +#, fuzzy +msgid "After looking at the exercise, you can look at the [solution] provided." +msgstr "Dopo aver esaminato l'esercizio, puoi esaminare la [soluzione] fornita." + +#: src/exercises/day-3/safe-ffi-wrapper.md:1 +#, fuzzy +msgid "# Safe FFI Wrapper" +msgstr "# Wrapper FFI sicuro" + +#: src/exercises/day-3/safe-ffi-wrapper.md:3 +#, fuzzy +msgid "" +"Rust has great support for calling functions through a _foreign function\n" +"interface_ (FFI). We will use this to build a safe wrapper for the `libc`\n" +"functions you would use from C to read the filenames of a directory." +msgstr "" +"Rust ha un ottimo supporto per le funzioni di chiamata attraverso una funzione _foreign\n" +"interfaccia_ (FFI). Lo useremo per costruire un wrapper sicuro per `libc`\n" +"funzioni che useresti da C per leggere i nomi dei file di una directory." + +#: src/exercises/day-3/safe-ffi-wrapper.md:7 +#, fuzzy +msgid "You will want to consult the manual pages:" +msgstr "Ti consigliamo di consultare le pagine di manuale:" + +#: src/exercises/day-3/safe-ffi-wrapper.md:9 +#, fuzzy +msgid "" +"* [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)\n" +"* [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)\n" +"* [`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)" +msgstr "" +"* [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)\n" +"* [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)\n" +"* [`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. There you find a number of\n" +"string types which you need for the exercise:" +msgstr "" +"Dovrai anche sfogliare il modulo [`std::ffi`]. Lì trovi un numero di\n" +"tipi di stringa necessari per l'esercizio:" + +#: src/exercises/day-3/safe-ffi-wrapper.md:16 +#, fuzzy +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 "" +"| Tipi | Codifica | Usa |\n" +"|----------------------------|----------------|--- -----------------------------|\n" +"| [`str`] e [`String`] | UTF-8 | Elaborazione del testo in Rust |\n" +"| [`CStr`] e [`CString`] | con terminazione NUL | Comunicare con le funzioni C |\n" +"| [`OsStr`] e [`OsString`] | specifico del sistema operativo | Comunicazione con il sistema operativo |" + +#: src/exercises/day-3/safe-ffi-wrapper.md:22 +#, fuzzy +msgid "You will convert between all these types:" +msgstr "Potrai convertire tra tutti questi tipi:" + +#: src/exercises/day-3/safe-ffi-wrapper.md:24 +#, fuzzy +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 "" +"- Da `&str` a `CString`: è necessario allocare spazio per un carattere finale `\\0`,\n" +"- Da `CString` a `*const i8`: è necessario un puntatore per chiamare le funzioni C,\n" +"- Da `*const i8` a `&CStr`: hai bisogno di qualcosa che possa trovare il carattere finale `\\0`,\n" +"- da `&CStr` a `&[u8]`: una fetta di byte è l'interfaccia universale per \"alcuni dati sconosciuti\",\n" +"- Da `&[u8]` a `&OsStr`: `&OsStr` è un passo verso `OsString`, usa\n" +" [`OsStrExt`](https://doc.rust-lang.org/std/os/unix/ffi/trait.OsStrExt.html)\n" +" per crearlo,\n" +"- `&OsStr` a `OsString`: è necessario clonare i dati in `&OsStr` per poterlo restituire e chiamare\n" +" `readdir` di nuovo." + +#: src/exercises/day-3/safe-ffi-wrapper.md:34 +#, fuzzy +msgid "The [Nomicon] also has a very useful chapter about FFI." +msgstr "Il [Nomicon] ha anche un capitolo molto utile su FFI." + +#: src/exercises/day-3/safe-ffi-wrapper.md:45 +#, fuzzy +msgid "" +"Copy the code below to and fill in the missing\n" +"functions and methods:" +msgstr "" +"Copia il codice qui sotto in e inserisci quello mancante\n" +"funzioni e metodi:" + +#: 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" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int};\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" use std::os::raw::{c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" // Layout as per man entry for dirent\n" +" #[cfg(target_os = \"macos\")]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: u64,\n" +" pub d_seekoff: u64,\n" +" pub d_reclen: u16,\n" +" pub d_namlen: u16,\n" +" pub d_type: u8,\n" +" pub d_name: [c_char; 1024],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}\n" +"\n" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/android.md:1 +#, fuzzy +msgid "# Welcome to Rust in Android" +msgstr "# Benvenuto in Rust su Android" + +#: src/android.md:3 +#, fuzzy +msgid "" +"Rust is supported for native platform development on Android. This means that\n" +"you can write new operating system services in Rust, as well as extending\n" +"existing services." +msgstr "" +"Rust è supportato per lo sviluppo della piattaforma nativa su Android. Ciò significa che\n" +"puoi scrivere nuovi servizi del sistema operativo in Rust, oltre ad estenderli\n" +"servizi esistenti." + +#: src/android.md:7 +#, fuzzy +msgid "" +"> We will attempt to call Rust from one of your own projects today. So try to\n" +"> find a little corner of your code base where we can move some lines of code to\n" +"> Rust. The fewer dependencies and \"exotic\" types the better. Something that\n" +"> parses some raw bytes would be ideal." +msgstr "" +"> Oggi tenteremo di chiamare Rust da uno dei tuoi progetti. Quindi prova a\n" +"> trova un piccolo angolo della tua base di codice in cui possiamo spostare alcune righe di codice\n" +"> Ruggine. Minori sono le dipendenze e i tipi \"esotici\", meglio è. Qualcosa che\n" +"> analizza alcuni byte grezzi sarebbe l'ideale." + +#: src/android/setup.md:1 +#, fuzzy +msgid "# Setup" +msgstr "# Impostare" + +#: src/android/setup.md:3 +#, fuzzy +msgid "" +"We will be using an Android Virtual Device to test our code. Make sure you have\n" +"access to one or create a new one with:" +msgstr "" +"Useremo un dispositivo virtuale Android per testare il nostro codice. Assicurati di avere\n" +"accedi a uno o creane uno nuovo con:" + +#: src/android/setup.md:6 +msgid "" +"```shell\n" +"$ source build/envsetup.sh\n" +"$ lunch aosp_cf_x86_64_phone-userdebug\n" +"$ acloud create\n" +"```" +msgstr "" + +#: src/android/setup.md:12 +#, fuzzy +msgid "" +"Please see the [Android Developer\n" +"Codelab](https://source.android.com/docs/setup/start) for details." +msgstr "" +"Si prega di consultare il [Sviluppatore Android\n" +"Codelab](https://source.android.com/docs/setup/start) per i dettagli." + +#: src/android/build-rules.md:1 +#, fuzzy +msgid "# Build Rules" +msgstr "# Crea regole" + +#: src/android/build-rules.md:3 +#, fuzzy +msgid "The Android build system (Soong) supports Rust via a number of modules:" +msgstr "Il sistema di compilazione Android (Soong) supporta Rust tramite una serie di moduli:" + +#: src/android/build-rules.md:5 +#, fuzzy +msgid "" +"| Module Type | Description |\n" +"|-------------------|----------------------------------------------------------------------------------------------------|\n" +"| `rust_binary` | Produces a Rust binary. |\n" +"| `rust_library` | Produces a Rust library, and provides both `rlib` and `dylib` variants. |\n" +"| `rust_ffi` | Produces a Rust C library usable by `cc` modules, and provides both static and shared variants. |\n" +"| `rust_proc_macro` | Produces a `proc-macro` Rust library. These are analogous to compiler plugins. |\n" +"| `rust_test` | Produces a Rust test binary that uses the standard Rust test harness. |\n" +"| `rust_fuzz` | Produces a Rust fuzz binary leveraging `libfuzzer`. |\n" +"| `rust_protobuf` | Generates source and produces a Rust library that provides an interface for a particular protobuf. |\n" +"| `rust_bindgen` | Generates source and produces a Rust library containing Rust bindings to C libraries. |" +msgstr "" +"| Tipo di modulo | Descrizione |\n" +"|-------------------|-------------------------------------- -------------------------------------------------- ---------------------|\n" +"| `binario_ruggine` | Produce un binario Rust. |\n" +"| `libreria_ruggine` | Produce una libreria Rust e fornisce entrambe le varianti `rlib` e `dylib`. |\n" +"| `ruggine_ffi` | Produce una libreria Rust C utilizzabile dai moduli `cc` e fornisce varianti sia statiche che condivise. |\n" +"| `rust_proc_macro` | Produce una libreria Rust `proc-macro`. Questi sono analoghi ai plugin del compilatore. |\n" +"| `test_ruggine` | Produce un file binario di test Rust che utilizza il cablaggio di test Rust standard. |\n" +"| `ruggine_fuzz` | Produce un binario fuzz di Rust sfruttando `libfuzzer`. |\n" +"| `protobuf_ruggine` | Genera il codice sorgente e produce una libreria Rust che fornisce un'interfaccia per un particolare protobuf. |\n" +"| `ruggine_bindgen` | Genera il codice sorgente e produce una libreria Rust contenente collegamenti Rust alle librerie C. |" + +#: src/android/build-rules.md:16 +#, fuzzy +msgid "We will look at `rust_binary` and `rust_library` next." +msgstr "Vedremo successivamente `rust_binary` e `rust_library`." + +#: src/android/build-rules/binary.md:1 +#, fuzzy +msgid "# Rust Binaries" +msgstr "# Binari Rust" + +#: src/android/build-rules/binary.md:3 +#, fuzzy +msgid "" +"Let us start with a simple application. At the root of an AOSP checkout, create\n" +"the following files:" +msgstr "" +"Iniziamo con una semplice applicazione. Alla radice di un checkout AOSP, create\n" +"i seguenti file:" + +#: src/android/build-rules/binary.md:6 src/android/build-rules/library.md:13 +#, fuzzy +msgid "_hello_rust/Android.bp_:" +msgstr "_ciao_rust/Android.bp_:" + +#: src/android/build-rules/binary.md:8 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust\",\n" +" crate_name: \"hello_rust\",\n" +" srcs: [\"src/main.rs\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md:16 src/android/build-rules/library.md:34 +#, fuzzy +msgid "_hello_rust/src/main.rs_:" +msgstr "_ciao_rust/src/main.rs_:" + +#: src/android/build-rules/binary.md:18 +msgid "" +"```rust\n" +"//! Rust demo.\n" +"\n" +"/// Prints a greeting to standard output.\n" +"fn main() {\n" +" println!(\"Hello from Rust!\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md:27 +#, fuzzy +msgid "You can now build, push, and run the binary:" +msgstr "Ora puoi creare, inviare ed eseguire il binario:" + +#: src/android/build-rules/binary.md:29 +msgid "" +"```shell\n" +"$ m hello_rust\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust\n" +"Hello from Rust!\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:1 +#, fuzzy +msgid "# Rust Libraries" +msgstr "# Librerie ruggine" + +#: src/android/build-rules/library.md:3 +#, fuzzy +msgid "You use `rust_library` to create a new Rust library for Android." +msgstr "Usa `rust_library` per creare una nuova libreria Rust per Android." + +#: src/android/build-rules/library.md:5 +#, fuzzy +msgid "Here we declare a dependency on two libraries:" +msgstr "Qui dichiariamo una dipendenza da due librerie:" + +#: src/android/build-rules/library.md:7 +#, fuzzy +msgid "" +"* `libgreeting`, which we define below,\n" +"* `libtextwrap`, which is a crate already vendored in\n" +" [`external/rust/crates/`][crates]." +msgstr "" +"* `libgreeting`, che definiamo di seguito,\n" +"* `libtextwrap`, che è una cassa già venduta\n" +" [`external/rust/crates/`][crates]." + +#: src/android/build-rules/library.md:15 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_with_dep\",\n" +" crate_name: \"hello_rust_with_dep\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libgreetings\",\n" +" \"libtextwrap\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"\n" +"rust_library {\n" +" name: \"libgreetings\",\n" +" crate_name: \"greetings\",\n" +" srcs: [\"src/lib.rs\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:36 +msgid "" +"```rust,ignore\n" +"//! Rust demo.\n" +"\n" +"use greetings::greeting;\n" +"use textwrap::fill;\n" +"\n" +"/// Prints a greeting to standard output.\n" +"fn main() {\n" +" println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:48 +#, fuzzy +msgid "_hello_rust/src/lib.rs_:" +msgstr "_ciao_rust/src/lib.rs_:" + +#: src/android/build-rules/library.md:50 +msgid "" +"```rust,ignore\n" +"//! Greeting library.\n" +"\n" +"/// Greet `name`.\n" +"pub fn greeting(name: &str) -> String {\n" +" format!(\"Hello {name}, it is very nice to meet you!\")\n" +"}\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:59 +#, fuzzy +msgid "You build, push, and run the binary like before:" +msgstr "Costruisci, spingi ed esegui il binario come prima:" + +#: src/android/build-rules/library.md:61 +msgid "" +"```shell\n" +"$ m hello_rust_with_dep\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust_with_dep\n" +"Hello Bob, it is very\n" +"nice to meet you!\n" +"```" +msgstr "" + +#: src/android/aidl.md:1 +#, fuzzy +msgid "# AIDL" +msgstr "#AIDL" + +#: src/android/aidl.md:3 +#, fuzzy +msgid "" +"The [Android Interface Definition Language\n" +"(AIDL)](https://developer.android.com/guide/components/aidl) is supported in Rust:" +msgstr "" +"Il [linguaggio di definizione dell'interfaccia Android\n" +"(AIDL)](https://developer.android.com/guide/components/aidl) è supportato in Rust:" + +#: src/android/aidl.md:6 +#, fuzzy +msgid "" +"* Rust code can call existing AIDL servers,\n" +"* You can create new AIDL servers in Rust." +msgstr "" +"* Il codice Rust può chiamare i server AIDL esistenti,\n" +"* Puoi creare nuovi server AIDL in Rust." + +#: src/android/aidl/interface.md:1 +#, fuzzy +msgid "# AIDL Interfaces" +msgstr "# Interfacce AIDL" + +#: src/android/aidl/interface.md:3 +#, fuzzy +msgid "You declare the API of your service using an AIDL interface:" +msgstr "Dichiari l'API del tuo servizio utilizzando un'interfaccia AIDL:" + +#: src/android/aidl/interface.md:5 +#, fuzzy +msgid "*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" +msgstr "*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" + +#: src/android/aidl/interface.md:7 +msgid "" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years);\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/interface.md:17 +#, fuzzy +msgid "*birthday_service/aidl/Android.bp*:" +msgstr "*servizio_compleanno/aidl/Android.bp*:" + +#: src/android/aidl/interface.md:19 +msgid "" +"```javascript\n" +"aidl_interface {\n" +" name: \"com.example.birthdayservice\",\n" +" srcs: [\"com/example/birthdayservice/*.aidl\"],\n" +" unstable: true,\n" +" backend: {\n" +" rust: { // Rust is not enabled by default\n" +" enabled: true,\n" +" },\n" +" },\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/interface.md:32 +#, fuzzy +msgid "" +"Add `vendor_available: true` if your AIDL file is used by a binary in the vendor\n" +"partition." +msgstr "" +"Aggiungi \"vendor_available: true\" se il tuo file AIDL è utilizzato da un file binario nel fornitore\n" +"partizione." + +#: src/android/aidl/implementation.md:1 +#, fuzzy +msgid "# Service Implementation" +msgstr "# Implementazione del servizio" + +#: src/android/aidl/implementation.md:3 +#, fuzzy +msgid "We can now implement the AIDL service:" +msgstr "Ora possiamo implementare il servizio AIDL:" + +#: src/android/aidl/implementation.md:5 +#, fuzzy +msgid "*birthday_service/src/lib.rs*:" +msgstr "*servizio_compleanno/src/lib.rs*:" + +#: src/android/aidl/implementation.md:7 +msgid "" +"```rust,ignore\n" +"//! Implementation of the `IBirthdayService` AIDL interface.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"/// The `IBirthdayService` implementation.\n" +"pub struct BirthdayService;\n" +"\n" +"impl binder::Interface for BirthdayService {}\n" +"\n" +"impl IBirthdayService for BirthdayService {\n" +" fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result {\n" +" Ok(format!(\n" +" \"Happy Birthday {name}, congratulations with the {years} years!\"\n" +" ))\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/implementation.md:26 src/android/aidl/server.md:28 src/android/aidl/client.md:37 +#, fuzzy +msgid "*birthday_service/Android.bp*:" +msgstr "*servizio_compleanno/Android.bp*:" + +#: src/android/aidl/implementation.md:28 +msgid "" +"```javascript\n" +"rust_library {\n" +" name: \"libbirthdayservice\",\n" +" srcs: [\"src/lib.rs\"],\n" +" crate_name: \"birthdayservice\",\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/server.md:1 +#, fuzzy +msgid "# AIDL Server" +msgstr "# Server AIDL" + +#: src/android/aidl/server.md:3 +#, fuzzy +msgid "Finally, we can create a server which exposes the service:" +msgstr "Infine, possiamo creare un server che espone il servizio:" + +#: src/android/aidl/server.md:5 +#, fuzzy +msgid "*birthday_service/src/server.rs*:" +msgstr "*servizio_compleanno/src/server.rs*:" + +#: src/android/aidl/server.md:7 +msgid "" +"```rust,ignore\n" +"//! Birthday service.\n" +"use birthdayservice::BirthdayService;\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::BnBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" +"/// Entry point for birthday service.\n" +"fn main() {\n" +" let birthday_service = BirthdayService;\n" +" let birthday_service_binder = BnBirthdayService::new_binder(\n" +" birthday_service,\n" +" binder::BinderFeatures::default(),\n" +" );\n" +" binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder.as_binder())\n" +" .expect(\"Failed to register service\");\n" +" binder::ProcessState::join_thread_pool()\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/server.md:30 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_server\",\n" +" crate_name: \"birthday_server\",\n" +" srcs: [\"src/server.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" \"libbirthdayservice\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:1 +#, fuzzy +msgid "# Deploy" +msgstr "# Distribuisci" + +#: src/android/aidl/deploy.md:3 +#, fuzzy +msgid "We can now build, push, and start the service:" +msgstr "Ora possiamo creare, inviare e avviare il servizio:" + +#: src/android/aidl/deploy.md:5 +msgid "" +"```shell\n" +"$ m birthday_server\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_server\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:11 +#, fuzzy +msgid "In another terminal, check that the service runs:" +msgstr "In un altro terminale, controlla che il servizio sia in esecuzione:" + +#: src/android/aidl/deploy.md:13 +msgid "" +"```shell\n" +"$ adb shell service check birthdayservice\n" +"Service birthdayservice: found\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:18 +#, fuzzy +msgid "You can also call the service with `service call`:" +msgstr "Puoi anche chiamare il servizio con `service call`:" + +#: src/android/aidl/deploy.md:20 +msgid "" +"```shell\n" +"$ $ adb shell service call birthdayservice 1 s16 Bob i32 24\n" +"Result: Parcel(\n" +" 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" +" 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" +" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'\n" +" 0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'\n" +" 0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'\n" +" 0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'\n" +" 0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'\n" +" 0x00000070: 00210073 00000000 's.!..... ')\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:1 +#, fuzzy +msgid "# AIDL Client" +msgstr "# Cliente AIDL" + +#: src/android/aidl/client.md:3 +#, fuzzy +msgid "Finally, we can create a Rust client for our new service." +msgstr "Infine, possiamo creare un client Rust per il nostro nuovo servizio." + +#: src/android/aidl/client.md:5 +#, fuzzy +msgid "*birthday_service/src/client.rs*:" +msgstr "*servizio_compleanno/src/client.rs*:" + +#: src/android/aidl/client.md:7 +msgid "" +"```rust,ignore\n" +"//! Birthday service.\n" +"use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;\n" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" +"/// Connect to the BirthdayService.\n" +"pub fn connect() -> Result, binder::StatusCode> {\n" +" binder::get_interface(SERVICE_IDENTIFIER)\n" +"}\n" +"\n" +"/// Call the birthday service.\n" +"fn main() -> Result<(), binder::Status> {\n" +" let name = std::env::args()\n" +" .nth(1)\n" +" .unwrap_or_else(|| String::from(\"Bob\"));\n" +" let years = std::env::args()\n" +" .nth(2)\n" +" .and_then(|arg| arg.parse::().ok())\n" +" .unwrap_or(42);\n" +"\n" +" binder::ProcessState::start_thread_pool();\n" +" let service = connect().expect(\"Failed to connect to BirthdayService\");\n" +" let msg = service.wishHappyBirthday(&name, years)?;\n" +" println!(\"{msg}\");\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:39 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"birthday_client\",\n" +" crate_name: \"birthday_client\",\n" +" srcs: [\"src/client.rs\"],\n" +" rustlibs: [\n" +" \"com.example.birthdayservice-rust\",\n" +" \"libbinder_rs\",\n" +" ],\n" +" prefer_rlib: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:52 +#, fuzzy +msgid "Notice that the client does not depend on `libbirthdayservice`." +msgstr "Si noti che il client non dipende da `libbirthdayservice`." + +#: src/android/aidl/client.md:54 +#, fuzzy +msgid "Build, push, and run the client on your device:" +msgstr "Crea, invia ed esegui il client sul tuo dispositivo:" + +#: src/android/aidl/client.md:56 +msgid "" +"```shell\n" +"$ m birthday_client\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp\n" +"$ adb shell /data/local/tmp/birthday_client Charlie 60\n" +"Happy Birthday Charlie, congratulations with the 60 years!\n" +"```" +msgstr "" + +#: src/android/aidl/changing.md:1 +#, fuzzy +msgid "# Changing API" +msgstr "# Modifica dell'API" + +#: src/android/aidl/changing.md:3 +#, fuzzy +msgid "" +"Let us extend the API with more functionality: we want to let clients specify a\n" +"list of lines for the birthday card:" +msgstr "" +"Estendiamo l'API con più funzionalità: vogliamo consentire ai client di specificare a\n" +"elenco delle righe per il biglietto d'auguri:" + +#: src/android/aidl/changing.md:6 +msgid "" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" +"/** Birthday service interface. */\n" +"interface IBirthdayService {\n" +" /** Generate a Happy Birthday message. */\n" +" String wishHappyBirthday(String name, int years, in String[] text);\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:1 src/bare-metal/aps/logging.md:1 +#, fuzzy +msgid "# Logging" +msgstr "# Registrazione" + +#: src/android/logging.md:3 +#, fuzzy +msgid "" +"You should use the `log` crate to automatically log to `logcat` (on-device) or\n" +"`stdout` (on-host):" +msgstr "" +"Dovresti usare la cassa `log` per accedere automaticamente a `logcat` (sul dispositivo) o\n" +"`stdout` (sull'host):" + +#: src/android/logging.md:6 +#, fuzzy +msgid "_hello_rust_logs/Android.bp_:" +msgstr "_ciao_rust_logs/Android.bp_:" + +#: src/android/logging.md:8 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"hello_rust_logs\",\n" +" crate_name: \"hello_rust_logs\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"liblog_rust\",\n" +" \"liblogger\",\n" +" ],\n" +" prefer_rlib: true,\n" +" host_supported: true,\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:22 +#, fuzzy +msgid "_hello_rust_logs/src/main.rs_:" +msgstr "_ciao_rust_logs/src/main.rs_:" + +#: src/android/logging.md:24 +msgid "" +"```rust,ignore\n" +"//! Rust logging demo.\n" +"\n" +"use log::{debug, error, info};\n" +"\n" +"/// Logs a greeting.\n" +"fn main() {\n" +" logger::init(\n" +" logger::Config::default()\n" +" .with_tag_on_device(\"rust\")\n" +" .with_min_level(log::Level::Trace),\n" +" );\n" +" debug!(\"Starting program.\");\n" +" info!(\"Things are going fine.\");\n" +" error!(\"Something went wrong!\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/logging.md:42 src/android/interoperability/with-c/bindgen.md:98 src/android/interoperability/with-c/rust.md:73 +#, fuzzy +msgid "Build, push, and run the binary on your device:" +msgstr "Crea, invia ed esegui il file binario sul tuo dispositivo:" + +#: src/android/logging.md:44 +msgid "" +"```shell\n" +"$ m hello_rust_logs\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/tmp\n" +"$ adb shell /data/local/tmp/hello_rust_logs\n" +"```" +msgstr "" + +#: src/android/logging.md:50 +#, fuzzy +msgid "The logs show up in `adb logcat`:" +msgstr "I log vengono visualizzati in `adb logcat`:" + +#: src/android/logging.md:52 +msgid "" +"```shell\n" +"$ adb logcat -s rust\n" +"09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.\n" +"09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going fine.\n" +"09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went wrong!\n" +"```" +msgstr "" + +#: src/android/interoperability.md:1 +#, fuzzy +msgid "# Interoperability" +msgstr "# Interoperabilità" + +#: src/android/interoperability.md:3 +#, fuzzy +msgid "" +"Rust has excellent support for interoperability with other languages. This means\n" +"that you can:" +msgstr "" +"Rust ha un eccellente supporto per l'interoperabilità con altri linguaggi. Questo significa\n" +"che tu puoi:" + +#: src/android/interoperability.md:6 +#, fuzzy +msgid "" +"* Call Rust functions from other languages.\n" +"* Call functions written in other languages from Rust." +msgstr "" +"* Richiama le funzioni di Rust da altre lingue.\n" +"* Funzioni di chiamata scritte in altri linguaggi da Rust." + +#: src/android/interoperability.md:9 +#, fuzzy +msgid "" +"When you call functions in a foreign language we say that you're using a\n" +"_foreign function interface_, also known as FFI." +msgstr "" +"Quando chiami funzioni in una lingua straniera diciamo che stai usando a\n" +"_interfaccia funzione straniera_, nota anche come FFI." + +#: src/android/interoperability/with-c.md:1 +#, fuzzy +msgid "# Interoperability with C" +msgstr "# Interoperabilità con C" + +#: src/android/interoperability/with-c.md:3 +#, fuzzy +msgid "" +"Rust has full support for linking object files with a C calling convention.\n" +"Similarly, you can export Rust functions and call them from C." +msgstr "" +"Rust ha il pieno supporto per il collegamento di file oggetto con una convenzione di chiamata C.\n" +"Allo stesso modo, puoi esportare le funzioni di Rust e chiamarle da C." + +#: src/android/interoperability/with-c.md:6 +#, fuzzy +msgid "You can do it by hand if you want:" +msgstr "Puoi farlo a mano se vuoi:" + +#: src/android/interoperability/with-c.md:8 +msgid "" +"```rust\n" +"extern \"C\" {\n" +" fn abs(x: i32) -> i32;\n" +"}\n" +"\n" +"fn main() {\n" +" let x = -42;\n" +" let abs_x = unsafe { abs(x) };\n" +" println!(\"{x}, {abs_x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c.md:20 +#, fuzzy +msgid "" +"We already saw this in the [Safe FFI Wrapper\n" +"exercise](../../exercises/day-3/safe-ffi-wrapper.md)." +msgstr "" +"Lo abbiamo già visto nel [Safe FFI Wrapper\n" +"esercizio](../../exercises/day-3/safe-ffi-wrapper.md)." + +#: src/android/interoperability/with-c.md:23 +#, fuzzy +msgid "" +"> This assumes full knowledge of the target platform. Not recommended for\n" +"> production." +msgstr "" +"> Ciò presuppone la piena conoscenza della piattaforma di destinazione. Non consigliato per\n" +"> produzione." + +#: src/android/interoperability/with-c.md:26 +#, fuzzy +msgid "We will look at better options next." +msgstr "Vedremo le opzioni migliori in seguito." + +#: src/android/interoperability/with-c/bindgen.md:1 +#, fuzzy +msgid "# Using Bindgen" +msgstr "# Utilizzo di Bindgen" + +#: src/android/interoperability/with-c/bindgen.md:3 +#, fuzzy +msgid "" +"The [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html) tool\n" +"can auto-generate bindings from a C header file." +msgstr "" +"Lo strumento [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html)\n" +"può generare automaticamente collegamenti da un file di intestazione C." + +#: src/android/interoperability/with-c/bindgen.md:6 +#, fuzzy +msgid "First create a small C library:" +msgstr "Per prima cosa crea una piccola libreria C:" + +#: src/android/interoperability/with-c/bindgen.md:8 +#, fuzzy +msgid "_interoperability/bindgen/libbirthday.h_:" +msgstr "_interoperabilità/bindgen/libbirthday.h_:" + +#: src/android/interoperability/with-c/bindgen.md:10 +msgid "" +"```c\n" +"typedef struct card {\n" +" const char* name;\n" +" int years;\n" +"} card;\n" +"\n" +"void print_card(const card* card);\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:19 +#, fuzzy +msgid "_interoperability/bindgen/libbirthday.c_:" +msgstr "_interoperabilità/bindgen/libbirthday.c_:" + +#: src/android/interoperability/with-c/bindgen.md:21 +msgid "" +"```c\n" +"#include \n" +"#include \"libbirthday.h\"\n" +"\n" +"void print_card(const card* card) {\n" +" printf(\"+--------------\\n\");\n" +" printf(\"| Happy Birthday %s!\\n\", card->name);\n" +" printf(\"| Congratulations with the %i years!\\n\", card->years);\n" +" printf(\"+--------------\\n\");\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:33 +#, fuzzy +msgid "Add this to your `Android.bp` file:" +msgstr "Aggiungi questo al tuo file `Android.bp`:" + +#: src/android/interoperability/with-c/bindgen.md:35 src/android/interoperability/with-c/bindgen.md:55 +#: src/android/interoperability/with-c/bindgen.md:69 src/android/interoperability/with-c/bindgen.md:108 +#, fuzzy +msgid "_interoperability/bindgen/Android.bp_:" +msgstr "_interoperabilità/bindgen/Android.bp_:" + +#: src/android/interoperability/with-c/bindgen.md:37 +msgid "" +"```javascript\n" +"cc_library {\n" +" name: \"libbirthday\",\n" +" srcs: [\"libbirthday.c\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:44 +#, fuzzy +msgid "" +"Create a wrapper header file for the library (not strictly needed in this\n" +"example):" +msgstr "" +"Crea un file di intestazione wrapper per la libreria (non strettamente necessario in questo\n" +"esempio):" + +#: src/android/interoperability/with-c/bindgen.md:47 +#, fuzzy +msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" +msgstr "_interoperabilità/bindgen/libbirthday_wrapper.h_:" + +#: src/android/interoperability/with-c/bindgen.md:49 +msgid "" +"```c\n" +"#include \"libbirthday.h\"\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:53 +#, fuzzy +msgid "You can now auto-generate the bindings:" +msgstr "Ora puoi generare automaticamente le associazioni:" + +#: src/android/interoperability/with-c/bindgen.md:57 +msgid "" +"```javascript\n" +"rust_bindgen {\n" +" name: \"libbirthday_bindgen\",\n" +" crate_name: \"birthday_bindgen\",\n" +" wrapper_src: \"libbirthday_wrapper.h\",\n" +" source_stem: \"bindings\",\n" +" static_libs: [\"libbirthday\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:67 +#, fuzzy +msgid "Finally, we can use the bindings in our Rust program:" +msgstr "Infine, possiamo usare i binding nel nostro programma Rust:" + +#: src/android/interoperability/with-c/bindgen.md:71 +msgid "" +"```javascript\n" +"rust_binary {\n" +" name: \"print_birthday_card\",\n" +" srcs: [\"main.rs\"],\n" +" rustlibs: [\"libbirthday_bindgen\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:79 +#, fuzzy +msgid "_interoperability/bindgen/main.rs_:" +msgstr "_interoperabilità/bindgen/main.rs_:" + +#: src/android/interoperability/with-c/bindgen.md:81 +msgid "" +"```rust,compile_fail\n" +"//! Bindgen demo.\n" +"\n" +"use birthday_bindgen::{card, print_card};\n" +"\n" +"fn main() {\n" +" let name = std::ffi::CString::new(\"Peter\").unwrap();\n" +" let card = card {\n" +" name: name.as_ptr(),\n" +" years: 42,\n" +" };\n" +" unsafe {\n" +" print_card(&card as *const card);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:100 +msgid "" +"```shell\n" +"$ m print_birthday_card\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/tmp\n" +"$ adb shell /data/local/tmp/print_birthday_card\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:106 +#, fuzzy +msgid "Finally, we can run auto-generated tests to ensure the bindings work:" +msgstr "Infine, possiamo eseguire test generati automaticamente per garantire che i binding funzionino:" + +#: src/android/interoperability/with-c/bindgen.md:110 +msgid "" +"```javascript\n" +"rust_test {\n" +" name: \"libbirthday_bindgen_test\",\n" +" srcs: [\":libbirthday_bindgen\"],\n" +" crate_name: \"libbirthday_bindgen_test\",\n" +" test_suites: [\"general-tests\"],\n" +" auto_gen_config: true,\n" +" clippy_lints: \"none\", // Generated file, skip linting\n" +" lints: \"none\",\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:122 +msgid "" +"```shell\n" +"$ atest libbirthday_bindgen_test\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:1 +#, fuzzy +msgid "# Calling Rust" +msgstr "# Calling Rust" + +#: src/android/interoperability/with-c/rust.md:3 +#, fuzzy +msgid "Exporting Rust functions and types to C is easy:" +msgstr "Esportare le funzioni e i tipi di Rust in C è facile:" + +#: src/android/interoperability/with-c/rust.md:5 +#, fuzzy +msgid "_interoperability/rust/libanalyze/analyze.rs_" +msgstr "_interoperabilità/ruggine/libanalyze/analyze.rs_" + +#: src/android/interoperability/with-c/rust.md:7 +msgid "" +"```rust,editable\n" +"//! Rust FFI demo.\n" +"#![deny(improper_ctypes_definitions)]\n" +"\n" +"use std::os::raw::c_int;\n" +"\n" +"/// Analyze the numbers.\n" +"#[no_mangle]\n" +"pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" +" if x < y {\n" +" println!(\"x ({x}) is smallest!\");\n" +" } else {\n" +" println!(\"y ({y}) is probably larger than x ({x})\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:24 +#, fuzzy +msgid "_interoperability/rust/libanalyze/analyze.h_" +msgstr "_interoperabilità/ruggine/libanalyze/analyze.h_" + +#: src/android/interoperability/with-c/rust.md:26 +msgid "" +"```c\n" +"#ifndef ANALYSE_H\n" +"#define ANALYSE_H\n" +"\n" +"extern \"C\" {\n" +"void analyze_numbers(int x, int y);\n" +"}\n" +"\n" +"#endif\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:37 +#, fuzzy +msgid "_interoperability/rust/libanalyze/Android.bp_" +msgstr "_interoperabilità/ruggine/libanalyze/Android.bp_" + +#: src/android/interoperability/with-c/rust.md:39 +msgid "" +"```javascript\n" +"rust_ffi {\n" +" name: \"libanalyze_ffi\",\n" +" crate_name: \"analyze_ffi\",\n" +" srcs: [\"analyze.rs\"],\n" +" include_dirs: [\".\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:48 +#, fuzzy +msgid "We can now call this from a C binary:" +msgstr "Ora possiamo chiamarlo da un binario C:" + +#: src/android/interoperability/with-c/rust.md:50 +#, fuzzy +msgid "_interoperability/rust/analyze/main.c_" +msgstr "_interoperabilità/rust/analyze/main.c_" + +#: src/android/interoperability/with-c/rust.md:52 +msgid "" +"```c\n" +"#include \"analyze.h\"\n" +"\n" +"int main() {\n" +" analyze_numbers(10, 20);\n" +" analyze_numbers(123, 123);\n" +" return 0;\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:62 +#, fuzzy +msgid "_interoperability/rust/analyze/Android.bp_" +msgstr "_interoperabilità/ruggine/analisi/Android.bp_" + +#: src/android/interoperability/with-c/rust.md:64 +msgid "" +"```javascript\n" +"cc_binary {\n" +" name: \"analyze_numbers\",\n" +" srcs: [\"main.c\"],\n" +" static_libs: [\"libanalyze_ffi\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:75 +msgid "" +"```shell\n" +"$ m analyze_numbers\n" +"$ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp\n" +"$ adb shell /data/local/tmp/analyze_numbers\n" +"```" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:83 +#, fuzzy +msgid "" +"`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol will just be the name of\n" +"the function. You can also use `#[export_name = \"some_name\"]` to specify whatever name you want." +msgstr "" +"`#[no_mangle]` disabilita la solita alterazione del nome di Rust, quindi il simbolo esportato sarà solo il nome di\n" +"la funzione. Puoi anche usare `#[export_name = \"some_name\"]` per specificare il nome che desideri." + +#: src/android/interoperability/cpp.md:1 +#, fuzzy +msgid "# With C++" +msgstr "# Con C++" + +#: src/android/interoperability/cpp.md:3 +#, fuzzy +msgid "" +"The [CXX crate][1] makes it possible to do safe interoperability between Rust\n" +"and C++." +msgstr "" +"Il [CXX crate][1] rende possibile l'interoperabilità sicura tra Rust\n" +"e C++." + +#: src/android/interoperability/cpp.md:6 +#, fuzzy +msgid "The overall approach looks like this:" +msgstr "L'approccio generale è simile al seguente:" + +#: src/android/interoperability/cpp.md:8 +#, fuzzy +msgid "" +msgstr "" + +#: src/android/interoperability/cpp.md:10 +#, fuzzy +msgid "See the [CXX tutorial][2] for an full example of using this." +msgstr "Vedere il [tutorial CXX][2] per un esempio completo di utilizzo di questo." + +#: src/android/interoperability/java.md:1 +#, fuzzy +msgid "# Interoperability with Java" +msgstr "# Interoperabilità con Java" + +#: src/android/interoperability/java.md:3 +#, fuzzy +msgid "" +"Java can load shared objects via [Java Native Interface\n" +"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). The [`jni`\n" +"crate](https://docs.rs/jni/) allows you to create a compatible library." +msgstr "" +"Java può caricare oggetti condivisi tramite [Java Native Interface\n" +"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). Il [`jni`\n" +"crate](https://docs.rs/jni/) consente di creare una libreria compatibile." + +#: src/android/interoperability/java.md:7 +#, fuzzy +msgid "First, we create a Rust function to export to Java:" +msgstr "Innanzitutto, creiamo una funzione Rust da esportare in Java:" + +#: src/android/interoperability/java.md:9 +#, fuzzy +msgid "_interoperability/java/src/lib.rs_:" +msgstr "_interoperabilità/java/src/lib.rs_:" + +#: src/android/interoperability/java.md:11 +msgid "" +"```rust,compile_fail\n" +"//! Rust <-> Java FFI demo.\n" +"\n" +"use jni::objects::{JClass, JString};\n" +"use jni::sys::jstring;\n" +"use jni::JNIEnv;\n" +"\n" +"/// HelloWorld::hello method implementation.\n" +"#[no_mangle]\n" +"pub extern \"system\" fn Java_HelloWorld_hello(\n" +" env: JNIEnv,\n" +" _class: JClass,\n" +" name: JString,\n" +") -> jstring {\n" +" let input: String = env.get_string(name).unwrap().into();\n" +" let greeting = format!(\"Hello, {input}!\");\n" +" let output = env.new_string(greeting).unwrap();\n" +" output.into_inner()\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:32 src/android/interoperability/java.md:62 +#, fuzzy +msgid "_interoperability/java/Android.bp_:" +msgstr "_interoperabilità/java/Android.bp_:" + +#: src/android/interoperability/java.md:34 +msgid "" +"```javascript\n" +"rust_ffi_shared {\n" +" name: \"libhello_jni\",\n" +" crate_name: \"hello_jni\",\n" +" srcs: [\"src/lib.rs\"],\n" +" rustlibs: [\"libjni\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:43 +#, fuzzy +msgid "Finally, we can call this function from Java:" +msgstr "Infine, possiamo chiamare questa funzione da Java:" + +#: src/android/interoperability/java.md:45 +#, fuzzy +msgid "_interoperability/java/HelloWorld.java_:" +msgstr "_interoperabilità/java/HelloWorld.java_:" + +#: src/android/interoperability/java.md:47 +msgid "" +"```java\n" +"class HelloWorld {\n" +" private static native String hello(String name);\n" +"\n" +" static {\n" +" System.loadLibrary(\"hello_jni\");\n" +" }\n" +"\n" +" public static void main(String[] args) {\n" +" String output = HelloWorld.hello(\"Alice\");\n" +" System.out.println(output);\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:64 +msgid "" +"```javascript\n" +"java_binary {\n" +" name: \"helloworld_jni\",\n" +" srcs: [\"HelloWorld.java\"],\n" +" main_class: \"HelloWorld\",\n" +" required: [\"libhello_jni\"],\n" +"}\n" +"```" +msgstr "" + +#: src/android/interoperability/java.md:73 +#, fuzzy +msgid "Finally, you can build, sync, and run the binary:" +msgstr "Infine, puoi creare, sincronizzare ed eseguire il binario:" + +#: src/android/interoperability/java.md:75 +msgid "" +"```shell\n" +"$ m helloworld_jni\n" +"$ adb sync # requires adb root && adb remount\n" +"$ adb shell /system/bin/helloworld_jni\n" +"```" +msgstr "" + +#: src/exercises/android/morning.md:1 src/exercises/bare-metal/morning.md:1 src/exercises/bare-metal/afternoon.md:1 +#: src/exercises/concurrency/morning.md:1 +#, fuzzy +msgid "# Exercises" +msgstr "# Esercizi" + +#: src/exercises/android/morning.md:3 +#, fuzzy +msgid "" +"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 "" +"Questo è un esercizio di gruppo: esamineremo uno dei progetti con cui lavori e\n" +"prova a integrarci un po' di ruggine. Alcuni suggerimenti:" + +#: src/exercises/android/morning.md:6 +#, fuzzy +msgid "" +"* Call your AIDL service with a client written in Rust.\n" +"\n" +"* Move a function from your project to Rust and call it." +msgstr "" +"* Chiama il tuo servizio AIDL con un client scritto in Rust.\n" +"\n" +"* Sposta una funzione dal tuo progetto a Rust e chiamala." + +#: src/exercises/android/morning.md:12 +#, fuzzy +msgid "" +"No solution is provided here since this is open-ended: it relies on someone in\n" +"the class having a piece of code which you can turn in to Rust on the fly." +msgstr "" +"Nessuna soluzione viene fornita qui poiché questo è a tempo indeterminato: si basa su qualcuno dentro\n" +"la classe ha un pezzo di codice che puoi consegnare a Rust al volo." + +#: src/bare-metal.md:1 +#, fuzzy +msgid "# Welcome to Bare Metal Rust" +msgstr "# Benvenuto in Bare Metal Rust" + +#: src/bare-metal.md:3 +#, fuzzy +msgid "" +"This is a standalone one-day course about bare-metal Rust, aimed at people who are familiar with the\n" +"basics of Rust (perhaps from completing the Comprehensive Rust course), and ideally also have some\n" +"experience with bare-metal programming in some other language such as C." +msgstr "" +"Questo è un corso autonomo di un giorno sul bare metal Rust, rivolto a persone che hanno familiarità con il\n" +"nozioni di base di Rust (forse completando il corso completo di Rust), e idealmente anche averne alcune\n" +"esperienza con la programmazione bare metal in qualche altro linguaggio come C." + +#: src/bare-metal.md:7 +#, fuzzy +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 "" +"Oggi parleremo di Rust 'bare-metal': eseguire il codice Rust senza un sistema operativo sotto di noi. Questo sarà\n" +"essere suddiviso in più parti:" + +#: src/bare-metal.md:10 +#, fuzzy +msgid "" +"- What is `no_std` Rust?\n" +"- Writing firmware for microcontrollers.\n" +"- Writing bootloader / kernel code for application processors.\n" +"- Some useful crates for bare-metal Rust development." +msgstr "" +"- Cos'è \"no_std\" Rust?\n" +"- Scrittura firmware per microcontrollori.\n" +"- Scrittura del codice bootloader/kernel per i processori delle applicazioni.\n" +"- Alcune casse utili per lo sviluppo di ruggine a metallo nudo." + +#: src/bare-metal.md:15 +#, fuzzy +msgid "" +"For the microcontroller part of the course we will use the [BBC micro:bit](https://microbit.org/) v2\n" +"as an example. It's a [development board](https://tech.microbit.org/hardware/) based on the Nordic\n" +"nRF51822 microcontroller with some LEDs and buttons, an I2C-connected accelerometer and compass, and\n" +"an on-board SWD debugger." +msgstr "" +"Per la parte del corso sui microcontrollori utilizzeremo la [BBC micro:bit](https://microbit.org/) v2\n" +"come esempio. È una [scheda di sviluppo](https://tech.microbit.org/hardware/) basata sul Nordic\n" +"microcontrollore nRF51822 con alcuni LED e pulsanti, un accelerometro e una bussola collegati a I2C e\n" +"un debugger SWD integrato." + +#: src/bare-metal.md:20 +#, fuzzy +msgid "To get started, install some tools we'll need later. On gLinux or Debian:" +msgstr "Per iniziare, installa alcuni strumenti che ci serviranno in seguito. Su gLinux o Debian:" + +#: src/bare-metal.md:22 +msgid "" +"```bash\n" +"sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom pkg-config qemu-system-arm\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" +msgstr "" + +#: src/bare-metal.md:30 +#, fuzzy +msgid "And give users in the `plugdev` group access to the micro:bit programmer:" +msgstr "E dai agli utenti del gruppo `plugdev` l'accesso al programmatore micro:bit:" + +#: src/bare-metal.md:32 +msgid "" +"```bash\n" +"echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", GROUP=\"plugdev\"' |\\\n" +" sudo tee /etc/udev/rules.d/50-microbit.rules\n" +"sudo udevadm control --reload-rules\n" +"```" +msgstr "" + +#: src/bare-metal.md:38 +#, fuzzy +msgid "On MacOS:" +msgstr "Su macOS:" + +#: src/bare-metal.md:40 +msgid "" +"```bash\n" +"xcode-select --install\n" +"brew install gdb picocom qemu\n" +"brew install --cask gcc-aarch64-embedded\n" +"rustup update\n" +"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +"rustup component add llvm-tools-preview\n" +"cargo install cargo-binutils cargo-embed\n" +"```" +msgstr "" + +#: src/bare-metal/no_std.md:1 +#, fuzzy +msgid "# `no_std`" +msgstr "# `no_std`" + +#: src/bare-metal/no_std.md:3 +#, fuzzy +msgid "" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"
" +msgstr "" +"\n" +"
" + +#: src/bare-metal/no_std.md:7 +#, fuzzy +msgid "`core`" +msgstr "`nucleo`" + +#: src/bare-metal/no_std.md:9 src/bare-metal/no_std.md:14 +#, fuzzy +msgid "" +"" +msgstr "" +"" + +#: src/bare-metal/no_std.md:12 +#, fuzzy +msgid "`alloc`" +msgstr "`alloc`" + +#: src/bare-metal/no_std.md:17 +#, fuzzy +msgid "`std`" +msgstr "`std`" + +#: src/bare-metal/no_std.md:19 +#, fuzzy +msgid "" +"
" +msgstr "" +"\n" +"
" + +#: src/bare-metal/no_std.md:24 +#, fuzzy +msgid "" +"* Slices, `&str`, `CStr`\n" +"* `NonZeroU8`...\n" +"* `Option`, `Result`\n" +"* `Display`, `Debug`, `write!`...\n" +"* `Iterator`\n" +"* `panic!`, `assert_eq!`...\n" +"* `NonNull` and all the usual pointer-related functions\n" +"* `Future` and `async`/`await`\n" +"* `fence`, `AtomicBool`, `AtomicPtr`, `AtomicU32`...\n" +"* `Duration`" +msgstr "" +"* Fette, `&str`, `CStr`\n" +"* `NonZeroU8`...\n" +"* `Opzione`, `Risultato`\n" +"* `Display`, `Debug`, `write!`...\n" +"* `Iteratore`\n" +"* `panico!`, `assert_eq!`...\n" +"* `NonNull` e tutte le solite funzioni relative ai puntatori\n" +"* `Future` e `async`/`await`\n" +"* `fence`, `AtomicBool`, `AtomicPtr`, `AtomicU32`...\n" +"* `Durata`" + +#: src/bare-metal/no_std.md:35 src/bare-metal/no_std.md:42 +#, fuzzy +msgid "" +"" +msgstr "" +"" + +#: src/bare-metal/no_std.md:38 +#, fuzzy +msgid "" +"* `Box`, `Cow`, `Arc`, `Rc`\n" +"* `Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque`\n" +"* `String`, `CString`, `format!`" +msgstr "" +"* `Scatola`, `Mucca`, `Arco`, `Rc`\n" +"* `Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque`\n" +"* `Stringa`, `CStringa`, `formato!`" + +#: src/bare-metal/no_std.md:45 +#, fuzzy +msgid "" +"* `Error`\n" +"* `HashMap`\n" +"* `Mutex`, `Condvar`, `Barrier`, `Once`, `RwLock`, `mpsc`\n" +"* `File` and the rest of `fs`\n" +"* `println!`, `Read`, `Write`, `Stdin`, `Stdout` and the rest of `io`\n" +"* `Path`, `OsString`\n" +"* `net`\n" +"* `Command`, `Child`, `ExitCode`\n" +"* `spawn`, `sleep` and the rest of `thread`\n" +"* `SystemTime`, `Instant`" +msgstr "" +"* `Errore`\n" +"* `Mappa hash`\n" +"* `Mutex`, `Condvar`, `Barrier`, `Once`, `RwLock`, `mpsc`\n" +"* `File` e il resto di `fs`\n" +"* `println!`, `Read`, `Write`, `Stdin`, `Stdout` e il resto di `io`\n" +"* `Percorso`, `OsString`\n" +"* `rete`\n" +"* `Comando`, `Figlio`, `CodiceUscita`\n" +"* `spawn`, `sleep` e il resto di `thread`\n" +"* `SystemTime`, `Instant`" + +#: src/bare-metal/no_std.md:56 +#, fuzzy +msgid "" +"
\n" +"\n" +"
" +msgstr "" +"\n" +"\n" +"\n" +"\n" +"" + +#: src/bare-metal/no_std.md:62 +#, fuzzy +msgid "" +"* `HashMap` depends on RNG.\n" +"* `std` re-exports the contents of both `core` and `alloc`." +msgstr "" +"* `HashMap` dipende da RNG.\n" +"* `std` riesporta il contenuto sia di `core` che di `alloc`." + +#: src/bare-metal/minimal.md:1 +#, fuzzy +msgid "# A minimal `no_std` program" +msgstr "# Un programma `no_std` minimo" + +#: src/bare-metal/minimal.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::panic::PanicInfo;\n" +"\n" +"#[panic_handler]\n" +"fn panic(_panic: &PanicInfo) -> ! {\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/minimal.md:17 +msgid "" +"* This will compile to an empty binary.\n" +"* `std` provides a panic handler; without it we must provide our own.\n" +"* It can also be provided by another crate, such as `panic-halt`.\n" +"* Depending on the target, you may need to compile with `panic = \"abort\"` to avoid an error about\n" +" `eh_personality`.\n" +"* Note that there is no `main` or any other entry point; it's up to you to define your own entry\n" +" point. This will typically involve a linker script and some assembly code to set things up ready\n" +" for Rust code to run." +msgstr "" + +#: src/bare-metal/alloc.md:1 +#, fuzzy +msgid "# `alloc`" +msgstr "# `alloc`" + +#: src/bare-metal/alloc.md:3 +#, fuzzy +msgid "" +"To use `alloc` you must implement a\n" +"[global (heap) allocator](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html)." +msgstr "" +"Per usare `alloc` devi implementare a\n" +"[allocatore globale (heap)](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html)." + +#: src/bare-metal/alloc.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate alloc;\n" +"extern crate panic_halt as _;\n" +"\n" +"use alloc::string::ToString;\n" +"use alloc::vec::Vec;\n" +"use buddy_system_allocator::LockedHeap;\n" +"\n" +"#[global_allocator]\n" +"static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();\n" +"\n" +"static mut HEAP: [u8; 65536] = [0; 65536];\n" +"\n" +"pub fn entry() {\n" +" // Safe because `HEAP` is only used here and `entry` is only called once.\n" +" unsafe {\n" +" // Give the allocator some memory to allocate.\n" +" HEAP_ALLOCATOR\n" +" .lock()\n" +" .init(HEAP.as_mut_ptr() as usize, HEAP.len());\n" +" }\n" +"\n" +" // Now we can do things that require heap allocation.\n" +" let mut v = Vec::new();\n" +" v.push(\"A string\".to_string());\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/alloc.md:39 +msgid "" +"* `buddy_system_allocator` is a third-party crate implementing a basic buddy system allocator. Other\n" +" crates are available, or you can write your own or hook into your existing allocator.\n" +"* The const parameter of `LockedHeap` is the max order of the allocator; i.e. in this case it can\n" +" allocate regions of up to 2**32 bytes.\n" +"* If any crate in your dependency tree depends on `alloc` then you must have exactly one global\n" +" allocator defined in your binary. Usually this is done in the top-level binary crate.\n" +"* `extern crate panic_halt as _` is necessary to ensure that the `panic_halt` crate is linked in so\n" +" we get its panic handler.\n" +"* This example will build but not run, as it doesn't have an entry point." +msgstr "" + +#: src/bare-metal/microcontrollers.md:1 +#, fuzzy +msgid "# Microcontrollers" +msgstr "# Microcontrollori" + +#: src/bare-metal/microcontrollers.md:3 +#, fuzzy +msgid "The `cortex_m_rt` crate provides (among other things) a reset handler for Cortex M microcontrollers." +msgstr "Il crate `cortex_m_rt` fornisce (tra le altre cose) un gestore di reset per i microcontrollori Cortex M." + +#: src/bare-metal/microcontrollers.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use cortex_m_rt::entry;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers.md:21 +#, fuzzy +msgid "Next we'll look at how to access peripherals, with increasing levels of abstraction." +msgstr "Successivamente vedremo come accedere alle periferiche, con livelli crescenti di astrazione." + +#: src/bare-metal/microcontrollers.md:25 +#, fuzzy +msgid "" +"* The `cortex_m_rt::entry` macro requires that the function have type `fn() -> !`, because returning\n" +" to the reset handler doesn't make sense.\n" +"* Run the example with `cargo embed --bin minimal`" +msgstr "" +"* La macro `cortex_m_rt::entry` richiede che la funzione abbia il tipo `fn() -> !`, perché restituisce\n" +" al gestore di ripristino non ha senso.\n" +"* Esegui l'esempio con `cargo embed --bin minimal`" + +#: src/bare-metal/microcontrollers/mmio.md:1 +#, fuzzy +msgid "# Raw MMIO" +msgstr "# MMIO grezzo" + +#: src/bare-metal/microcontrollers/mmio.md:3 +#, fuzzy +msgid "" +"Most microcontrollers access peripherals via memory-mapped IO. Let's try turning on an LED on our\n" +"micro:bit:" +msgstr "" +"La maggior parte dei microcontrollori accede alle periferiche tramite IO mappato in memoria. Proviamo ad accendere un LED sul nostro\n" +"micro:bit:" + +#: src/bare-metal/microcontrollers/mmio.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"mod interrupts;\n" +"\n" +"use core::mem::size_of;\n" +"use cortex_m_rt::entry;\n" +"\n" +"/// GPIO port 0 peripheral address\n" +"const GPIO_P0: usize = 0x5000_0000;\n" +"\n" +"// GPIO peripheral offsets\n" +"const PIN_CNF: usize = 0x700;\n" +"const OUTSET: usize = 0x508;\n" +"const OUTCLR: usize = 0x50c;\n" +"\n" +"// PIN_CNF fields\n" +"const DIR_OUTPUT: u32 = 0x1;\n" +"const INPUT_DISCONNECT: u32 = 0x1 << 1;\n" +"const PULL_DISABLED: u32 = 0x0 << 2;\n" +"const DRIVE_S0S1: u32 = 0x0 << 8;\n" +"const SENSE_DISABLED: u32 = 0x0 << 16;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let pin_cnf_21 = (GPIO_P0 + PIN_CNF + 21 * size_of::()) as *mut u32;\n" +" let pin_cnf_28 = (GPIO_P0 + PIN_CNF + 28 * size_of::()) as *mut u32;\n" +" // Safe because the pointers are to valid peripheral control registers, and\n" +" // no aliases exist.\n" +" unsafe {\n" +" pin_cnf_21.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED,\n" +" );\n" +" pin_cnf_28.write_volatile(\n" +" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED,\n" +" );\n" +" }\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" let gpio0_outset = (GPIO_P0 + OUTSET) as *mut u32;\n" +" let gpio0_outclr = (GPIO_P0 + OUTCLR) as *mut u32;\n" +" // Safe because the pointers are to valid peripheral control registers, and\n" +" // no aliases exist.\n" +" unsafe {\n" +" gpio0_outclr.write_volatile(1 << 28);\n" +" gpio0_outset.write_volatile(1 << 21);\n" +" }\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:64 +#, fuzzy +msgid "* GPIO 0 pin 21 is connected to the first column of the LED matrix, and pin 28 to the first row." +msgstr "* Il pin 21 di GPIO 0 è collegato alla prima colonna della matrice LED e il pin 28 alla prima riga." + +#: src/bare-metal/microcontrollers/mmio.md:66 src/bare-metal/microcontrollers/pacs.md:59 src/bare-metal/microcontrollers/hals.md:43 +#: src/bare-metal/microcontrollers/board-support.md:34 +#, fuzzy +msgid "Run the example with:" +msgstr "Esegui l'esempio con:" + +#: src/bare-metal/microcontrollers/mmio.md:68 +msgid "" +"```sh\n" +"cargo embed --bin mmio\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:1 +#, fuzzy +msgid "# Peripheral Access Crates" +msgstr "# Casse di accesso periferico" + +#: src/bare-metal/microcontrollers/pacs.md:3 +#, fuzzy +msgid "" +"[`svd2rust`](https://crates.io/crates/svd2rust) generates mostly-safe Rust wrappers for\n" +"memory-mapped peripherals from [CMSIS-SVD](https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html)\n" +"files." +msgstr "" +"[`svd2rust`](https://crates.io/crates/svd2rust) genera wrapper Rust per lo più sicuri per\n" +"periferiche mappate in memoria da [CMSIS-SVD](https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html)\n" +"File." + +#: src/bare-metal/microcontrollers/pacs.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_pac::Peripherals;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p.P0;\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" gpio0.pin_cnf[21].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +" gpio0.pin_cnf[28].write(|w| {\n" +" w.dir().output();\n" +" w.input().disconnect();\n" +" w.pull().disabled();\n" +" w.drive().s0s1();\n" +" w.sense().disabled();\n" +" w\n" +" });\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" gpio0.outclr.write(|w| w.pin28().clear());\n" +" gpio0.outset.write(|w| w.pin21().set());\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/pacs.md:49 +#, fuzzy +msgid "" +"* SVD (System View Description) files are XML files typically provided by silicon vendors which\n" +" describe the memory map of the device.\n" +" * They are organised by peripheral, register, field and value, with names, descriptions, addresses\n" +" and so on.\n" +" * SVD files are often buggy and incomplete, so there are various projects which patch the\n" +" mistakes, add missing details, and publish the generated crates.\n" +"* `cortex-m-rt` provides the vector table, among other things.\n" +"* If you `cargo install cargo-binutils` then you can run\n" +" `cargo objdump --bin pac -- -d --no-show-raw-insn` to see the resulting binary." +msgstr "" +"* I file SVD (System View Description) sono file XML generalmente forniti da fornitori di silicio che\n" +" descrivere la mappa di memoria del dispositivo.\n" +" * Sono organizzati per periferica, registro, campo e valore, con nomi, descrizioni, indirizzi\n" +" e così via.\n" +" * I file SVD sono spesso difettosi e incompleti, quindi ci sono vari progetti che correggono il file\n" +" errori, aggiungere i dettagli mancanti e pubblicare le casse generate.\n" +"* `cortex-m-rt` fornisce la tabella dei vettori, tra le altre cose.\n" +"* Se `cargo installi cargo-binutils` allora puoi eseguire\n" +" `cargo objdump --bin pac -- -d --no-show-raw-insn` per vedere il binario risultante." + +#: src/bare-metal/microcontrollers/pacs.md:61 +msgid "" +"```sh\n" +"cargo embed --bin pac\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:1 +#, fuzzy +msgid "# HAL crates" +msgstr "# casse HAL" + +#: src/bare-metal/microcontrollers/hals.md:3 +#, fuzzy +msgid "" +"[HAL crates](https://github.com/rust-embedded/awesome-embedded-rust#hal-implementation-crates) for\n" +"many microcontrollers provide wrappers around various peripherals. These generally implement traits\n" +"from [`embedded-hal`](https://crates.io/crates/embedded-hal)." +msgstr "" +"[Casse HAL](https://github.com/rust-embedded/awesome-embedded-rust#hal-implementation-crates) per\n" +"molti microcontrollori forniscono wrapper attorno a varie periferiche. Questi generalmente implementano i tratti\n" +"da [`embedded-hal`](https://crates.io/crates/embedded-hal)." + +#: src/bare-metal/microcontrollers/hals.md:7 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use nrf52833_hal::gpio::{p0, Level};\n" +"use nrf52833_hal::pac::Peripherals;\n" +"use nrf52833_hal::prelude::*;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +"\n" +" // Create HAL wrapper for GPIO port 0.\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +" let mut col1 = gpio0.p0_28.into_push_pull_output(Level::High);\n" +" let mut row1 = gpio0.p0_21.into_push_pull_output(Level::Low);\n" +"\n" +" // Set pin 28 low and pin 21 high to turn the LED on.\n" +" col1.set_low().unwrap();\n" +" row1.set_high().unwrap();\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/hals.md:39 +#, fuzzy +msgid "" +" * `set_low` and `set_high` are methods on the `embedded_hal` `OutputPin` trait.\n" +" * HAL crates exist for many Cortex-M and RISC-V devices, including various STM32, GD32, nRF, NXP,\n" +" MSP430, AVR and PIC microcontrollers." +msgstr "" +" * `set_low` e `set_high` sono metodi sul tratto `embedded_hal` `OutputPin`.\n" +" * Esistono casse HAL per molti dispositivi Cortex-M e RISC-V, inclusi vari STM32, GD32, nRF, NXP,\n" +" Microcontrollori MSP430, AVR e PIC." + +#: src/bare-metal/microcontrollers/hals.md:45 +msgid "" +"```sh\n" +"cargo embed --bin hal\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:1 +#, fuzzy +msgid "# Board support crates" +msgstr "# Casse di supporto della scheda" + +#: src/bare-metal/microcontrollers/board-support.md:3 +#, fuzzy +msgid "Board support crates provide a further level of wrapping for a specific board for convenience." +msgstr "Le casse di supporto della tavola forniscono un ulteriore livello di avvolgimento per una tavola specifica per comodità." + +#: src/bare-metal/microcontrollers/board-support.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use cortex_m_rt::entry;\n" +"use microbit::hal::prelude::*;\n" +"use microbit::Board;\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let mut board = Board::take().unwrap();\n" +"\n" +" board.display_pins.col1.set_low().unwrap();\n" +" board.display_pins.row1.set_high().unwrap();\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/board-support.md:28 +#, fuzzy +msgid "" +" * In this case the board support crate is just providing more useful names, and a bit of\n" +" initialisation.\n" +" * The crate may also include drivers for some on-board devices outside of the microcontroller\n" +" itself.\n" +" * `microbit-v2` includes a simple driver for the LED matrix." +msgstr "" +" * In questo caso la cassa di supporto della scheda fornisce solo nomi più utili e un po' di\n" +" inizializzazione.\n" +" * Il crate può anche includere driver per alcuni dispositivi integrati al di fuori del microcontrollore\n" +" si.\n" +" * `microbit-v2` include un semplice driver per la matrice LED." + +#: src/bare-metal/microcontrollers/board-support.md:36 +msgid "" +"```sh\n" +"cargo embed --bin board_support\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:1 +#, fuzzy +msgid "# The type state pattern" +msgstr "# Il modello di stato del tipo" + +#: src/bare-metal/microcontrollers/type-state.md:3 +msgid "" +"```rust,editable,compile_fail\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let p = Peripherals::take().unwrap();\n" +" let gpio0 = p0::Parts::new(p.P0);\n" +"\n" +" let pin: P0_01 = gpio0.p0_01;\n" +"\n" +" // let gpio0_01_again = gpio0.p0_01; // Error, moved.\n" +" let pin_input: P0_01> = pin.into_floating_input();\n" +" if pin_input.is_high().unwrap() {\n" +" // ...\n" +" }\n" +" let mut pin_output: P0_01> = pin_input\n" +" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);\n" +" pin_output.set_high().unwrap();\n" +" // pin_input.is_high(); // Error, moved.\n" +"\n" +" let _pin2: P0_02> = gpio0\n" +" .p0_02\n" +" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);\n" +" let _pin3: P0_03> = gpio0.p0_03.into_push_pull_output(Level::Low);\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:32 +#, fuzzy +msgid "" +" * Pins don't implement `Copy` or `Clone`, so only one instance of each can exist. Once a pin is\n" +" moved out of the port struct nobody else can take it.\n" +" * Changing the configuration of a pin consumes the old pin instance, so you can’t keep use the old\n" +" instance afterwards.\n" +" * The type of a value indicates the state that it is in: e.g. in this case, the configuration state\n" +" of a GPIO pin. This encodes the state machine into the type system, and ensures that you don't\n" +" try to use a pin in a certain way without properly configuring it first. Illegal state\n" +" transitions are caught at compile time.\n" +" * You can call `is_high` on an input pin and `set_high` on an output pin, but not vice-versa.\n" +" * Many HAL crates follow this pattern." +msgstr "" +" * I pin non implementano `Copy` o `Clone`, quindi può esistere solo un'istanza di ciascuno. Una volta che uno spillo è\n" +" spostato fuori dalla struttura portuale nessun altro può prenderlo.\n" +" * La modifica della configurazione di un pin consuma la vecchia istanza del pin, quindi non puoi continuare a utilizzare il vecchio\n" +" esempio dopo.\n" +" * Il tipo di un valore indica lo stato in cui si trova: ad es. in questo caso, lo stato di configurazione\n" +" di un pin GPIO. Questo codifica la macchina a stati nel sistema di tipi e garantisce che non lo fai\n" +" provare a utilizzare un pin in un certo modo senza prima configurarlo correttamente. Stato illegale\n" +" le transizioni vengono rilevate in fase di compilazione.\n" +" * Puoi chiamare `is_high` su un pin di input e `set_high` su un pin di output, ma non viceversa.\n" +" * Molte casse HAL seguono questo schema." + +#: src/bare-metal/microcontrollers/embedded-hal.md:1 +#, fuzzy +msgid "# `embedded-hal`" +msgstr "# `hal incorporato`" + +#: src/bare-metal/microcontrollers/embedded-hal.md:3 +#, fuzzy +msgid "" +"The [`embedded-hal`](https://crates.io/crates/embedded-hal) crate provides a number of traits\n" +"covering common microcontroller peripherals." +msgstr "" +"Il crate [`embedded-hal`](https://crates.io/crates/embedded-hal) fornisce una serie di caratteristiche\n" +"che copre le comuni periferiche del microcontrollore." + +#: src/bare-metal/microcontrollers/embedded-hal.md:6 +#, fuzzy +msgid "" +" * GPIO\n" +" * ADC\n" +" * I2C, SPI, UART, CAN\n" +" * RNG\n" +" * Timers\n" +" * Watchdogs" +msgstr "" +" * GPIO\n" +" *ADC\n" +" * I2C, SPI, UART, PUÒ\n" +" * RNG\n" +" * Timer\n" +" * Cani da guardia" + +#: src/bare-metal/microcontrollers/embedded-hal.md:13 +#, fuzzy +msgid "" +"Other crates then implement\n" +"[drivers](https://github.com/rust-embedded/awesome-embedded-rust#driver-crates) in terms of these\n" +"traits, e.g. an accelerometer driver might need an I2C or SPI bus implementation." +msgstr "" +"Altre casse quindi implementano\n" +"[driver](https://github.com/rust-embedded/awesome-embedded-rust#driver-crates) in termini di questi\n" +"tratti, ad es. un driver dell'accelerometro potrebbe richiedere un'implementazione del bus I2C o SPI." + +#: src/bare-metal/microcontrollers/embedded-hal.md:19 +#, fuzzy +msgid "" +" * There are implementations for many microcontrollers, as well as other platforms such as Linux on\n" +"Raspberry Pi.\n" +" * There is work in progress on an `async` version of `embedded-hal`, but it isn't stable yet." +msgstr "" +" * Ci sono implementazioni per molti microcontrollori, così come altre piattaforme come Linux su\n" +"Lampone Pi.\n" +" * C'è lavoro in corso su una versione `async` di `embedded-hal`, ma non è ancora stabile." + +#: src/bare-metal/microcontrollers/probe-rs.md:1 +#, fuzzy +msgid "# `probe-rs`, `cargo-embed`" +msgstr "# `probe-rs`, `cargo-embed`" + +#: src/bare-metal/microcontrollers/probe-rs.md:3 +#, fuzzy +msgid "" +"[probe-rs](https://probe.rs/) is a handy toolset for embedded debugging, like OpenOCD but better\n" +"integrated." +msgstr "" +"[probe-rs](https://probe.rs/) è un utile set di strumenti per il debug integrato, come OpenOCD ma migliore\n" +"integrato." + +#: src/bare-metal/microcontrollers/probe-rs.md:6 +#, fuzzy +msgid "" +"* SWD and JTAG via CMSIS-DAP, ST-Link and J-Link probes\n" +"* GDB stub and Microsoft DAP server\n" +"* Cargo integration" +msgstr "" +"* SWD e JTAG tramite sonde CMSIS-DAP, ST-Link e J-Link\n" +"* GDB stub e server Microsoft DAP\n" +"* Integrazione del carico" + +#: src/bare-metal/microcontrollers/probe-rs.md:10 +#, fuzzy +msgid "" +"`cargo-embed` is a cargo subcommand to build and flash binaries, log\n" +"RTT output and connect GDB. It's configured by an\n" +"`Embed.toml` file in your project directory." +msgstr "" +"`cargo-embed` è un sottocomando cargo per compilare e aggiornare binari, log\n" +"RTT emette e collega GDB. È configurato da un\n" +"\"Embed.toml\" nella directory del progetto." + +#: src/bare-metal/microcontrollers/probe-rs.md:16 +#, fuzzy +msgid "" +"* [CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) is an Arm standard\n" +" protocol over USB for an in-circuit debugger to access the CoreSight Debug Access Port of various\n" +" Arm Cortex processors. It's what the on-board debugger on the BBC micro:bit uses.\n" +"* ST-Link is a range of in-circuit debuggers from ST Microelectronics, J-Link is a range from\n" +" SEGGER.\n" +"* The Debug Access Port is usually either a 5-pin JTAG interface or 2-pin Serial Wire Debug.\n" +"* probe-rs is a library which you can integrate into your own tools if you want to.\n" +"* The [Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/) lets\n" +" VSCode and other IDEs debug code running on any supported microcontroller.\n" +"* cargo-embed is a binary built using the probe-rs library.\n" +"* RTT (Real Time Transfers) is a mechanism to transfer data between the debug host and the target\n" +" through a number of ringbuffers." +msgstr "" +"* [CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) è uno standard Arm\n" +" protocollo su USB per un debugger in-circuit per accedere alla porta di accesso di debug CoreSight di vari\n" +" Processori Arm Cortex. È ciò che utilizza il debugger integrato sul micro: bit della BBC.\n" +"* ST-Link è una gamma di debugger in-circuit di ST Microelectronics, J-Link è una gamma di\n" +" SEGGER.\n" +"* La porta di accesso al debug è in genere un'interfaccia JTAG a 5 pin o un cavo di debug seriale a 2 pin.\n" +"* probe-rs è una libreria che puoi integrare nei tuoi strumenti se lo desideri.\n" +"* Il [Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/) consente\n" +" VSCode e altri IDE eseguono il debug del codice in esecuzione su qualsiasi microcontrollore supportato.\n" +"* cargo-embed è un binario creato utilizzando la libreria probe-rs.\n" +"* RTT (Real Time Transfers) è un meccanismo per trasferire i dati tra l'host di debug e il target\n" +" attraverso una serie di ringbuffer." + +#: src/bare-metal/microcontrollers/debugging.md:1 +#, fuzzy +msgid "# Debugging" +msgstr "# Debug" + +#: src/bare-metal/microcontrollers/debugging.md:3 +#, fuzzy +msgid "Embed.toml:" +msgstr "Incorpora.toml:" + +#: src/bare-metal/microcontrollers/debugging.md:5 +msgid "" +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:13 +#, fuzzy +msgid "In one terminal under `src/bare-metal/microcontrollers/examples/`:" +msgstr "In un terminale sotto `src/bare-metal/microcontrollers/examples/`:" + +#: src/bare-metal/microcontrollers/debugging.md:15 +msgid "" +"```sh\n" +"cargo embed --bin board_support debug\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:19 +#, fuzzy +msgid "In another terminal in the same directory:" +msgstr "In un altro terminale nella stessa directory:" + +#: src/bare-metal/microcontrollers/debugging.md:21 +msgid "" +"```sh\n" +"gdb-multiarch target/thumbv7em-none-eabihf/debug/board_support --eval-command=\"target remote :1337\"\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/debugging.md:27 +#, fuzzy +msgid "In GDB, try running:" +msgstr "In GDB, prova a eseguire:" + +#: src/bare-metal/microcontrollers/debugging.md:29 +msgid "" +"```gdb\n" +"b src/bin/board_support.rs:29\n" +"b src/bin/board_support.rs:30\n" +"b src/bin/board_support.rs:32\n" +"c\n" +"c\n" +"c\n" +"```" +msgstr "" + +#: src/bare-metal/microcontrollers/other-projects.md:1 src/bare-metal/aps/other-projects.md:1 +#, fuzzy +msgid "# Other projects" +msgstr "# Altri progetti" + +#: src/bare-metal/microcontrollers/other-projects.md:3 +#, fuzzy +msgid "" +" * [RTIC](https://rtic.rs/)\n" +" * \"Real-Time Interrupt-driven Concurrency\"\n" +" * Shared resource management, message passing, task scheduling, timer queue\n" +" * [Embassy](https://embassy.dev/)\n" +" * `async` executors with priorities, timers, networking, USB\n" +" * [TockOS](https://www.tockos.org/documentation/getting-started)\n" +" * Security-focused RTOS with preemptive scheduling and Memory Protection Unit support\n" +" * [Hubris](https://hubris.oxide.computer/)\n" +" * Microkernel RTOS from Oxide Computer Company with memory protection, unprivileged drivers, IPC\n" +" * [Bindings for FreeRTOS](https://github.com/lobaro/FreeRTOS-rust)\n" +" * Some platforms have `std` implementations, e.g.\n" +" [esp-idf](https://esp-rs.github.io/book/overview/using-the-standard-library.html)." +msgstr "" +" * [RTIC](https://rtic.rs/)\n" +" * \"Concorrenza basata su interrupt in tempo reale\"\n" +" * Gestione delle risorse condivise, passaggio di messaggi, pianificazione delle attività, coda del timer\n" +" * [Ambasciata](https://embassy.dev/)\n" +" * Esecutori `async` con priorità, timer, networking, USB\n" +" * [TockOS](https://www.tockos.org/documentation/getting-started)\n" +" * RTOS incentrato sulla sicurezza con pianificazione preventiva e supporto dell'unità di protezione della memoria\n" +" * [Hubris](https://hubris.oxide.computer/)\n" +" * Microkernel RTOS di Oxide Computer Company con protezione della memoria, driver non privilegiati, IPC\n" +" * [Binding per FreeRTOS](https://github.com/lobaro/FreeRTOS-rust)\n" +" * Alcune piattaforme hanno implementazioni `std`, ad es.\n" +" [esp-idf](https://esp-rs.github.io/book/overview/using-the-standard-library.html)." + +#: src/bare-metal/microcontrollers/other-projects.md:18 +#, fuzzy +msgid "" +" * RTIC can be considered either an RTOS or a concurrency framework.\n" +" * It doesn't include any HALs.\n" +" * It uses the Cortex-M NVIC (Nested Virtual Interrupt Controller) for scheduling rather than a\n" +" proper kernel.\n" +" * Cortex-M only.\n" +" * Google uses TockOS on the Haven microcontroller for Titan security keys.\n" +" * FreeRTOS is mostly written in C, but there are Rust bindings for writing applications." +msgstr "" +" * RTIC può essere considerato un RTOS o un framework di concorrenza.\n" +" * Non include nessun HAL.\n" +" * Utilizza Cortex-M NVIC (Nested Virtual Interrupt Controller) per la pianificazione piuttosto che un\n" +" kernel corretto.\n" +" * Solo Cortex-M.\n" +" * Google utilizza TockOS sul microcontrollore Haven per le chiavi di sicurezza Titan.\n" +" * FreeRTOS è principalmente scritto in C, ma ci sono collegamenti Rust per la scrittura di applicazioni." + +#: src/exercises/bare-metal/morning.md:3 +#, fuzzy +msgid "We will read the direction from an I2C compass, and log the readings to a serial port." +msgstr "Leggeremo la direzione da una bussola I2C e registreremo le letture su una porta seriale." + +#: src/exercises/bare-metal/compass.md:1 +#, fuzzy +msgid "# Compass" +msgstr "# Bussola" + +#: src/exercises/bare-metal/compass.md:3 +#, fuzzy +msgid "" +"We will read the direction from an I2C compass, and log the readings to a serial port. If you have\n" +"time, try displaying it on the LEDs somehow too, or use the buttons somehow." +msgstr "" +"Leggeremo la direzione da una bussola I2C e registreremo le letture su una porta seriale. Se hai\n" +"tempo, prova a visualizzarlo in qualche modo anche sui LED o usa i pulsanti in qualche modo." + +#: src/exercises/bare-metal/compass.md:6 +#, fuzzy +msgid "Hints:" +msgstr "Suggerimenti:" + +#: src/exercises/bare-metal/compass.md:8 +#, fuzzy +msgid "" +"- Check the documentation for the [`lsm303agr`](https://docs.rs/lsm303agr/latest/lsm303agr/) and\n" +" [`microbit-v2`](https://docs.rs/microbit-v2/latest/microbit/) crates, as well as the\n" +" [micro:bit hardware](https://tech.microbit.org/hardware/).\n" +"- The LSM303AGR Inertial Measurement Unit is connected to the internal I2C bus.\n" +"- TWI is another name for I2C, so the I2C master peripheral is called TWIM.\n" +"- The LSM303AGR driver needs something implementing the `embedded_hal::blocking::i2c::WriteRead`\n" +" trait. The\n" +" [`microbit::hal::Twim`](https://docs.rs/microbit-v2/latest/microbit/hal/struct.Twim.html) struct\n" +" implements this.\n" +"- You have a [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/struct.Board.html)\n" +" struct with fields for the various pins and peripherals.\n" +"- You can also look at the\n" +" [nRF52833 datasheet](https://infocenter.nordicsemi.com/pdf/nRF52833_PS_v1.5.pdf) if you want, but\n" +" it shouldn't be necessary for this exercise." +msgstr "" +"- Controlla la documentazione per [`lsm303agr`](https://docs.rs/lsm303agr/latest/lsm303agr/) e\n" +" [`microbit-v2`](https://docs.rs/microbit-v2/latest/microbit/) e le\n" +" [micro:bit hardware](https://tech.microbit.org/hardware/).\n" +"- L'unità di misura inerziale LSM303AGR è collegata al bus I2C interno.\n" +"- TWI è un altro nome per I2C, quindi la periferica master I2C si chiama TWIM.\n" +"- Il driver LSM303AGR necessita di qualcosa che implementi `embedded_hal::blocking::i2c::WriteRead`\n" +" tratto. IL\n" +" [`microbit::hal::Twim`](https://docs.rs/microbit-v2/latest/microbit/hal/struct.Twim.html) struttura\n" +" implementa questo.\n" +"- Hai un [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/struct.Board.html)\n" +" struct con campi per i vari pin e periferiche.\n" +"- Puoi anche guardare il\n" +" [scheda tecnica nRF52833](https://infocenter.nordicsemi.com/pdf/nRF52833_PS_v1.5.pdf) se vuoi, ma\n" +" non dovrebbe essere necessario per questo esercizio." + +#: src/exercises/bare-metal/compass.md:23 +#, fuzzy +msgid "" +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the `compass`\n" +"directory for the following files." +msgstr "" +"Scarica il [modello di esercizio](../../comprehensive-rust-exercises.zip) e guarda nella `bussola`\n" +"directory per i seguenti file." + +#: src/exercises/bare-metal/compass.md:26 src/exercises/bare-metal/rtc.md:19 src/exercises/concurrency/elevator.md:17 +#, fuzzy +msgid "`src/main.rs`:" +msgstr "`src/principale.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/elevator.md:19 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/compass.md:30 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"use microbit::{hal::uarte::{Baudrate, Parity, Uarte}, Board};\n" +"\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // TODO\n" +"\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // TODO\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:64 src/exercises/bare-metal/rtc.md:385 src/exercises/concurrency/elevator.md:365 +#, fuzzy +msgid "`Cargo.toml` (you shouldn't need to change this):" +msgstr "`Cargo.toml` (non dovrebbe essere necessario modificarlo):" + +#: 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/elevator.md:367 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/compass.md:68 +msgid "" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"compass\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"cortex-m-rt = \"0.7.3\"\n" +"embedded-hal = \"0.2.6\"\n" +"lsm303agr = \"0.2.2\"\n" +"microbit-v2 = \"0.13.0\"\n" +"panic-halt = \"0.2.0\"\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:85 +#, fuzzy +msgid "`Embed.toml` (you shouldn't need to change this):" +msgstr "`Embed.toml` (non dovrebbe essere necessario modificarlo):" + +#: src/exercises/bare-metal/compass.md:87 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/compass.md:89 +msgid "" +"```toml\n" +"[default.general]\n" +"chip = \"nrf52833_xxAA\"\n" +"\n" +"[debug.gdb]\n" +"enabled = true\n" +"\n" +"[debug.reset]\n" +"halt_afterwards = true\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:100 src/exercises/bare-metal/rtc.md:985 +#, fuzzy +msgid "`.cargo/config.toml` (you shouldn't need to change this):" +msgstr "`.cargo/config.toml` (non dovresti aver bisogno di cambiarlo):" + +#: src/exercises/bare-metal/compass.md:102 src/exercises/bare-metal/rtc.md:987 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/compass.md:104 +msgid "" +"```toml\n" +"[build]\n" +"target = \"thumbv7em-none-eabihf\" # Cortex-M4F\n" +"\n" +"[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))']\n" +"rustflags = [\"-C\", \"link-arg=-Tlink.x\"]\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:112 +#, fuzzy +msgid "See the serial output on Linux with:" +msgstr "Guarda l'output seriale su Linux con:" + +#: src/exercises/bare-metal/compass.md:114 +msgid "" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/ttyACM0\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:118 +#, fuzzy +msgid "Or on Mac OS something like (the device name may be slightly different):" +msgstr "O su Mac OS qualcosa di simile (il nome del dispositivo potrebbe essere leggermente diverso):" + +#: src/exercises/bare-metal/compass.md:120 +msgid "" +"```sh\n" +"picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/compass.md:124 +#, fuzzy +msgid "Use Ctrl+A Ctrl+Q to quit picocom." +msgstr "Usa Ctrl+A Ctrl+Q per uscire da picocom." + +#: src/bare-metal/aps.md:1 +#, fuzzy +msgid "# Application processors" +msgstr "# Processori di applicazioni" + +#: src/bare-metal/aps.md:3 +#, fuzzy +msgid "" +"So far we've talked about microcontrollers, such as the Arm Cortex-M series. Now let's try writing\n" +"something for Cortex-A. For simplicity we'll just work with QEMU's aarch64\n" +"['virt'](https://qemu-project.gitlab.io/qemu/system/arm/virt.html) board." +msgstr "" +"Finora abbiamo parlato di microcontrollori, come la serie Arm Cortex-M. Ora proviamo a scrivere\n" +"qualcosa per Cortex-A. Per semplicità lavoreremo solo con aarch64 di QEMU\n" +"['virt'](https://qemu-project.gitlab.io/qemu/system/arm/virt.html) scheda." + +#: src/bare-metal/aps.md:9 +#, fuzzy +msgid "" +"* Broadly speaking, microcontrollers don't have an MMU or multiple levels of privilege (exception\n" +" levels on Arm CPUs, rings on x86), while application processors do.\n" +"* QEMU supports emulating various different machines or board models for each architecture. The\n" +" 'virt' board doesn't correspond to any particular real hardware, but is designed purely for\n" +" virtual machines." +msgstr "" +"* In generale, i microcontrollori non hanno una MMU o più livelli di privilegio (eccezione\n" +" livelli su CPU Arm, anelli su x86), mentre i processori delle applicazioni lo fanno.\n" +"* QEMU supporta l'emulazione di diverse macchine o modelli di scheda per ciascuna architettura. IL\n" +" La scheda 'virt' non corrisponde a nessun particolare hardware reale, ma è progettata esclusivamente per\n" +" macchine virtuali." + +#: src/bare-metal/aps/inline-assembly.md:1 +#, fuzzy +msgid "# Inline assembly" +msgstr "# Assemblaggio in linea" + +#: src/bare-metal/aps/inline-assembly.md:3 +#, fuzzy +msgid "" +"Sometimes we need to use assembly to do things that aren't possible with Rust code. For example,\n" +"to make an HVC to tell the firmware to power off the system:" +msgstr "" +"A volte abbiamo bisogno di usare l'assembly per fare cose che non sono possibili con il codice Rust. Per esempio,\n" +"per effettuare un HVC per dire al firmware di spegnere il sistema:" + +#: src/bare-metal/aps/inline-assembly.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use core::arch::asm;\n" +"use core::panic::PanicInfo;\n" +"\n" +"mod exceptions;\n" +"\n" +"const PSCI_SYSTEM_OFF: u32 = 0x84000008;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) {\n" +" // Safe because this only uses the declared registers and doesn't do\n" +" // anything with memory.\n" +" unsafe {\n" +" asm!(\"hvc #0\",\n" +" inout(\"w0\") PSCI_SYSTEM_OFF => _,\n" +" inout(\"w1\") 0 => _,\n" +" inout(\"w2\") 0 => _,\n" +" inout(\"w3\") 0 => _,\n" +" inout(\"w4\") 0 => _,\n" +" inout(\"w5\") 0 => _,\n" +" inout(\"w6\") 0 => _,\n" +" inout(\"w7\") 0 => _,\n" +" options(nomem, nostack)\n" +" );\n" +" }\n" +"\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:39 +#, fuzzy +msgid "(If you actually want to do this, use the [`smccc`][1] crate which has wrappers for all these functions.)" +msgstr "(Se vuoi davvero farlo, usa la cassa [`smccc`][1] che ha wrapper per tutte queste funzioni.)" + +#: src/bare-metal/aps/inline-assembly.md:43 +#, fuzzy +msgid "" +"* PSCI is the Arm Power State Coordination Interface, a standard set of functions to manage system\n" +" and CPU power states, among other things. It is implemented by EL3 firmware and hypervisors on\n" +" many systems.\n" +"* The `0 => _` syntax means initialise the register to 0 before running the inline assembly code,\n" +" and ignore its contents afterwards. We need to use `inout` rather than `in` because the call could\n" +" potentially clobber the contents of the registers.\n" +"* This `main` function needs to be `#[no_mangle]` and `extern \"C\"` because it is called from our\n" +" entry point in `entry.S`.\n" +"* `_x0`–`_x3` are the values of registers `x0`–`x3`, which are conventionally used by the bootloader\n" +" to pass things like a pointer to the device tree. According to the standard aarch64 calling\n" +" convention (which is what `extern \"C\"` specifies to use), registers `x0`–`x7` are used for the\n" +" first 8 arguments passed to a function, so `entry.S` doesn't need to do anything special except\n" +" make sure it doesn't change these registers.\n" +"* Run the example in QEMU with `make qemu_psci` under `src/bare-metal/aps/examples`." +msgstr "" +"* PSCI è l'Arm Power State Coordination Interface, un insieme standard di funzioni per gestire il sistema\n" +" e gli stati di alimentazione della CPU, tra le altre cose. È implementato dal firmware EL3 e dagli hypervisor su\n" +" molti sistemi.\n" +"* La sintassi `0 => _` significa inizializzare il registro a 0 prima di eseguire il codice assembly inline,\n" +" e ignorarne il contenuto in seguito. Dobbiamo usare \"inout\" piuttosto che \"in\" perché la chiamata potrebbe\n" +" potenzialmente intasare il contenuto dei registri.\n" +"* Questa funzione `main` deve essere `#[no_mangle]` e `extern \"C\"` perché viene chiamata dal nostro\n" +" punto di ingresso in \"entry.S\".\n" +"* `_x0`–`_x3` sono i valori dei registri `x0`–`x3`, che sono convenzionalmente utilizzati dal bootloader\n" +" per passare cose come un puntatore all'albero dei dispositivi. Secondo la chiamata standard aarch64\n" +" convenzione (che è ciò che `extern \"C\"` specifica di usare), i registri `x0`–`x7` sono usati per\n" +" primi 8 argomenti passati a una funzione, quindi `entry.S` non ha bisogno di fare niente di speciale tranne\n" +" assicurati che non modifichi questi registri.\n" +"* Eseguire l'esempio in QEMU con `make qemu_psci` in `src/bare-metal/aps/examples`." + +#: src/bare-metal/aps/mmio.md:1 +#, fuzzy +msgid "# Volatile memory access for MMIO" +msgstr "# Accesso alla memoria volatile per MMIO" + +#: src/bare-metal/aps/mmio.md:3 +#, fuzzy +msgid "" +" * Use `pointer::read_volatile` and `pointer::write_volatile`.\n" +" * Never hold a reference.\n" +" * `addr_of!` lets you get fields of structs without creating an intermediate reference." +msgstr "" +" * Usa `pointer::read_volatile` e `pointer::write_volatile`.\n" +" * Non tenere mai un riferimento.\n" +" * `addr_of!` consente di ottenere campi di struct senza creare un riferimento intermedio." + +#: src/bare-metal/aps/mmio.md:9 +#, fuzzy +msgid "" +" * Volatile access: read or write operations may have side-effects, so prevent the compiler or\n" +" hardware from reordering, duplicating or eliding them.\n" +" * Usually if you write and then read, e.g. via a mutable reference, the compiler may assume that\n" +" the value read is the same as the value just written, and not bother actually reading memory.\n" +" * Some existing crates for volatile access to hardware do hold references, but this is unsound.\n" +" Whenever a reference exist, the compiler may choose to dereference it.\n" +" * Use the `addr_of!` macro to get struct field pointers from a pointer to the struct." +msgstr "" +" * Accesso volatile: le operazioni di lettura o scrittura possono avere effetti collaterali, quindi impedisci al compilatore o\n" +" hardware dal riordinarli, duplicarli o eliminarli.\n" +" * Di solito se scrivi e poi leggi, ad es. tramite un riferimento mutabile, il compilatore può assumerlo\n" +" il valore letto è uguale al valore appena scritto, e non disturba effettivamente la lettura della memoria.\n" +" * Alcuni crate esistenti per l'accesso volatile all'hardware contengono riferimenti, ma questo non è corretto.\n" +" Ogni volta che esiste un riferimento, il compilatore può scegliere di dereferenziarlo.\n" +" * Usa la macro `addr_of!` per ottenere i puntatori di campo struct da un puntatore alla struct." + +#: src/bare-metal/aps/uart.md:1 +#, fuzzy +msgid "# Let's write a UART driver" +msgstr "# Scriviamo un driver UART" + +#: src/bare-metal/aps/uart.md:3 +#, fuzzy +msgid "The QEMU 'virt' machine has a [PL011][1] UART, so let's write a driver for that." +msgstr "La macchina QEMU 'virt' ha un [PL011][1] UART, quindi scriviamo un driver per quello." + +#: src/bare-metal/aps/uart.md:5 +msgid "" +"```rust,editable\n" +"const FLAG_REGISTER_OFFSET: usize = 0x18;\n" +"const FR_BUSY: u8 = 1 << 3;\n" +"const FR_TXFF: u8 = 1 << 5;\n" +"\n" +"/// Minimal driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" base_address: *mut u8,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of a\n" +" /// PL011 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u8) -> Self {\n" +" Self { base_address }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register() & FR_TXFF != 0 {}\n" +"\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" self.base_address.write_volatile(byte);\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register() & FR_BUSY != 0 {}\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> u8 {\n" +" // Safe because we know that the base address points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { self.base_address.add(FLAG_REGISTER_OFFSET).read_volatile() }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/uart.md:55 +#, fuzzy +msgid "" +"* Note that `Uart::new` is unsafe while the other methods are safe. This is because as long as the\n" +" caller of `Uart::new` guarantees that its safety requirements are met (i.e. that there is only\n" +" ever one instance of the driver for a given UART, and nothing else aliasing its address space),\n" +" then it is always safe to call `write_byte` later because we can assume the necessary\n" +" preconditions.\n" +"* We could have done it the other way around (making `new` safe but `write_byte` unsafe), but that\n" +" would be much less convenient to use as every place that calls `write_byte` would need to reason\n" +" about the safety\n" +"* This is a common pattern for writing safe wrappers of unsafe code: moving the burden of proof for\n" +" soundness from a large number of places to a smaller number of places." +msgstr "" +"* Nota che `Uart::new` non è sicuro mentre gli altri metodi sono sicuri. Questo perché finché il\n" +" chiamante di `Uart::new` garantisce che i suoi requisiti di sicurezza siano soddisfatti (cioè che ci sia solo\n" +" mai un'istanza del driver per un dato UART, e nient'altro che alias il suo spazio degli indirizzi),\n" +" quindi è sempre sicuro chiamare `write_byte` in seguito perché possiamo assumere il necessario\n" +" precondizioni.\n" +"* Avremmo potuto fare il contrario (rendere `new` sicuro ma `write_byte` non sicuro), ma quello\n" +" sarebbe molto meno conveniente da usare poiché ogni posto che chiama `write_byte` dovrebbe ragionare\n" +" sulla sicurezza\n" +"* Questo è un modello comune per scrivere wrapper sicuri di codice non sicuro: spostare l'onere della prova per\n" +" solidità da un gran numero di posti a un numero minore di posti." + +#: src/bare-metal/aps/uart.md:66 +#, fuzzy +msgid "" +msgstr "" + +#: src/bare-metal/aps/uart/traits.md:1 +#, fuzzy +msgid "# More traits" +msgstr "# Altri tratti" + +#: src/bare-metal/aps/uart/traits.md:3 +#, fuzzy +msgid "We derived the `Debug` trait. It would be useful to implement a few more traits too." +msgstr "Abbiamo derivato il tratto `Debug`. Sarebbe utile implementare anche qualche altro tratto." + +#: src/bare-metal/aps/uart/traits.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use core::fmt::{self, Write};\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/uart/traits.md:24 +#, fuzzy +msgid "" +"* Implementing `Write` lets us use the `write!` and `writeln!` macros with our `Uart` type.\n" +"* Run the example in QEMU with `make qemu_minimal` under `src/bare-metal/aps/examples`." +msgstr "" +"* L'implementazione di `Write` ci permette di usare le macro `write!` e `writeln!` con il nostro tipo `Uart`.\n" +"* Esegui l'esempio in QEMU con `make qemu_minimal` sotto `src/bare-metal/aps/examples`." + +#: src/bare-metal/aps/better-uart.md:1 +#, fuzzy +msgid "# A better UART driver" +msgstr "# Un driver UART migliore" + +#: src/bare-metal/aps/better-uart.md:3 +#, fuzzy +msgid "" +"The PL011 actually has [a bunch more registers][1], and adding offsets to construct pointers to access\n" +"them is error-prone and hard to read. Plus, some of them are bit fields which would be nice to\n" +"access in a structured way." +msgstr "" +"Il PL011 in realtà ha [un mucchio di registri in più][1] e aggiunge offset per costruire puntatori a cui accedere\n" +"è soggetto a errori e difficile da leggere. Inoltre, alcuni di loro sono campi di bit che sarebbero carini\n" +"accedere in modo strutturato." + +#: src/bare-metal/aps/better-uart.md:7 +#, fuzzy +msgid "" +"| Offset | Register name | Width |\n" +"| ------ | ------------- | ----- |\n" +"| 0x00 | DR | 12 |\n" +"| 0x04 | RSR | 4 |\n" +"| 0x18 | FR | 9 |\n" +"| 0x20 | ILPR | 8 |\n" +"| 0x24 | IBRD | 16 |\n" +"| 0x28 | FBRD | 6 |\n" +"| 0x2c | LCR_H | 8 |\n" +"| 0x30 | CR | 16 |\n" +"| 0x34 | IFLS | 6 |\n" +"| 0x38 | IMSC | 11 |\n" +"| 0x3c | RIS | 11 |\n" +"| 0x40 | MIS | 11 |\n" +"| 0x44 | ICR | 11 |\n" +"| 0x48 | DMACR | 3 |" +msgstr "" +"| Compensazione | Registra nome | Larghezza |\n" +"| ------ | ------------- | ----- |\n" +"| 0x00 | DR | 12 |\n" +"| 0x04 | RSR | 4 |\n" +"| 0x18 | FR | 9 |\n" +"| 0x20 | ILPR | 8 |\n" +"| 0x24 | BIRS | 16 |\n" +"| 0x28 | FBRD | 6 |\n" +"| 0x2c | LCR_H | 8 |\n" +"| 0x30 | CR | 16 |\n" +"| 0x34 | IFL | 6 |\n" +"| 0x38 | IMSC | 11 |\n" +"| 0x3c | RIS| 11 |\n" +"| 0x40 | MIS | 11 |\n" +"| 0x44 | CRI | 11 |\n" +"| 0x48 | DMACR | 3 |" + +#: src/bare-metal/aps/better-uart.md:26 +#, fuzzy +msgid "- There are also some ID registers which have been omitted for brevity." +msgstr "- Sono inoltre presenti alcuni registri identificativi che per brevità sono stati omessi." + +#: src/bare-metal/aps/better-uart/bitflags.md:1 +#, fuzzy +msgid "# Bitflags" +msgstr "# Bitflag" + +#: src/bare-metal/aps/better-uart/bitflags.md:3 +#, fuzzy +msgid "The [`bitflags`](https://crates.io/crates/bitflags) crate is useful for working with bitflags." +msgstr "Il crate [`bitflags`](https://crates.io/crates/bitflags) è utile per lavorare con i bitflags." + +#: src/bare-metal/aps/better-uart/bitflags.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:37 +#, fuzzy +msgid "" +"* The `bitflags!` macro creates a newtype something like `Flags(u16)`, along with a bunch of method\n" +" implementations to get and set flags." +msgstr "" +"* La macro `bitflags!` crea un nuovo tipo qualcosa come `Flags(u16)`, insieme a una serie di metodi\n" +" implementazioni per ottenere e impostare flag." + +#: src/bare-metal/aps/better-uart/registers.md:1 +#, fuzzy +msgid "# Multiple registers" +msgstr "# Più registri" + +#: src/bare-metal/aps/better-uart/registers.md:3 +#, fuzzy +msgid "We can use a struct to represent the memory layout of the UART's registers." +msgstr "Possiamo usare una struct per rappresentare il layout di memoria dei registri dell'UART." + +#: src/bare-metal/aps/better-uart/registers.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/registers.md:41 +#, fuzzy +msgid "" +"* [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-representation) tells\n" +" the compiler to lay the struct fields out in order, following the same rules as C. This is\n" +" necessary for our struct to have a predictable layout, as default Rust representation allows the\n" +" compiler to (among other things) reorder fields however it sees fit." +msgstr "" +"* [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-representation) indica\n" +" il compilatore per disporre i campi struct in ordine, seguendo le stesse regole di C. Questo è\n" +" necessario affinché la nostra struttura abbia un layout prevedibile, poiché la rappresentazione predefinita di Rust lo consente\n" +" compilatore per (tra le altre cose) riordinare i campi come meglio crede." + +#: src/bare-metal/aps/better-uart/driver.md:1 +#, fuzzy +msgid "# Driver" +msgstr "# Autista" + +#: src/bare-metal/aps/better-uart/driver.md:3 +#, fuzzy +msgid "Now let's use the new `Registers` struct in our driver." +msgstr "Ora usiamo la nuova struttura `Registers` nel nostro driver." + +#: src/bare-metal/aps/better-uart/driver.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the 8 MMIO control registers of a\n" +" /// PL011 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr).read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:64 +#, fuzzy +msgid "" +"* Note the use of `addr_of!` / `addr_of_mut!` to get pointers to individual fields without creating\n" +" an intermediate reference, which would be unsound." +msgstr "" +"* Notare l'uso di `addr_of!` / `addr_of_mut!` per ottenere puntatori a singoli campi senza creare\n" +" un riferimento intermedio, che sarebbe errato." + +#: src/bare-metal/aps/better-uart/using.md:1 src/bare-metal/aps/logging/using.md:1 +#, fuzzy +msgid "# Using it" +msgstr "# Usandolo" + +#: src/bare-metal/aps/better-uart/using.md:3 +#, fuzzy +msgid "" +"Let's write a small program using our driver to write to the serial console, and echo incoming\n" +"bytes." +msgstr "" +"Scriviamo un piccolo programma usando il nostro driver per scrivere sulla console seriale ed echo in entrata\n" +"byte." + +#: src/bare-metal/aps/better-uart/using.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use core::panic::PanicInfo;\n" +"use log::error;\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" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +"\n" +" writeln!(uart, \"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\").unwrap();\n" +"\n" +" loop {\n" +" if let Some(b) = uart.read_byte() {\n" +" uart.write_byte(b);\n" +" match b {\n" +" b'\\r' => {\n" +" uart.write_byte(b'\\n');\n" +" }\n" +" b'q' => break,\n" +" _ => {}\n" +" }\n" +" }\n" +" }\n" +"\n" +" writeln!(uart, \"Bye!\").unwrap();\n" +" system_off::().unwrap();\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:51 +#, fuzzy +msgid "" +"* As in the [inline assembly](../inline-assembly.md) example, this `main` function is called from our\n" +" entry point code in `entry.S`. See the speaker notes there for details.\n" +"* Run the example in QEMU with `make qemu` under `src/bare-metal/aps/examples`." +msgstr "" +"* Come nell'esempio [inline assembly](../inline-assembly.md), questa funzione `main` è chiamata dal nostro\n" +" codice del punto di ingresso in \"entry.S\". Vedi le note del relatore lì per i dettagli.\n" +"* Esegui l'esempio in QEMU con `make qemu` sotto `src/bare-metal/aps/examples`." + +#: src/bare-metal/aps/logging.md:3 +#, fuzzy +msgid "" +"It would be nice to be able to use the logging macros from the [`log`][1] crate. We can do this by\n" +"implementing the `Log` trait." +msgstr "" +"Sarebbe bello poter usare le macro di registrazione dalla cassa [`log`][1]. Possiamo farlo con\n" +"implementando il tratto `Log`." + +#: src/bare-metal/aps/logging.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" +" }\n" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/logging.md:50 +#, fuzzy +msgid "* The unwrap in `log` is safe because we initialise `LOGGER` before calling `set_logger`." +msgstr "* L'unwrap in `log` è sicuro perché inizializziamo `LOGGER` prima di chiamare `set_logger`." + +#: src/bare-metal/aps/logging/using.md:3 +#, fuzzy +msgid "We need to initialise the logger before we use it." +msgstr "Dobbiamo inizializzare il logger prima di usarlo." + +#: src/bare-metal/aps/logging/using.md:5 +msgid "" +"```rust,editable,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, LevelFilter};\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" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\");\n" +"\n" +" assert_eq!(x1, 42);\n" +"\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off::().unwrap();\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/logging/using.md:46 +#, fuzzy +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`." +msgstr "" +"* Nota che il nostro gestore del panico ora può registrare i dettagli dei panico.\n" +"* Eseguire l'esempio in QEMU con `make qemu_logger` in `src/bare-metal/aps/examples`." + +#: src/bare-metal/aps/other-projects.md:3 +#, fuzzy +msgid "" +" * [oreboot](https://github.com/oreboot/oreboot)\n" +" * \"coreboot without the C\"\n" +" * Supports x86, aarch64 and RISC-V.\n" +" * Relies on LinuxBoot rather than having many drivers itself.\n" +" * [Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials)\n" +" * Initialisation, UART driver, simple bootloader, JTAG, exception levels, exception handling, page tables\n" +" * Not all very well written, so beware.\n" +" * [`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)\n" +" * Static analysis to determine maximum stack usage." +msgstr "" +" * [oreboot](https://github.com/oreboot/oreboot)\n" +" * \"coreboot senza la C\"\n" +" * Supporta x86, aarch64 e RISC-V.\n" +" * Si basa su LinuxBoot piuttosto che avere molti driver.\n" +" * [Tutorial sul sistema operativo Rust RaspberryPi](https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials)\n" +" * Inizializzazione, driver UART, bootloader semplice, JTAG, livelli di eccezione, gestione delle eccezioni, tabelle delle pagine\n" +" * Non tutto molto ben scritto, quindi attenzione.\n" +" * [`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)\n" +" * Analisi statica per determinare l'utilizzo massimo dello stack." + +#: src/bare-metal/useful-crates.md:1 +#, fuzzy +msgid "# Useful crates" +msgstr "# Casse utili" + +#: src/bare-metal/useful-crates.md:3 +#, fuzzy +msgid "We'll go over a few crates which solve some common problems in bare-metal programming." +msgstr "Esamineremo alcune casse che risolvono alcuni problemi comuni nella programmazione bare-metal." + +#: src/bare-metal/useful-crates/zerocopy.md:1 +#, fuzzy +msgid "# `zerocopy`" +msgstr "# `zerocopia`" + +#: src/bare-metal/useful-crates/zerocopy.md:3 +#, fuzzy +msgid "" +"The [`zerocopy`][1] crate (from Fuchsia) provides traits and macros for safely converting between\n" +"byte sequences and other types." +msgstr "" +"La cassa [`zerocopy`][1] (da Fuchsia) fornisce tratti e macro per la conversione sicura tra\n" +"sequenze di byte e altri tipi." + +#: src/bare-metal/useful-crates/zerocopy.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use zerocopy::AsBytes;\n" +"\n" +"#[repr(u32)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"enum RequestType {\n" +" #[default]\n" +" In = 0,\n" +" Out = 1,\n" +" Flush = 4,\n" +"}\n" +"\n" +"#[repr(C)]\n" +"#[derive(AsBytes, Debug, Default)]\n" +"struct VirtioBlockRequest {\n" +" request_type: RequestType,\n" +" reserved: u32,\n" +" sector: u64,\n" +"}\n" +"\n" +"fn main() {\n" +" let request = VirtioBlockRequest {\n" +" request_type: RequestType::Flush,\n" +" sector: 42,\n" +" ..Default::default()\n" +" };\n" +"\n" +" assert_eq!(\n" +" request.as_bytes(),\n" +" &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0]\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/zerocopy.md:40 +#, fuzzy +msgid "" +"This is not suitable for MMIO (as it doesn't use volatile reads and writes), but can be useful for\n" +"working with structures shared with hardware e.g. by DMA, or sent over some external interface." +msgstr "" +"Questo non è adatto per MMIO (poiché non utilizza letture e scritture volatili), ma può essere utile per\n" +"lavorare con strutture condivise con l'hardware, ad es. tramite DMA o inviato tramite un'interfaccia esterna." + +#: src/bare-metal/useful-crates/zerocopy.md:45 +#, fuzzy +msgid "" +"* `FromBytes` can be implemented for types for which any byte pattern is valid, and so can safely be\n" +" converted from an untrusted sequence of bytes.\n" +"* Attempting to derive `FromBytes` for these types would fail, because `RequestType` doesn't use all\n" +" possible u32 values as discriminants, so not all byte patterns are valid.\n" +"* `zerocopy::byteorder` has types for byte-order aware numeric primitives.\n" +"* Run the example with `cargo run` under `src/bare-metal/useful-crates/zerocopy-example/`. (It won't\n" +" run in the Playground because of the crate dependency.)" +msgstr "" +"* `FromBytes` può essere implementato per i tipi per i quali qualsiasi modello di byte è valido, e quindi può tranquillamente esserlo\n" +" convertito da una sequenza di byte non attendibile.\n" +"* Il tentativo di derivare `FromBytes` per questi tipi fallirebbe, perché `RequestType` non usa tutti\n" +" possibili valori u32 come discriminanti, quindi non tutti i modelli di byte sono validi.\n" +"* `zerocopy::byteorder` ha tipi per primitive numeriche che riconoscono l'ordine dei byte.\n" +"* Esegui l'esempio con `cargo run` sotto `src/bare-metal/useful-crates/zerocopy-example/`. (Non lo farà\n" +" eseguito nel Parco giochi a causa della dipendenza dalla cassa.)" + +#: src/bare-metal/useful-crates/aarch64-paging.md:1 +#, fuzzy +msgid "# `aarch64-paging`" +msgstr "# `aarch64-paging`" + +#: src/bare-metal/useful-crates/aarch64-paging.md:3 +#, fuzzy +msgid "" +"The [`aarch64-paging`][1] crate lets you create page tables according to the AArch64 Virtual Memory\n" +"System Architecture." +msgstr "" +"Il crate [`aarch64-paging`][1] consente di creare tabelle di pagine in base alla memoria virtuale AArch64\n" +"Architettura di sistema." + +#: src/bare-metal/useful-crates/aarch64-paging.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"use aarch64_paging::{\n" +" idmap::IdMap,\n" +" paging::{Attributes, MemoryRegion},\n" +"};\n" +"\n" +"const ASID: usize = 1;\n" +"const ROOT_LEVEL: usize = 1;\n" +"\n" +"// Create a new page table with identity mapping.\n" +"let mut idmap = IdMap::new(ASID, ROOT_LEVEL);\n" +"// Map a 2 MiB region of memory as read-only.\n" +"idmap.map_range(\n" +" &MemoryRegion::new(0x80200000, 0x80400000),\n" +" Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,\n" +").unwrap();\n" +"// Set `TTBR0_EL1` to activate the page table.\n" +"idmap.activate();\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:28 +#, fuzzy +msgid "" +"* For now it only supports EL1, but support for other exception levels should be straightforward to\n" +" add.\n" +"* This is used in Android for the [Protected VM Firmware][2].\n" +"* There's no easy way to run this example, as it needs to run on real hardware or under QEMU." +msgstr "" +"* Per ora supporta solo EL1, ma il supporto per altri livelli di eccezione dovrebbe essere semplice\n" +" aggiungere.\n" +"* Viene utilizzato in Android per il [Firmware VM protetto][2].\n" +"* Non esiste un modo semplice per eseguire questo esempio, poiché deve essere eseguito su hardware reale o sotto QEMU." + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:1 +#, fuzzy +msgid "# `buddy_system_allocator`" +msgstr "# `buddy_system_allocator`" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:3 +#, fuzzy +msgid "" +"[`buddy_system_allocator`][1] is a third-party crate implementing a basic buddy system allocator.\n" +"It can be used both for [`LockedHeap`][2] implementing [`GlobalAlloc`][3] so you can use the\n" +"standard `alloc` crate (as we saw [before][4]), or for allocating other address space. For example,\n" +"we might want to allocate MMIO space for PCI BARs:" +msgstr "" +"[`buddy_system_allocator`][1] è un crate di terze parti che implementa un allocatore di sistema buddy di base.\n" +"Può essere utilizzato sia per [`LockedHeap`][2] che implementa [`GlobalAlloc`][3] in modo da poter utilizzare il\n" +"crate standard `alloc` (come abbiamo visto [prima][4]), o per allocare altro spazio di indirizzi. Per esempio,\n" +"potremmo voler allocare spazio MMIO per PCI BAR:" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use buddy_system_allocator::FrameAllocator;\n" +"use core::alloc::Layout;\n" +"\n" +"fn main() {\n" +" let mut allocator = FrameAllocator::<32>::new();\n" +" allocator.add_frame(0x200_0000, 0x400_0000);\n" +"\n" +" let layout = Layout::from_size_align(0x100, 0x100).unwrap();\n" +" let bar = allocator\n" +" .alloc_aligned(layout)\n" +" .expect(\"Failed to allocate 0x100 byte MMIO region\");\n" +" println!(\"Allocated 0x100 byte MMIO region at {:#x}\", bar);\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/buddy_system_allocator.md:26 +#, fuzzy +msgid "" +"* PCI BARs always have alignment equal to their size.\n" +"* Run the example with `cargo run` under `src/bare-metal/useful-crates/allocator-example/`. (It won't\n" +" run in the Playground because of the crate dependency.)" +msgstr "" +"* Le barre PCI hanno sempre un allineamento uguale alla loro dimensione.\n" +"* Esegui l'esempio con `cargo run` sotto `src/bare-metal/useful-crates/allocator-example/`. (Non lo farà\n" +" eseguito nel Parco giochi a causa della dipendenza dalla cassa.)" + +#: src/bare-metal/useful-crates/tinyvec.md:1 +#, fuzzy +msgid "# `tinyvec`" +msgstr "# `tinyvec`" + +#: src/bare-metal/useful-crates/tinyvec.md:3 +#, fuzzy +msgid "" +"Sometimes you want something which can be resized like a `Vec`, but without heap allocation.\n" +"[`tinyvec`][1] provides this: a vector backed by an array or slice, which could be statically\n" +"allocated or on the stack, which keeps track of how many elements are used and panics if you try to\n" +"use more than are allocated." +msgstr "" +"A volte vuoi qualcosa che possa essere ridimensionato come un `Vec`, ma senza allocazione dell'heap.\n" +"[`tinyvec`][1] fornisce questo: un vettore supportato da un array o da una slice, che potrebbe essere staticamente\n" +"allocato o in pila, che tiene traccia di quanti elementi vengono utilizzati e va in panico se ci provi\n" +"utilizzare più di quanto assegnato." + +#: src/bare-metal/useful-crates/tinyvec.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use tinyvec::{array_vec, ArrayVec};\n" +"\n" +"fn main() {\n" +" let mut numbers: ArrayVec<[u32; 5]> = array_vec!(42, 66);\n" +" println!(\"{numbers:?}\");\n" +" numbers.push(7);\n" +" println!(\"{numbers:?}\");\n" +" numbers.remove(1);\n" +" println!(\"{numbers:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/tinyvec.md:23 +#, fuzzy +msgid "" +"* `tinyvec` requires that the element type implement `Default` for initialisation.\n" +"* The Rust Playground includes `tinyvec`, so this example will run fine inline." +msgstr "" +"* `tinyvec` richiede che il tipo di elemento implementi `Default` per l'inizializzazione.\n" +"* Rust Playground include `tinyvec`, quindi questo esempio funzionerà correttamente in linea." + +#: src/bare-metal/useful-crates/spin.md:1 +#, fuzzy +msgid "# `spin`" +msgstr "# `gira`" + +#: src/bare-metal/useful-crates/spin.md:3 +#, fuzzy +msgid "" +"`std::sync::Mutex` and the other synchronisation primitives from `std::sync` are not available in\n" +"`core` or `alloc`. How can we manage synchronisation or interior mutability, such as for sharing\n" +"state between different CPUs?" +msgstr "" +"`std::sync::Mutex` e le altre primitive di sincronizzazione da `std::sync` non sono disponibili in\n" +"`core` o `alloc`. Come gestire la sincronizzazione o la mutevolezza interiore, ad esempio per la condivisione\n" +"stato tra diverse CPU?" + +#: src/bare-metal/useful-crates/spin.md:7 +#, fuzzy +msgid "The [`spin`][1] crate provides spinlock-based equivalents of many of these primitives." +msgstr "La cassa [`spin`][1] fornisce equivalenti basati su spinlock di molte di queste primitive." + +#: src/bare-metal/useful-crates/spin.md:9 +msgid "" +"```rust,editable,compile_fail\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static counter: SpinMutex = SpinMutex::new(0);\n" +"\n" +"fn main() {\n" +" println!(\"count: {}\", counter.lock());\n" +" *counter.lock() += 2;\n" +" println!(\"count: {}\", counter.lock());\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/useful-crates/spin.md:23 +msgid "" +"* Be careful to avoid deadlock if you take locks in interrupt handlers.\n" +"* `spin` also has a ticket lock mutex implementation; equivalents of `RwLock`, `Barrier` and `Once`\n" +" from `std::sync`; and `Lazy` for lazy initialisation.\n" +"* The [`once_cell`][2] crate also has some useful types for late initialisation with a slightly\n" +" different approach to `spin::once::Once`.\n" +"* The Rust Playground includes `spin`, so this example will run fine inline." +msgstr "" + +#: src/bare-metal/android.md:1 +#, fuzzy +msgid "# Android" +msgstr "#Androide" + +#: src/bare-metal/android.md:3 +#, fuzzy +msgid "" +"To build a bare-metal Rust binary in AOSP, you need to use a `rust_ffi_static` Soong rule to build\n" +"your Rust code, then a `cc_binary` with a linker script to produce the binary itself, and then a\n" +"`raw_binary` to convert the ELF to a raw binary ready to be run." +msgstr "" +"Per costruire un binario Rust bare-metal in AOSP, devi usare una regola `rust_ffi_static` Soong per costruire\n" +"il tuo codice Rust, poi un `cc_binary` con uno script linker per produrre il binario stesso, e poi a\n" +"`raw_binary` per convertire l'ELF in un binario grezzo pronto per essere eseguito." + +#: src/bare-metal/android.md:7 +msgid "" +"```soong\n" +"rust_ffi_static {\n" +" name: \"libvmbase_example\",\n" +" defaults: [\"vmbase_ffi_defaults\"],\n" +" crate_name: \"vmbase_example\",\n" +" srcs: [\"src/main.rs\"],\n" +" rustlibs: [\n" +" \"libvmbase\",\n" +" ],\n" +"}\n" +"\n" +"cc_binary {\n" +" name: \"vmbase_example\",\n" +" defaults: [\"vmbase_elf_defaults\"],\n" +" srcs: [\n" +" \"idmap.S\",\n" +" ],\n" +" static_libs: [\n" +" \"libvmbase_example\",\n" +" ],\n" +" linker_scripts: [\n" +" \"image.ld\",\n" +" \":vmbase_sections\",\n" +" ],\n" +"}\n" +"\n" +"raw_binary {\n" +" name: \"vmbase_example_bin\",\n" +" stem: \"vmbase_example.bin\",\n" +" src: \":vmbase_example\",\n" +" enabled: false,\n" +" target: {\n" +" android_arm64: {\n" +" enabled: true,\n" +" },\n" +" },\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/android/vmbase.md:1 +#, fuzzy +msgid "# vmbase" +msgstr "# vbase" + +#: src/bare-metal/android/vmbase.md:3 +#, fuzzy +msgid "" +"For VMs running under crosvm on aarch64, the [vmbase][1] library provides a linker script and useful\n" +"defaults for the build rules, along with an entry point, UART console logging and more." +msgstr "" +"Per le VM in esecuzione in crosvm su aarch64, la libreria [vmbase][1] fornisce uno script linker e utili\n" +"impostazioni predefinite per le regole di compilazione, insieme a un punto di ingresso, la registrazione della console UART e altro ancora." + +#: src/bare-metal/android/vmbase.md:6 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"use vmbase::{main, println};\n" +"\n" +"main!(main);\n" +"\n" +"pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {\n" +" println!(\"Hello world\");\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/android/vmbase.md:21 +#, fuzzy +msgid "" +"* The `main!` macro marks your main function, to be called from the `vmbase` entry point.\n" +"* The `vmbase` entry point handles console initialisation, and issues a PSCI_SYSTEM_OFF to shutdown\n" +" the VM if your main function returns." +msgstr "" +"* La macro `main!` contrassegna la tua funzione principale, da chiamare dal punto di ingresso `vmbase`.\n" +"* Il punto di ingresso `vmbase` gestisce l'inizializzazione della console ed emette un PSCI_SYSTEM_OFF per l'arresto\n" +" la VM se la tua funzione principale ritorna." + +#: src/exercises/bare-metal/afternoon.md:3 +#, fuzzy +msgid "We will write a driver for the PL031 real-time clock device." +msgstr "Scriveremo un driver per il dispositivo orologio in tempo reale PL031." + +#: src/exercises/bare-metal/rtc.md:1 +#, fuzzy +msgid "# RTC driver" +msgstr "# Driver RTC" + +#: src/exercises/bare-metal/rtc.md:3 +#, fuzzy +msgid "" +"The QEMU aarch64 virt machine has a [PL031][1] real-time clock at 0x9010000. For this exercise, you\n" +"should write a driver for it." +msgstr "" +"La macchina QEMU aarch64 virt ha un orologio in tempo reale [PL031][1] a 0x9010000. Per questo esercizio, tu\n" +"dovrebbe scrivere un driver per esso." + +#: src/exercises/bare-metal/rtc.md:6 +#, fuzzy +msgid "" +"1. Use it to print the current time to the serial console. You can use the [`chrono`][2] crate for\n" +" date/time formatting.\n" +"2. Use the match register and raw interrupt status to busy-wait until a given time, e.g. 3 seconds\n" +" 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`][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 "" +"1. Usalo per stampare l'ora corrente sulla console seriale. Puoi usare la cassa [`chrono`][2] per\n" +" formattazione data/ora.\n" +"2. Utilizzare il registro delle corrispondenze e lo stato di interrupt non elaborato per attendere occupato fino a un determinato momento, ad es. 3 " +"secondi\n" +" in futuro. (Chiama [`core::hint::spin_loop`][3] all'interno del ciclo.)\n" +"3. _Estensione se hai tempo:_ Abilita e gestisci l'interrupt generato dalla corrispondenza RTC. Puoi\n" +" utilizzare il driver fornito nella cassa [`arm-gic`][4] per configurare Arm Generic Interrupt Controller.\n" +" - Usa l'interrupt RTC, che è cablato al GIC come `IntId::spi(2)`.\n" +" - Una volta abilitato l'interrupt, puoi mettere il core in sleep tramite `arm_gic::wfi()`, che farà dormire il core finché non riceve un " +"interrupt.\n" +" " + +#: src/exercises/bare-metal/rtc.md:16 +#, fuzzy +msgid "" +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the `rtc`\n" +"directory for the following files." +msgstr "" +"Scarica il [modello di esercizio](../../comprehensive-rust-exercises.zip) e cerca in `rtc`\n" +"directory per i seguenti file." + +#: src/exercises/bare-metal/rtc.md:23 +msgid "" +"```rust,compile_fail\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"\n" +"use crate::pl011::Uart;\n" +"use arm_gic::gicv3::GicV3;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, trace, LevelFilter};\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" +"const GICR_BASE_ADDRESS: *mut u64 = 0x80A_0000 as _;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +"\n" +" // Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base\n" +" // addresses of a GICv3 distributor and redistributor respectively, and\n" +" // nothing else accesses those address ranges.\n" +" let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, GICR_BASE_ADDRESS) };\n" +" gic.setup();\n" +"\n" +" // TODO: Create instance of RTC driver and print current time.\n" +"\n" +" // TODO: Wait for 3 seconds.\n" +"\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off::().unwrap();\n" +" loop {}\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:75 +#, fuzzy +msgid "`src/exceptions.rs` (you should only need to change this for the 3rd part of the exercise):" +msgstr "`src/exceptions.rs` (dovresti solo cambiarlo per la terza parte dell'esercizio):" + +#: src/exercises/bare-metal/rtc.md:77 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:79 +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" +"use arm_gic::gicv3::GicV3;\n" +"use log::{error, info, trace};\n" +"use smccc::psci::system_off;\n" +"use smccc::Hvc;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_exception_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" +" trace!(\"irq_current\");\n" +" let intid = GicV3::get_and_acknowledge_interrupt().expect(\"No pending interrupt\");\n" +" info!(\"IRQ {intid:?}\");\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:149 +#, fuzzy +msgid "`src/logger.rs` (you shouldn't need to change this):" +msgstr "`src/logger.rs` (non dovrebbe essere necessario modificarlo):" + +#: src/exercises/bare-metal/rtc.md:151 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:153 +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: main\n" +"use crate::pl011::Uart;\n" +"use core::fmt::Write;\n" +"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" +"use spin::mutex::SpinMutex;\n" +"\n" +"static LOGGER: Logger = Logger {\n" +" uart: SpinMutex::new(None),\n" +"};\n" +"\n" +"struct Logger {\n" +" uart: SpinMutex>,\n" +"}\n" +"\n" +"impl Log for Logger {\n" +" fn enabled(&self, _metadata: &Metadata) -> bool {\n" +" true\n" +" }\n" +"\n" +" fn log(&self, record: &Record) {\n" +" writeln!(\n" +" self.uart.lock().as_mut().unwrap(),\n" +" \"[{}] {}\",\n" +" record.level(),\n" +" record.args()\n" +" )\n" +" .unwrap();\n" +" }\n" +"\n" +" fn flush(&self) {}\n" +"}\n" +"\n" +"/// Initialises UART logger.\n" +"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), SetLoggerError> {\n" +" LOGGER.uart.lock().replace(uart);\n" +"\n" +" log::set_logger(&LOGGER)?;\n" +" log::set_max_level(max_level);\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:210 +#, fuzzy +msgid "`src/pl011.rs` (you shouldn't need to change this):" +msgstr "`src/pl011.rs` (non dovresti aver bisogno di cambiarlo):" + +#: src/exercises/bare-metal/rtc.md:212 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:214 +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" +"#![allow(unused)]\n" +"\n" +"use core::fmt::{self, Write};\n" +"use core::ptr::{addr_of, addr_of_mut};\n" +"\n" +"// ANCHOR: Flags\n" +"use bitflags::bitflags;\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART flag register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct Flags: u16 {\n" +" /// Clear to send.\n" +" const CTS = 1 << 0;\n" +" /// Data set ready.\n" +" const DSR = 1 << 1;\n" +" /// Data carrier detect.\n" +" const DCD = 1 << 2;\n" +" /// UART busy transmitting data.\n" +" const BUSY = 1 << 3;\n" +" /// Receive FIFO is empty.\n" +" const RXFE = 1 << 4;\n" +" /// Transmit FIFO is full.\n" +" const TXFF = 1 << 5;\n" +" /// Receive FIFO is full.\n" +" const RXFF = 1 << 6;\n" +" /// Transmit FIFO is empty.\n" +" const TXFE = 1 << 7;\n" +" /// Ring indicator.\n" +" const RI = 1 << 8;\n" +" }\n" +"}\n" +"// ANCHOR_END: Flags\n" +"\n" +"bitflags! {\n" +" /// Flags from the UART Receive Status Register / Error Clear Register.\n" +" #[repr(transparent)]\n" +" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +" struct ReceiveStatus: u16 {\n" +" /// Framing error.\n" +" const FE = 1 << 0;\n" +" /// Parity error.\n" +" const PE = 1 << 1;\n" +" /// Break error.\n" +" const BE = 1 << 2;\n" +" /// Overrun error.\n" +" const OE = 1 << 3;\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Registers\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" dr: u16,\n" +" _reserved0: [u8; 2],\n" +" rsr: ReceiveStatus,\n" +" _reserved1: [u8; 19],\n" +" fr: Flags,\n" +" _reserved2: [u8; 6],\n" +" ilpr: u8,\n" +" _reserved3: [u8; 3],\n" +" ibrd: u16,\n" +" _reserved4: [u8; 2],\n" +" fbrd: u8,\n" +" _reserved5: [u8; 3],\n" +" lcr_h: u8,\n" +" _reserved6: [u8; 3],\n" +" cr: u16,\n" +" _reserved7: [u8; 3],\n" +" ifls: u8,\n" +" _reserved8: [u8; 3],\n" +" imsc: u16,\n" +" _reserved9: [u8; 2],\n" +" ris: u16,\n" +" _reserved10: [u8; 2],\n" +" mis: u16,\n" +" _reserved11: [u8; 2],\n" +" icr: u16,\n" +" _reserved12: [u8; 2],\n" +" dmacr: u8,\n" +" _reserved13: [u8; 3],\n" +"}\n" +"// ANCHOR_END: Registers\n" +"\n" +"// ANCHOR: Uart\n" +"/// Driver for a PL011 UART.\n" +"#[derive(Debug)]\n" +"pub struct Uart {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Uart {\n" +" /// Constructs a new instance of the UART driver for a PL011 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of a\n" +" /// PL011 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Writes a single byte to the UART.\n" +" pub fn write_byte(&self, byte: u8) {\n" +" // Wait until there is room in the TX buffer.\n" +" while self.read_flag_register().contains(Flags::TXFF) {}\n" +"\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe {\n" +" // Write to the TX buffer.\n" +" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" +" }\n" +"\n" +" // Wait until the UART is no longer busy.\n" +" while self.read_flag_register().contains(Flags::BUSY) {}\n" +" }\n" +"\n" +" /// Reads and returns a pending byte, or `None` if nothing has been received.\n" +" pub fn read_byte(&self) -> Option {\n" +" if self.read_flag_register().contains(Flags::RXFE) {\n" +" None\n" +" } else {\n" +" let data = unsafe { addr_of!((*self.registers).dr).read_volatile() };\n" +" // TODO: Check for error conditions in bits 8-11.\n" +" Some(data as u8)\n" +" }\n" +" }\n" +"\n" +" fn read_flag_register(&self) -> Flags {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL011 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" +" }\n" +"}\n" +"// ANCHOR_END: Uart\n" +"\n" +"impl Write for Uart {\n" +" fn write_str(&mut self, s: &str) -> fmt::Result {\n" +" for c in s.as_bytes() {\n" +" self.write_byte(*c);\n" +" }\n" +" Ok(())\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Uart {}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:389 +msgid "" +"```toml\n" +"[workspace]\n" +"\n" +"[package]\n" +"name = \"rtc\"\n" +"version = \"0.1.0\"\n" +"edition = \"2021\"\n" +"publish = false\n" +"\n" +"[dependencies]\n" +"arm-gic = \"0.1.0\"\n" +"bitflags = \"2.0.0\"\n" +"chrono = { version = \"0.4.24\", default-features = false }\n" +"log = \"0.4.17\"\n" +"smccc = \"0.1.1\"\n" +"spin = \"0.9.8\"\n" +"\n" +"[build-dependencies]\n" +"cc = \"1.0.73\"\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:410 +#, fuzzy +msgid "`build.rs` (you shouldn't need to change this):" +msgstr "`build.rs` (non dovresti aver bisogno di cambiarlo):" + +#: src/exercises/bare-metal/rtc.md:412 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:414 +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" +"use cc::Build;\n" +"use std::env;\n" +"\n" +"fn main() {\n" +" #[cfg(target_os = \"linux\")]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-linux-gnu\");\n" +" #[cfg(not(target_os = \"linux\"))]\n" +" env::set_var(\"CROSS_COMPILE\", \"aarch64-none-elf\");\n" +"\n" +" Build::new()\n" +" .file(\"entry.S\")\n" +" .file(\"exceptions.S\")\n" +" .file(\"idmap.S\")\n" +" .compile(\"empty\")\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:446 +#, fuzzy +msgid "`entry.S` (you shouldn't need to change this):" +msgstr "`entry.S` (non dovresti aver bisogno di cambiarlo):" + +#: src/exercises/bare-metal/rtc.md:448 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:450 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".macro adr_l, reg:req, sym:req\n" +"\tadrp \\reg, \\sym\n" +"\tadd \\reg, \\reg, :lo12:\\sym\n" +".endm\n" +"\n" +".macro mov_i, reg:req, imm:req\n" +"\tmovz \\reg, :abs_g3:\\imm\n" +"\tmovk \\reg, :abs_g2_nc:\\imm\n" +"\tmovk \\reg, :abs_g1_nc:\\imm\n" +"\tmovk \\reg, :abs_g0_nc:\\imm\n" +".endm\n" +"\n" +".set .L_MAIR_DEV_nGnRE,\t0x04\n" +".set .L_MAIR_MEM_WBWA,\t0xff\n" +".set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8)\n" +"\n" +"/* 4 KiB granule size for TTBR0_EL1. */\n" +".set .L_TCR_TG0_4KB, 0x0 << 14\n" +"/* 4 KiB granule size for TTBR1_EL1. */\n" +".set .L_TCR_TG1_4KB, 0x2 << 30\n" +"/* Disable translation table walk for TTBR1_EL1, generating a translation fault instead. */\n" +".set .L_TCR_EPD1, 0x1 << 23\n" +"/* Translation table walks for TTBR0_EL1 are inner sharable. */\n" +".set .L_TCR_SH_INNER, 0x3 << 12\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are outer write-back read-allocate write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_OWB, 0x1 << 10\n" +"/*\n" +" * Translation table walks for TTBR0_EL1 are inner write-back read-allocate write-allocate\n" +" * cacheable.\n" +" */\n" +".set .L_TCR_RGN_IWB, 0x1 << 8\n" +"/* Size offset for TTBR0_EL1 is 2**39 bytes (512 GiB). */\n" +".set .L_TCR_T0SZ_512, 64 - 39\n" +".set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_TG1_4KB | .L_TCR_EPD1 | .L_TCR_RGN_OWB\n" +".set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | .L_TCR_T0SZ_512\n" +"\n" +"/* Stage 1 instruction access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_I, 0x1 << 12\n" +"/* SP alignment fault if SP is not aligned to a 16 byte boundary. */\n" +".set .L_SCTLR_ELx_SA, 0x1 << 3\n" +"/* Stage 1 data access cacheability is unaffected. */\n" +".set .L_SCTLR_ELx_C, 0x1 << 2\n" +"/* EL0 and EL1 stage 1 MMU enabled. */\n" +".set .L_SCTLR_ELx_M, 0x1 << 0\n" +"/* Privileged Access Never is unchanged on taking an exception to EL1. */\n" +".set .L_SCTLR_EL1_SPAN, 0x1 << 23\n" +"/* SETEND instruction disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_SED, 0x1 << 8\n" +"/* Various IT instructions are disabled at EL0 in aarch32 mode. */\n" +".set .L_SCTLR_EL1_ITD, 0x1 << 7\n" +".set .L_SCTLR_EL1_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29)\n" +".set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | .L_SCTLR_EL1_ITD | .L_SCTLR_EL1_SED\n" +".set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL1_SPAN | .L_SCTLR_EL1_RES1\n" +"\n" +"/**\n" +" * This is a generic entry point for an image. It carries out the operations required to prepare the\n" +" * loaded image to be run. Specifically, it zeroes the bss section using registers x25 and above,\n" +" * prepares the stack, enables floating point, and sets up the exception vector. It preserves x0-x3\n" +" * for the Rust entry point, as these may contain boot parameters.\n" +" */\n" +".section .init.entry, \"ax\"\n" +".global entry\n" +"entry:\n" +"\t/* Load and apply the memory management configuration, ready to enable MMU and caches. */\n" +"\tadrp x30, idmap\n" +"\tmsr ttbr0_el1, x30\n" +"\n" +"\tmov_i x30, .Lmairval\n" +"\tmsr mair_el1, x30\n" +"\n" +"\tmov_i x30, .Ltcrval\n" +"\t/* Copy the supported PA range into TCR_EL1.IPS. */\n" +"\tmrs x29, id_aa64mmfr0_el1\n" +"\tbfi x30, x29, #32, #4\n" +"\n" +"\tmsr tcr_el1, x30\n" +"\n" +"\tmov_i x30, .Lsctlrval\n" +"\n" +"\t/*\n" +"\t * Ensure everything before this point has completed, then invalidate any potentially stale\n" +"\t * local TLB entries before they start being used.\n" +"\t */\n" +"\tisb\n" +"\ttlbi vmalle1\n" +"\tic iallu\n" +"\tdsb nsh\n" +"\tisb\n" +"\n" +"\t/*\n" +"\t * Configure sctlr_el1 to enable MMU and cache and don't proceed until this has completed.\n" +"\t */\n" +"\tmsr sctlr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Disable trapping floating point access in EL1. */\n" +"\tmrs x30, cpacr_el1\n" +"\torr x30, x30, #(0x3 << 20)\n" +"\tmsr cpacr_el1, x30\n" +"\tisb\n" +"\n" +"\t/* Zero out the bss section. */\n" +"\tadr_l x29, bss_begin\n" +"\tadr_l x30, bss_end\n" +"0:\tcmp x29, x30\n" +"\tb.hs 1f\n" +"\tstp xzr, xzr, [x29], #16\n" +"\tb 0b\n" +"\n" +"1:\t/* Prepare the stack. */\n" +"\tadr_l x30, boot_stack_end\n" +"\tmov sp, x30\n" +"\n" +"\t/* Set up exception vector. */\n" +"\tadr x30, vector_table_el1\n" +"\tmsr vbar_el1, x30\n" +"\n" +"\t/* Call into Rust code. */\n" +"\tbl main\n" +"\n" +"\t/* Loop forever waiting for interrupts. */\n" +"2:\twfi\n" +"\tb 2b\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:595 +#, fuzzy +msgid "`exceptions.S` (you shouldn't need to change this):" +msgstr "`eccezioni.S` (non dovresti aver bisogno di cambiarlo):" + +#: src/exercises/bare-metal/rtc.md:597 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:599 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +"/**\n" +" * Saves the volatile registers onto the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers with 18 instructions\n" +" * left.\n" +" *\n" +" * On return, x0 and x1 are initialised to elr_el2 and spsr_el2 respectively,\n" +" * which can be used as the first and second arguments of a subsequent call.\n" +" */\n" +".macro save_volatile_to_stack\n" +"\t/* Reserve stack space and save registers x0-x18, x29 & x30. */\n" +"\tstp x0, x1, [sp, #-(8 * 24)]!\n" +"\tstp x2, x3, [sp, #8 * 2]\n" +"\tstp x4, x5, [sp, #8 * 4]\n" +"\tstp x6, x7, [sp, #8 * 6]\n" +"\tstp x8, x9, [sp, #8 * 8]\n" +"\tstp x10, x11, [sp, #8 * 10]\n" +"\tstp x12, x13, [sp, #8 * 12]\n" +"\tstp x14, x15, [sp, #8 * 14]\n" +"\tstp x16, x17, [sp, #8 * 16]\n" +"\tstr x18, [sp, #8 * 18]\n" +"\tstp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/*\n" +"\t * Save elr_el1 & spsr_el1. This such that we can take nested exception\n" +"\t * and still be able to unwind.\n" +"\t */\n" +"\tmrs x0, elr_el1\n" +"\tmrs x1, spsr_el1\n" +"\tstp x0, x1, [sp, #8 * 22]\n" +".endm\n" +"\n" +"/**\n" +" * Restores the volatile registers from the stack. This currently takes 14\n" +" * instructions, so it can be used in exception handlers while still leaving 18\n" +" * instructions left; if paired with save_volatile_to_stack, there are 4\n" +" * instructions to spare.\n" +" */\n" +".macro restore_volatile_from_stack\n" +"\t/* Restore registers x2-x18, x29 & x30. */\n" +"\tldp x2, x3, [sp, #8 * 2]\n" +"\tldp x4, x5, [sp, #8 * 4]\n" +"\tldp x6, x7, [sp, #8 * 6]\n" +"\tldp x8, x9, [sp, #8 * 8]\n" +"\tldp x10, x11, [sp, #8 * 10]\n" +"\tldp x12, x13, [sp, #8 * 12]\n" +"\tldp x14, x15, [sp, #8 * 14]\n" +"\tldp x16, x17, [sp, #8 * 16]\n" +"\tldr x18, [sp, #8 * 18]\n" +"\tldp x29, x30, [sp, #8 * 20]\n" +"\n" +"\t/* Restore registers elr_el1 & spsr_el1, using x0 & x1 as scratch. */\n" +"\tldp x0, x1, [sp, #8 * 22]\n" +"\tmsr elr_el1, x0\n" +"\tmsr spsr_el1, x1\n" +"\n" +"\t/* Restore x0 & x1, and release stack space. */\n" +"\tldp x0, x1, [sp], #8 * 24\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while using\n" +" * SP0. It behaves similarly to the SPx case by first switching to SPx, doing\n" +" * the work, then switching back to SP0 before returning.\n" +" *\n" +" * Switching to SPx and calling the Rust handler takes 16 instructions. To\n" +" * restore and return we need an additional 16 instructions, so we can implement\n" +" * the whole handler within the allotted 32 instructions.\n" +" */\n" +".macro current_exception_sp0 handler:req\n" +"\tmsr spsel, #1\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\tmsr spsel, #0\n" +"\teret\n" +".endm\n" +"\n" +"/**\n" +" * This is a generic handler for exceptions taken at the current EL while using\n" +" * SPx. It saves volatile registers, calls the Rust handler, restores volatile\n" +" * registers, then returns.\n" +" *\n" +" * This also works for exceptions taken from EL0, if we don't care about\n" +" * non-volatile registers.\n" +" *\n" +" * Saving state and jumping to the Rust handler takes 15 instructions, and\n" +" * restoring and returning also takes 15 instructions, so we can fit the whole\n" +" * handler in 30 instructions, under the limit of 32.\n" +" */\n" +".macro current_exception_spx handler:req\n" +"\tsave_volatile_to_stack\n" +"\tbl \\handler\n" +"\trestore_volatile_from_stack\n" +"\teret\n" +".endm\n" +"\n" +".section .text.vector_table_el1, \"ax\"\n" +".global vector_table_el1\n" +".balign 0x800\n" +"vector_table_el1:\n" +"sync_cur_sp0:\n" +"\tcurrent_exception_sp0 sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_sp0:\n" +"\tcurrent_exception_sp0 irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_sp0:\n" +"\tcurrent_exception_sp0 fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_sp0:\n" +"\tcurrent_exception_sp0 serr_current\n" +"\n" +".balign 0x80\n" +"sync_cur_spx:\n" +"\tcurrent_exception_spx sync_exception_current\n" +"\n" +".balign 0x80\n" +"irq_cur_spx:\n" +"\tcurrent_exception_spx irq_current\n" +"\n" +".balign 0x80\n" +"fiq_cur_spx:\n" +"\tcurrent_exception_spx fiq_current\n" +"\n" +".balign 0x80\n" +"serr_cur_spx:\n" +"\tcurrent_exception_spx serr_current\n" +"\n" +".balign 0x80\n" +"sync_lower_64:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_64:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_64:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_64:\n" +"\tcurrent_exception_spx serr_lower\n" +"\n" +".balign 0x80\n" +"sync_lower_32:\n" +"\tcurrent_exception_spx sync_lower\n" +"\n" +".balign 0x80\n" +"irq_lower_32:\n" +"\tcurrent_exception_spx irq_lower\n" +"\n" +".balign 0x80\n" +"fiq_lower_32:\n" +"\tcurrent_exception_spx fiq_lower\n" +"\n" +".balign 0x80\n" +"serr_lower_32:\n" +"\tcurrent_exception_spx serr_lower\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:780 +#, fuzzy +msgid "`idmap.S` (you shouldn't need to change this):" +msgstr "`idmap.S` (non dovresti aver bisogno di cambiarlo):" + +#: src/exercises/bare-metal/rtc.md:782 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:784 +msgid "" +"```armasm\n" +"/*\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" +" * https://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" +"\n" +".set .L_TT_TYPE_BLOCK, 0x1\n" +".set .L_TT_TYPE_PAGE, 0x3\n" +".set .L_TT_TYPE_TABLE, 0x3\n" +"\n" +"/* Access flag. */\n" +".set .L_TT_AF, 0x1 << 10\n" +"/* Not global. */\n" +".set .L_TT_NG, 0x1 << 11\n" +".set .L_TT_XN, 0x3 << 53\n" +"\n" +".set .L_TT_MT_DEV, 0x0 << 2\t\t\t// MAIR #0 (DEV_nGnRE)\n" +".set .L_TT_MT_MEM, (0x1 << 2) | (0x3 << 8)\t// MAIR #1 (MEM_WBWA), inner shareable\n" +"\n" +".set .L_BLOCK_DEV, .L_TT_TYPE_BLOCK | .L_TT_MT_DEV | .L_TT_AF | .L_TT_XN\n" +".set .L_BLOCK_MEM, .L_TT_TYPE_BLOCK | .L_TT_MT_MEM | .L_TT_AF | .L_TT_NG\n" +"\n" +".section \".rodata.idmap\", \"a\", %progbits\n" +".global idmap\n" +".align 12\n" +"idmap:\n" +"\t/* level 1 */\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x0\t\t // 1 GiB of device mappings\n" +"\t.quad\t\t.L_BLOCK_MEM | 0x40000000\t// 1 GiB of DRAM\n" +"\t.fill\t\t254, 8, 0x0\t\t\t// 254 GiB of unmapped VA space\n" +"\t.quad\t\t.L_BLOCK_DEV | 0x4000000000 // 1 GiB of device mappings\n" +"\t.fill\t\t255, 8, 0x0\t\t\t// 255 GiB of remaining VA space\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:829 +#, fuzzy +msgid "`image.ld` (you shouldn't need to change this):" +msgstr "`image.ld` (non dovresti aver bisogno di cambiarlo):" + +#: src/exercises/bare-metal/rtc.md:831 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:833 +msgid "" +"```ld\n" +"/*\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" +" * https://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" +"\n" +"/*\n" +" * Code will start running at this symbol which is placed at the start of the\n" +" * image.\n" +" */\n" +"ENTRY(entry)\n" +"\n" +"MEMORY\n" +"{\n" +"\timage : ORIGIN = 0x40080000, LENGTH = 2M\n" +"}\n" +"\n" +"SECTIONS\n" +"{\n" +"\t/*\n" +"\t * Collect together the code.\n" +"\t */\n" +"\t.init : ALIGN(4096) {\n" +"\t\ttext_begin = .;\n" +"\t\t*(.init.entry)\n" +"\t\t*(.init.*)\n" +"\t} >image\n" +"\t.text : {\n" +"\t\t*(.text.*)\n" +"\t} >image\n" +"\ttext_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together read-only data.\n" +"\t */\n" +"\t.rodata : ALIGN(4096) {\n" +"\t\trodata_begin = .;\n" +"\t\t*(.rodata.*)\n" +"\t} >image\n" +"\t.got : {\n" +"\t\t*(.got)\n" +"\t} >image\n" +"\trodata_end = .;\n" +"\n" +"\t/*\n" +"\t * Collect together the read-write data including .bss at the end which\n" +"\t * will be zero'd by the entry code.\n" +"\t */\n" +"\t.data : ALIGN(4096) {\n" +"\t\tdata_begin = .;\n" +"\t\t*(.data.*)\n" +"\t\t/*\n" +"\t\t * The entry point code assumes that .data is a multiple of 32\n" +"\t\t * bytes long.\n" +"\t\t */\n" +"\t\t. = ALIGN(32);\n" +"\t\tdata_end = .;\n" +"\t} >image\n" +"\n" +"\t/* Everything beyond this point will not be included in the binary. */\n" +"\tbin_end = .;\n" +"\n" +"\t/* The entry point code assumes that .bss is 16-byte aligned. */\n" +"\t.bss : ALIGN(16) {\n" +"\t\tbss_begin = .;\n" +"\t\t*(.bss.*)\n" +"\t\t*(COMMON)\n" +"\t\t. = ALIGN(16);\n" +"\t\tbss_end = .;\n" +"\t} >image\n" +"\n" +"\t.stack (NOLOAD) : ALIGN(4096) {\n" +"\t\tboot_stack_begin = .;\n" +"\t\t. += 40 * 4096;\n" +"\t\t. = ALIGN(4096);\n" +"\t\tboot_stack_end = .;\n" +"\t} >image\n" +"\n" +"\t. = ALIGN(4K);\n" +"\tPROVIDE(dma_region = .);\n" +"\n" +"\t/*\n" +"\t * Remove unused sections from the image.\n" +"\t */\n" +"\t/DISCARD/ : {\n" +"\t\t/* The image loads itself so doesn't need these sections. */\n" +"\t\t*(.gnu.hash)\n" +"\t\t*(.hash)\n" +"\t\t*(.interp)\n" +"\t\t*(.eh_frame_hdr)\n" +"\t\t*(.eh_frame)\n" +"\t\t*(.note.gnu.build-id)\n" +"\t}\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:940 +#, fuzzy +msgid "`Makefile` (you shouldn't need to change this):" +msgstr "`Makefile` (non dovresti aver bisogno di cambiarlo):" + +#: src/exercises/bare-metal/rtc.md:942 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:944 +msgid "" +"```makefile\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" +"UNAME := $(shell uname -s)\n" +"ifeq ($(UNAME),Linux)\n" +"\tTARGET = aarch64-linux-gnu\n" +"else\n" +"\tTARGET = aarch64-none-elf\n" +"endif\n" +"OBJCOPY = $(TARGET)-objcopy\n" +"\n" +".PHONY: build qemu_minimal qemu qemu_logger\n" +"\n" +"all: rtc.bin\n" +"\n" +"build:\n" +"\tcargo build\n" +"\n" +"rtc.bin: build\n" +"\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 $< -s\n" +"\n" +"clean:\n" +"\tcargo clean\n" +"\trm -f *.bin\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:989 +msgid "" +"```toml\n" +"[build]\n" +"target = \"aarch64-unknown-none\"\n" +"rustflags = [\"-C\", \"link-arg=-Timage.ld\"]\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:995 +#, fuzzy +msgid "Run the code in QEMU with `make qemu`." +msgstr "Esegui il codice in QEMU con `make qemu`." + +#: src/concurrency.md:1 +#, fuzzy +msgid "# Welcome to Concurrency in Rust" +msgstr "Benvenuti a Comprehensive Rust 🦀" + +#: src/concurrency.md:3 +#, fuzzy +msgid "" +"Rust has full support for concurrency using OS threads with mutexes and\n" +"channels." +msgstr "" +"Rust ha il pieno supporto per la concorrenza utilizzando i thread del sistema operativo con mutex e\n" +"canali." + +#: 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 "" +"Il sistema di tipo Rust gioca un ruolo importante nella creazione di molti bug di concorrenza\n" +"bug in fase di compilazione. Questo è spesso indicato come _concorrenza senza paura_ da quando tu\n" +"può fare affidamento sul compilatore per garantire la correttezza in fase di esecuzione." + +#: src/concurrency/threads.md:1 +#, fuzzy +msgid "# Threads" +msgstr "# Discussioni" + +#: src/concurrency/threads.md:3 +#, fuzzy +msgid "Rust threads work similarly to threads in other languages:" +msgstr "I thread Rust funzionano in modo simile ai thread in altre lingue:" + +#: 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 "" +"* I thread sono tutti thread demoni, il thread principale non li aspetta.\n" +"* I thread panic sono indipendenti l'uno dall'altro.\n" +" * Panics può trasportare un payload, che può essere decompresso con `downcast_ref`." + +#: src/concurrency/threads.md:32 +#, fuzzy +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 "" +"* Si noti che il thread viene interrotto prima che raggiunga 10 — il thread principale lo è\n" +" non aspettare.\n" +"\n" +"* Usa `let handle = thread::spawn(...)` e successivamente `handle.join()` per aspettare\n" +" il filo per finire.\n" +"\n" +"* Attivare un panico nel thread, notare come questo non influisca su `main`.\n" +"\n" +"* Usa il valore di ritorno `Result` da `handle.join()` per ottenere l'accesso al panico\n" +" carico utile. Questo è un buon momento per parlare di [`Any`]." + +#: src/concurrency/scoped-threads.md:1 +#, fuzzy +msgid "# Scoped Threads" +msgstr "# Thread con ambito" + +#: src/concurrency/scoped-threads.md:3 +#, fuzzy +msgid "Normal threads cannot borrow from their environment:" +msgstr "I thread normali non possono prendere in prestito dal loro ambiente:" + +#: 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 "Tuttavia, puoi utilizzare un [thread con ambito][1] per questo:" + +#: 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 "" +"* La ragione di ciò è che quando la funzione `thread::scope` viene completata, è garantito che tutti i thread vengano uniti, in modo che possano " +"restituire dati presi in prestito.\n" +"* Si applicano le normali regole di prestito di Rust: puoi prendere in prestito in modo mutabile da un thread o immutabile da un numero qualsiasi di " +"thread.\n" +" " + +#: src/concurrency/channels.md:1 +#, fuzzy +msgid "# Channels" +msgstr "# Canali" + +#: 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 "" +"I canali Rust hanno due parti: un `Sender` e un `Receiver`. Le due parti\n" +"sono collegati tramite il canale, ma vedi solo i punti finali." + +#: 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` sta per Multi-Producer, Single-Consumer. `Sender` e `SyncSender` implementano `Clone` (quindi\n" +" puoi creare più produttori) ma `Receiver` no.\n" +"* `send()` e `recv()` restituiscono `Risultato`. Se restituiscono \"Err\", significa che la controparte \"Mittente\" o\n" +" `Receiver` viene eliminato e il canale viene chiuso." + +#: src/concurrency/channels/unbounded.md:1 +#, fuzzy +msgid "# Unbounded Channels" +msgstr "# Canali illimitati" + +#: src/concurrency/channels/unbounded.md:3 +#, fuzzy +msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" +msgstr "Ottieni un canale illimitato e asincrono con `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 "# Canali delimitati" + +#: src/concurrency/channels/bounded.md:3 +#, fuzzy +msgid "Bounded and synchronous channels make `send` block the current thread:" +msgstr "I canali limitati e sincroni fanno in modo che `send` blocchi il thread corrente:" + +#: 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 "# Stato condiviso" + +#: 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 utilizza il sistema dei tipi per imporre la sincronizzazione dei dati condivisi. Questo è\n" +"fatto principalmente tramite due tipi:" + +#: 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], riferimento atomico contato `T`: gestisce la condivisione tra thread e\n" +" si occupa di deallocare `T` quando viene eliminato l'ultimo riferimento,\n" +"* [`Mutex`][2]: garantisce l'accesso mutuamente esclusivo al valore `T`." + +#: src/concurrency/shared_state/arc.md:1 +#, fuzzy +msgid "# `Arc`" +msgstr "# `Arco`" + +#: src/concurrency/shared_state/arc.md:3 +#, fuzzy +msgid "[`Arc`][1] allows shared read-only access via `Arc::clone`:" +msgstr "[`Arc`][1] consente l'accesso condiviso in sola lettura tramite `Arc::clone`:" + +#: 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` sta per \"Atomic Reference Counted\", una versione thread-safe di `Rc` che usa atomic\n" +" operazioni.\n" +"* `Arc` implementa `Clone` indipendentemente dal fatto che `T` lo faccia. Implementa `Send` e `Sync` se e solo `T`\n" +" li implementa entrambi.\n" +"* `Arc::clone()` ha il costo delle operazioni atomiche che vengono eseguite, ma dopo ciò l'uso di\n" +" `T` è gratuito.\n" +"* Attenzione ai cicli di riferimento, `Arc` non usa un garbage collector per rilevarli.\n" +" * `std::sync::Weak` può aiutare." + +#: 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] garantisce l'esclusione reciproca _e_ consente l'accesso mutabile a `T`\n" +"dietro un'interfaccia di sola lettura:" + +#: 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 "" +"Nota come abbiamo una coperta [`impl Sync per Mutex`][2].\n" +"implementazione." + +#: 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 sembra una raccolta con un solo elemento: i dati protetti.\n" +" * Non è possibile dimenticare di acquisire il mutex prima di accedere ai dati protetti.\n" +"* Puoi ottenere un `&mut T` da un `&Mutex` prendendo il lock. Il `MutexGuard` assicura che il file\n" +" `&mut T` non sopravvive al blocco mantenuto.\n" +"* `Mutex` implementa sia `Send` che `Sync` se `T` implementa `Send`.\n" +"* Una controparte del blocco lettura-scrittura - `RwLock`.\n" +"* Perché `lock()` restituisce un `Risultato`?\n" +" * Se il thread che conteneva il `Mutex` va nel panico, il `Mutex` diventa \"avvelenato\" per segnalare che\n" +" i dati protetti potrebbero trovarsi in uno stato incoerente. Chiamare `lock()` su un mutex avvelenato\n" +" fallisce con un [`PoisonError`]. Puoi chiamare `into_inner()` sull'errore per recuperare i dati\n" +" indipendentemente." + +#: src/concurrency/shared_state/example.md:3 +#, fuzzy +msgid "Let us see `Arc` and `Mutex` in action:" +msgstr "Vediamo `Arc` e `Mutex` in azione:" + +#: 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 +#, fuzzy +msgid "Possible solution:" +msgstr "Possibile soluzione:" + +#: 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 +#, fuzzy +msgid "Notable parts:" +msgstr "Parti notevoli:" + +#: 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` è racchiuso sia in `Arc` che in `Mutex`, perché i loro interessi sono ortogonali.\n" +" * Avvolgere un `Mutex` in un `Arc` è un modello comune per condividere lo stato mutabile tra i thread.\n" +"* `v: Arc<_>` deve essere clonato come `v2` prima di poter essere spostato in un altro thread. Nota che \"move\" è stato aggiunto alla firma " +"lambda.\n" +"* I blocchi vengono introdotti per restringere il più possibile l'ambito di `LockGuard`." + +#: src/concurrency/send-sync.md:1 +#, fuzzy +msgid "# `Send` and `Sync`" +msgstr "# `Invia` e `Sincronizza`" + +#: 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 "Come fa Rust a sapere di vietare l'accesso condiviso attraverso il thread? La risposta è in due tratti:" + +#: 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]: un tipo `T` è `Send` se è sicuro spostare una `T` attraverso un thread\n" +" confine.\n" +"* [`Sync`][2]: un tipo `T` è `Sync` se è sicuro spostare una `&T` attraverso un thread\n" +" confine." + +#: 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 "" +"\"Send\" e \"Sync\" sono [tratti non sicuri][3]. Il compilatore li deriverà automaticamente per i tuoi tipi\n" +"purché contengano solo i tipi \"Send\" e \"Sync\". Puoi anche implementarli manualmente quando tu\n" +"sapere che è valido." + +#: 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 "" +"* Si può pensare a questi tratti come indicatori che il tipo ha determinate proprietà di sicurezza del thread.\n" +"* Possono essere usati nei vincoli generici come tratti normali.\n" +" " + +#: src/concurrency/send-sync/send.md:1 +#, fuzzy +msgid "# `Send`" +msgstr "# `Invia`" + +#: 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 "> Un tipo `T` è [`Send`][1] se è sicuro spostare un valore `T` in un altro thread." + +#: 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 "" +"L'effetto dello spostamento della proprietà su un altro thread è che i _destructors_ verranno eseguiti\n" +"in quel filo. Quindi la domanda è quando puoi allocare un valore in un thread\n" +"e deallocarlo in un altro." + +#: src/concurrency/send-sync/sync.md:1 +#, fuzzy +msgid "# `Sync`" +msgstr "# `Sincronizza`" + +#: 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 "" +"> Un tipo `T` è [`Sync`][1] se è sicuro accedere a un valore `T` da più\n" +"> thread contemporaneamente." + +#: src/concurrency/send-sync/sync.md:6 +#, fuzzy +msgid "More precisely, the definition is:" +msgstr "Più precisamente la definizione è:" + +#: src/concurrency/send-sync/sync.md:8 +#, fuzzy +msgid "> `T` is `Sync` if and only if `&T` is `Send`" +msgstr "> `T` è `Sync` se e solo se `&T` è `Send`" + +#: 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 "" +"Questa affermazione è essenzialmente un modo abbreviato per dire che se un tipo è thread-safe per l'uso condiviso, è anche thread-safe per passarne " +"i riferimenti attraverso i thread." + +#: 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 "" +"Questo perché se un tipo è Sync significa che può essere condiviso tra più thread senza il rischio di corse di dati o altri problemi di " +"sincronizzazione, quindi è sicuro spostarlo su un altro thread. Un riferimento al tipo è anche sicuro da spostare in un altro thread, perché è " +"possibile accedere ai dati a cui fa riferimento da qualsiasi thread in modo sicuro." + +#: src/concurrency/send-sync/examples.md:1 +#, fuzzy +msgid "# Examples" +msgstr "# Esempi" + +#: src/concurrency/send-sync/examples.md:3 +#, fuzzy +msgid "## `Send + Sync`" +msgstr "## \"Invia + Sincronizza\"." + +#: src/concurrency/send-sync/examples.md:5 +#, fuzzy +msgid "Most types you come across are `Send + Sync`:" +msgstr "La maggior parte dei tipi che incontri sono \"Invia + sincronizzazione\":" + +#: 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 "" +"I tipi generici sono in genere \"Send + Sync\" quando i parametri di tipo lo sono\n" +"\"Invia + Sincronizza\"." + +#: src/concurrency/send-sync/examples.md:17 +#, fuzzy +msgid "## `Send + !Sync`" +msgstr "## \"Invia + !Sincronizza\"." + +#: 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 "" +"Questi tipi possono essere spostati in altri thread, ma non sono thread-safe.\n" +"Tipicamente a causa della mutevolezza interna:" + +#: src/concurrency/send-sync/examples.md:22 +#, fuzzy +msgid "" +"* `mpsc::Sender`\n" +"* `mpsc::Receiver`\n" +"* `Cell`\n" +"* `RefCell`" +msgstr "" +"* `mpsc::Sender`\n" +"* `mpsc::Ricevitore`\n" +"* `Cella`\n" +"* `RefCella`" + +#: src/concurrency/send-sync/examples.md:27 +#, fuzzy +msgid "## `!Send + Sync`" +msgstr "## `!Invia + Sincronizza`" + +#: src/concurrency/send-sync/examples.md:29 +#, fuzzy +msgid "These types are thread-safe, but they cannot be moved to another thread:" +msgstr "Questi tipi sono thread-safe, ma non possono essere spostati in un altro thread:" + +#: 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`: utilizza primitive a livello di sistema operativo che devono essere deallocate su\n" +" thread che li ha creati." + +#: src/concurrency/send-sync/examples.md:34 +#, fuzzy +msgid "## `!Send + !Sync`" +msgstr "## `!Invia + !Sync`" + +#: src/concurrency/send-sync/examples.md:36 +#, fuzzy +msgid "These types are not thread-safe and cannot be moved to other threads:" +msgstr "Questi tipi non sono thread-safe e non possono essere spostati in altri thread:" + +#: 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`: ogni `Rc` ha un riferimento a un `RcBox`, che contiene un\n" +" conteggio dei riferimenti non atomici.\n" +"* `*const T`, `*mut T`: Rust presuppone che i puntatori grezzi possano avere caratteri speciali\n" +" considerazioni sulla concorrenza" + +#: src/exercises/concurrency/morning.md:3 +#, fuzzy +msgid "Let us practice our new concurrency skills with" +msgstr "Mettiamo in pratica le nostre nuove abilità di concorrenza con" + +#: 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 "" +"* Filosofi a tavola: un classico problema in concorrenza.\n" +"\n" +"* Verifica link multi-thread: un progetto più ampio in cui utilizzerai Cargo\n" +" scaricare le dipendenze e quindi controllare i collegamenti in parallelo." + +#: src/exercises/concurrency/dining-philosophers.md:1 +#, fuzzy +msgid "# Dining Philosophers" +msgstr "# Filosofi da pranzo" + +#: src/exercises/concurrency/dining-philosophers.md:3 +#, fuzzy +msgid "The dining philosophers problem is a classic problem in concurrency:" +msgstr "Il problema dei filosofi da pranzo è un classico problema in concorrenza:" + +#: 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 "" +"> Cinque filosofi cenano insieme alla stessa tavola. Ogni filosofo ha il suo\n" +"> proprio posto a tavola. C'è una forchetta tra ogni piatto. Il piatto servito è\n" +"> una specie di spaghetto che si mangia con due forchette. Ogni filosofo può\n" +"> solo alternativamente pensa e mangia. Inoltre, un filosofo può solo mangiare il loro\n" +"> gli spaghetti quando hanno sia la forchetta destra che quella sinistra. Quindi solo due forchette\n" +"> essere disponibile quando i loro due vicini più vicini stanno pensando, non mangiando. Dopo\n" +"> un singolo filosofo finisce di mangiare, metteranno giù entrambe le forchette." + +#: 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 "" +"Avrai bisogno di un'[installazione Cargo](../../cargo/running-locally.md) locale per\n" +"questo esercizio. Copia il codice qui sotto in un file chiamato `src/main.rs`, compila il file\n" +"spazi vuoti e verificare che `cargo run` non vada in stallo:" + +#: 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 +#, fuzzy +msgid "You can use the following `Cargo.toml`:" +msgstr "Puoi usare il seguente `Cargo.toml`:" + +#: 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 "# Verifica link multi-thread" + +#: 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 "" +"Usiamo le nostre nuove conoscenze per creare un verificatore di collegamenti multi-thread. Dovrebbe\n" +"iniziare da una pagina Web e verificare che i collegamenti sulla pagina siano validi. Dovrebbe\n" +"controlla ricorsivamente altre pagine sullo stesso dominio e continua a farlo fino a quando all\n" +"le pagine sono state convalidate." + +#: 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 "" +"Per questo, avrai bisogno di un client HTTP come [`reqwest`][1]. Crea un nuovo\n" +"Progetto Cargo e `richiedilo` come dipendenza con:" + +#: 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 "" +"> Se `cargo add` fallisce con `error: no such subcommand`, modifica il file\n" +"> File `Cargo.toml` a mano. Aggiungere le dipendenze elencate di seguito." + +#: 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 "Avrai anche bisogno di un modo per trovare i link. Possiamo usare [`scraper`][2] per questo:" + +#: 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 "" +"Infine, avremo bisogno di un modo per gestire gli errori. Usiamo [`thiserror`][3] per\n" +"Quello:" + +#: 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 "Le chiamate `cargo add` aggiorneranno il file `Cargo.toml` in questo modo:" + +#: 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 "" +"Ora puoi scaricare la pagina iniziale. Prova con un piccolo sito come\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 "Il tuo file `src/main.rs` dovrebbe assomigliare a questo:" + +#: 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 "Esegui il codice in `src/main.rs` con" + +#: src/exercises/concurrency/link-checker.md:102 +msgid "" +"```shell\n" +"$ cargo run\n" +"```" +msgstr "" + +#: src/exercises/concurrency/link-checker.md:106 +#, fuzzy +msgid "## Tasks" +msgstr "## Compiti" + +#: 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 "" +"* Usa i thread per controllare i collegamenti in parallelo: invia gli URL da controllare a a\n" +" channel e lasciare che alcuni thread controllino gli URL in parallelo.\n" +"* Estendilo per estrarre in modo ricorsivo i collegamenti da tutte le pagine del file\n" +" dominio \"www.google.org\". Metti un limite massimo di 100 pagine o giù di lì in modo che tu\n" +" non finire per essere bloccato dal sito." + +#: src/async.md:1 +#, fuzzy +msgid "# Async Rust" +msgstr "# Ruggine asincrona" + +#: src/async.md:3 +#, fuzzy +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 "" +"\"Async\" è un modello di concorrenza in cui più attività vengono eseguite contemporaneamente da\n" +"eseguire ogni attività fino a quando non si bloccherebbe, quindi passare a un'altra attività che è\n" +"pronto a fare progressi. Il modello consente di eseguire un numero maggiore di attività su a\n" +"numero limitato di thread. Questo perché il sovraccarico per attività è in genere\n" +"molto basso e i sistemi operativi forniscono primitive per l'identificazione efficiente\n" +"I/O che è in grado di procedere." + +#: src/async.md:10 +#, fuzzy +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 "" +"L'operazione asincrona di Rust si basa sui \"futuri\", che rappresentano il lavoro che\n" +"potrebbe essere completata in futuro. I futures vengono \"interrogati\" fino a quando non lo segnalano\n" +"sono completi." + +#: src/async.md:14 +#, fuzzy +msgid "" +"Futures are polled by an async runtime, and several different runtimes are\n" +"available." +msgstr "" +"I futures vengono interrogati da un runtime asincrono e diversi runtime lo sono\n" +"disponibile." + +#: src/async.md:17 +#, fuzzy +msgid "## Comparisons" +msgstr "Comparazione" + +#: src/async.md:19 +#, fuzzy +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 "" +" * Python ha un modello simile nel suo `asyncio`. Tuttavia, il suo tipo \"Futuro\" è\n" +" basato su callback e non su polling. I programmi Python asincroni richiedono un \"loop\",\n" +" simile a un runtime in Rust.\n" +"\n" +" * La \"promessa\" di JavaScript è simile, ma ancora una volta basata su callback. La lingua\n" +" runtime implementa il ciclo di eventi, tanti dei dettagli di Promise\n" +" risoluzione sono nascosti." + +#: src/async/async-await.md:1 +#, fuzzy +msgid "# `async`/`await`" +msgstr "# `asincrono`/`aspetta`" + +#: src/async/async-await.md:3 +#, fuzzy +msgid "At a high level, async Rust code looks very much like \"normal\" sequential code:" +msgstr "Ad alto livello, il codice asincrono di Rust assomiglia molto al codice sequenziale \"normale\":" + +#: 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 "# Futuri" + +#: src/async/futures.md:3 +#, fuzzy +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 "" +"[`Futuro`](https://doc.rust-lang.org/std/future/trait.Future.html)\n" +"è un tratto, implementato da oggetti che rappresentano un'operazione che potrebbe non essere\n" +"ancora completo. È possibile eseguire il polling di un futuro e `poll` restituisce a\n" +"[`Sondaggio`](https://doc.rust-lang.org/std/task/enum.Poll.html)." + +#: 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 +#, fuzzy +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 "" +"Una funzione asincrona restituisce un `impl Future`. È anche possibile (ma non comune).\n" +"implementa `Future` per i tuoi tipi. Ad esempio, è stato restituito \"JoinHandle\".\n" +"da `tokio::spawn` implementa `Future` per consentire l'unione ad esso." + +#: src/async/futures.md:27 +#, fuzzy +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 "" +"La parola chiave `.await`, applicata a un Future, fa sì che la funzione async corrente si attivi\n" +"mettere in pausa fino a quando Future non è pronto, quindi valuta il suo output." + +#: 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 "# Runtime" + +#: src/async/runtimes.md:3 +#, fuzzy +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 "" +"Un *runtime* fornisce supporto per l'esecuzione di operazioni in modo asincrono (a\n" +"*reattore*) ed è responsabile dell'esecuzione dei futures (un *esecutore*). La ruggine non ha un\n" +"runtime \"incorporato\", ma sono disponibili diverse opzioni:" + +#: src/async/runtimes.md:7 +#, fuzzy +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 "" +" * [Tokio](https://tokio.rs/) - performante, con un ecosistema ben sviluppato di\n" +" funzionalità come [Hyper](https://hyper.rs/) per HTTP o\n" +" [Tonic](https://github.com/hyperium/tonic) per gRPC.\n" +" * [async-std](https://async.rs/) - mira a essere uno \"std per async\" e include un\n" +" runtime di base in `async::task`.\n" +" * [smol](https://docs.rs/smol/latest/smol/) - semplice e leggero" + +#: src/async/runtimes.md:14 +#, fuzzy +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 "" +"Diverse applicazioni più grandi hanno i propri tempi di esecuzione. Per esempio,\n" +"[Fucsia](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/lib/fuchsia-async/src/lib.rs)\n" +"ne ha già uno." + +#: src/async/runtimes.md:20 +#, fuzzy +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 "" +"* Si noti che dei runtime elencati, solo Tokio è supportato in Rust\n" +" terreno di gioco. Anche il parco giochi non consente alcun I/O, quindi molto interessante\n" +" le cose asincrone non possono essere eseguite nel parco giochi.\n" +"\n" +"* I futures sono \"inerti\" in quanto non fanno nulla (nemmeno avviano un I/O\n" +" operazione) a meno che non ci sia un esecutore che li interroga. Questo differisce da JS\n" +" Promesse, ad esempio, che andranno a buon fine anche se non lo saranno mai\n" +" usato." + +#: src/async/runtimes/tokio.md:1 +#, fuzzy +msgid "# Tokio" +msgstr "# Tokyo" + +#: src/async/runtimes/tokio.md:4 +#, fuzzy +msgid "Tokio provides: " +msgstr "Tokyo fornisce:" + +#: src/async/runtimes/tokio.md:6 +#, fuzzy +msgid "" +"* A multi-threaded runtime for executing asynchronous code.\n" +"* An asynchronous version of the standard library.\n" +"* A large ecosystem of libraries." +msgstr "" +"* Un runtime multithread per l'esecuzione di codice asincrono.\n" +"* Una versione asincrona della libreria standard.\n" +"* Un grande ecosistema di biblioteche." + +#: 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 +#, fuzzy +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 "" +"* Con la macro `tokio::main` ora possiamo rendere `main` asincrono.\n" +"\n" +"* La funzione `spawn` crea un nuovo \"task\" simultaneo.\n" +"\n" +"* Nota: `spawn` prende un `Future`, non devi chiamare `.await` su `count_to`." + +#: src/async/runtimes/tokio.md:39 +#, fuzzy +msgid "**Further exploration:**" +msgstr "**Ulteriori esplorazioni:**" + +#: src/async/runtimes/tokio.md:41 +#, fuzzy +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 "" +"* Perché `count_to` non arriva (di solito) a 10? Questo è un esempio di async\n" +" cancellazione. `tokio::spawn` restituisce un handle che può essere atteso per attendere\n" +" finché non finisce.\n" +"\n" +"* Prova `count_to(10).await` invece di spawnare.\n" +"\n" +"* Prova ad attendere il task restituito da `tokio::spawn`." + +#: src/async/tasks.md:1 +#, fuzzy +msgid "# Tasks" +msgstr "# Compiti" + +#: src/async/tasks.md:3 +#, fuzzy +msgid "" +"Runtimes have the concept of a \"task\", similar to a thread but much\n" +"less resource-intensive." +msgstr "" +"I runtime hanno il concetto di \"attività\", simile a un thread ma molto\n" +"meno dispendioso in termini di risorse." + +#: src/async/tasks.md:6 +#, fuzzy +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 "" +"Un'attività ha un singolo futuro di primo livello che l'esecutore interroga per fare progressi.\n" +"Quel futuro può avere uno o più futuri nidificati che il suo metodo \"poll\" esegue il polling,\n" +"corrispondente vagamente a uno stack di chiamate. La concorrenza all'interno di un'attività è possibile tramite\n" +"polling di più futuri figli, come correre un timer e un'operazione di I/O." + +#: 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 +#, fuzzy +msgid "Copy this example into your prepared `src/main.rs` and run it from there." +msgstr "Copia questo esempio nel tuo `src/main.rs` preparato ed eseguilo da lì." + +#: src/async/tasks.md:55 +#, fuzzy +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 "" +"* Chiedi agli studenti di visualizzare quale sarebbe lo stato del server di esempio con a\n" +" pochi client connessi. Quali compiti esistono? Quali sono i loro futuri?\n" +"\n" +"* Questa è la prima volta che vediamo un blocco `async`. Questo è simile a a\n" +" chiusura, ma non accetta argomenti. Il suo valore di ritorno è un Futuro,\n" +" simile a un `async fn`.\n" +"\n" +"* Rifattorizzare il blocco asincrono in una funzione e migliorare la gestione degli errori utilizzando `?`." + +#: src/async/channels.md:1 +#, fuzzy +msgid "# Async Channels" +msgstr "# Canali asincroni" + +#: src/async/channels.md:3 +#, fuzzy +msgid "Several crates have support for `async`/`await`. For instance `tokio` channels:" +msgstr "Diversi crate hanno il supporto per `async`/`await`. Ad esempio i canali `tokio`:" + +#: 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 +#, fuzzy +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 "" +"* Cambia la dimensione del canale in \"3\" e guarda come influisce sull'esecuzione.\n" +"\n" +"* Nel complesso, l'interfaccia è simile ai canali `sync` come si vede nel file\n" +" [lezione mattutina](concurrency/channels.md).\n" +"\n" +"* Prova a rimuovere la chiamata `std::mem::drop`. Che succede? Perché?\n" +"\n" +"* La cassa [Flume](https://docs.rs/flume/latest/flume/) ha canali che\n" +" implementa sia `sync` che `async` `send` e `recv`. Questo può essere conveniente\n" +" per applicazioni complesse con attività di elaborazione di CPU e IO pesanti.\n" +"\n" +"* Ciò che rende preferibile lavorare con i canali `async` è la capacità di combinare\n" +" loro con altri `futuri` per combinarli e creare un flusso di controllo complesso." + +#: src/async/control-flow.md:1 +#, fuzzy +msgid "# Futures Control Flow" +msgstr "# Flusso di controllo dei futures" + +#: src/async/control-flow.md:3 +#, fuzzy +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 "" +"I futures possono essere combinati insieme per produrre grafici di flusso di calcolo simultanei. Noi\n" +"ho già visto le attività, che funzionano come thread di esecuzione indipendenti." + +#: src/async/control-flow.md:6 +#, fuzzy +msgid "" +"- [Join](control-flow/join.md)\n" +"- [Select](control-flow/select.md)" +msgstr "" +"- [Partecipa](control-flow/join.md)\n" +"- [Seleziona](control-flow/select.md)" + +#: src/async/control-flow/join.md:1 +#, fuzzy +msgid "# Join" +msgstr "# Giuntura" + +#: src/async/control-flow/join.md:3 +#, fuzzy +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 "" +"Un'operazione di join attende fino a quando tutti i futures sono pronti e\n" +"restituisce una raccolta dei loro risultati. Questo è simile a \"Promise.all\" in\n" +"JavaScript o `asyncio.gather` in Python." + +#: 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 +#, fuzzy +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 "" +"* Per future multiple di tipi disgiunti, puoi usare `std::future::join!` ma\n" +" devi sapere quanti futuri avrai al momento della compilazione. Questo è\n" +" attualmente nella cassa `futures`, presto sarà stabilizzata in `std::future`.\n" +"\n" +"* Il rischio di \"unirsi\" è che uno dei futuri potrebbe non risolversi mai, questo sì\n" +" causare l'arresto del programma.\n" +"\n" +"* Puoi anche combinare `join_all` con `join!`, ad esempio per unire tutte le richieste\n" +" a un servizio http così come una query di database. Prova ad aggiungere un\n" +" `tokio::time::sleep` nel futuro, usando `futures::join!`. Questo non è un\n" +" timeout (che richiede `select!`, spiegato nel prossimo capitolo), ma dimostra `join!`." + +#: src/async/control-flow/select.md:1 +#, fuzzy +msgid "# Select" +msgstr "# Selezionare" + +#: src/async/control-flow/select.md:3 +#, fuzzy +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 "" +"Un'operazione di selezione attende fino a quando uno qualsiasi di un insieme di futures è pronto e risponde a\n" +"il risultato di quel futuro. In JavaScript, è simile a `Promise.race`. In\n" +"Python, confronta con `asyncio.wait(task_set,\n" +"return_when=asyncio.FIRST_COMPLETED)`." + +#: src/async/control-flow/select.md:8 +#, fuzzy +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 "" +"Di solito è una macro, simile a match, con ogni braccio della forma `pattern =\n" +"futuro => istruzione`. Quando il futuro è pronto, l'istruzione viene eseguita con il\n" +"variabile legata al risultato del futuro." + +#: 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 +#, fuzzy +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 "" +"* In questo esempio, abbiamo una gara tra un gatto e un cane.\n" +" `first_animal_to_finish_race` ascolta entrambi i canali e sceglierà quello che preferisci\n" +" arriva prima. Poiché il cane impiega 50 ms, vince contro il gatto\n" +" prendere 500 ms secondi.\n" +"\n" +"* In questo esempio puoi usare i canali `oneshot` come dovrebbero\n" +" ricevere un solo \"invio\".\n" +"\n" +"* Prova ad aggiungere una scadenza alla gara, dimostrando la selezione di diversi tipi di\n" +" futuri.\n" +"\n" +"* Nota che `select!` sposta i valori che gli vengono dati. È più facile da usare\n" +" quando ogni esecuzione di `select!` crea nuovi futuri. Un'alternativa è\n" +" passa `&mut future` invece del futuro stesso, ma questo può portare a\n" +" problemi, ulteriormente discussi nella diapositiva di blocco." + +#: src/async/pitfalls.md:1 +#, fuzzy +msgid "# Pitfalls of async/await" +msgstr "# Insidie di async/await" + +#: src/async/pitfalls.md:3 +#, fuzzy +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 "" +"Async / await fornisce un'astrazione comoda ed efficiente per la programmazione asincrona simultanea. Tuttavia, anche il modello async/await in Rust " +"ha la sua parte di insidie e pistole. Ne illustriamo alcuni in questo capitolo:" + +#: src/async/pitfalls.md:5 +#, fuzzy +msgid "" +"- [Blocking the Executor](pitfalls/blocking-executor.md)\n" +"- [Pin](pitfalls/pin.md)\n" +"- [Async Traits](pitfall/async-traits.md)" +msgstr "" +"- [Blocco dell'esecutore](trappole/blocking-executor.md)\n" +"- [Pin](trappole/pin.md)\n" +"- [Tratti asincroni](trapano/async-traits.md)" + +#: src/async/pitfalls/blocking-executor.md:1 +#, fuzzy +msgid "# Blocking the executor" +msgstr "# Blocco dell'esecutore" + +#: src/async/pitfalls/blocking-executor.md:3 +#, fuzzy +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 "" +"La maggior parte dei runtime asincroni consente solo l'esecuzione simultanea delle attività di I/O.\n" +"Ciò significa che le attività di blocco della CPU bloccheranno l'esecutore e impediranno l'esecuzione di altre attività.\n" +"Una soluzione semplice consiste nell'usare metodi equivalenti asincroni ove possibile." + +#: 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 +#, fuzzy +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 "" +"* Esegui il codice e verifica che le interruzioni avvengano consecutivamente anziché\n" +" in concomitanza.\n" +"\n" +"* Il profilo `\"current_thread\"` pone tutte le attività su un singolo thread. Questo rende il\n" +" effetto più evidente, ma il bug è ancora presente nel multithread\n" +" gusto.\n" +"\n" +"* Passa da `std::thread::sleep` a `tokio::time::sleep` e attendi il risultato.\n" +"\n" +"* Un'altra soluzione potrebbe essere `tokio::task::spawn_blocking` che genera un file effettivo\n" +" thread e trasforma il suo handle in un futuro senza bloccare l'esecutore.\n" +"\n" +"* Non dovresti pensare alle attività come thread del sistema operativo. Non mappano 1 a 1 e la maggior parte\n" +" gli esecutori consentiranno l'esecuzione di molte attività su un singolo thread del sistema operativo. Questo è\n" +" particolarmente problematico quando si interagisce con altre biblioteche tramite FFI, dove\n" +" quella libreria potrebbe dipendere dall'archiviazione locale del thread o essere mappata su un sistema operativo specifico\n" +" thread (ad esempio, CUDA). Preferisci `tokio::task::spawn_blocking` in tali situazioni.\n" +"\n" +"* Usa i mutex di sincronizzazione con attenzione. Mantenere un mutex sopra un `.await` può causarne un altro\n" +" attività da bloccare e tale attività potrebbe essere in esecuzione sullo stesso thread." + +#: src/async/pitfalls/pin.md:1 +#, fuzzy +msgid "# Pin" +msgstr "# Spillo" + +#: src/async/pitfalls/pin.md:3 +#, fuzzy +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 "" +"Quando aspetti un futuro, tutte le variabili locali (che normalmente sarebbero memorizzate su\n" +"uno stack frame) vengono invece archiviati in Future per il blocco asincrono corrente. Se tuo\n" +"future ha puntatori ai dati nello stack, quei puntatori potrebbero essere invalidati.\n" +"Questo non è sicuro." + +#: src/async/pitfalls/pin.md:8 +#, fuzzy +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 "" +"Pertanto, è necessario garantire che gli indirizzi futuri puntino a non farlo\n" +"modifica. Ecco perché dobbiamo \"bloccare\" i futuri. Usando ripetutamente lo stesso futuro\n" +"in un `select!` spesso porta a problemi con i valori bloccati." + +#: 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 "# Tratti asincroni" + +#: src/async/pitfalls/async-traits.md:3 +#, fuzzy +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 "" +"I metodi asincroni nei tratti non sono ancora supportati nel canale stabile ([Esiste una funzionalità sperimentale in nightly e dovrebbe essere " +"stabilizzata a medio termine.](https://blog.rust-lang.org/inside-rust/2022/11 /17/async-fn-in-trait-nightly.html))" + +#: src/async/pitfalls/async-traits.md:5 +#, fuzzy +msgid "The crate [async_trait](https://docs.rs/async-trait/latest/async_trait/) provides a workaround through a macro:" +msgstr "Il crate [async_trait](https://docs.rs/async-trait/latest/async_trait/) fornisce una soluzione tramite una macro:" + +#: 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 +#, fuzzy +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 "" +"* `async_trait` è facile da usare, ma si noti che utilizza allocazioni di heap per\n" +" raggiungere questo obiettivo. Questa allocazione dell'heap comporta un sovraccarico delle prestazioni.\n" +"\n" +"* Le sfide nel supporto del linguaggio per `async trait` sono il profondo Rust e\n" +" probabilmente non vale la pena descriverlo in modo approfondito. Niko Matsakis ha fatto un buon lavoro\n" +" spiegandoli in [questo\n" +" post](https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/)\n" +" se sei interessato a scavare più a fondo.\n" +"\n" +"* Prova a creare una nuova struttura dormiente che dormirà per un periodo di tempo casuale\n" +" e aggiungendolo al Vec." + +#: src/exercises/concurrency/elevator.md:1 +#, fuzzy +msgid "# Elevator Operation" +msgstr "# Funzionamento dell'ascensore" + +#: src/exercises/concurrency/elevator.md:3 +#, fuzzy +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 "" +"Gli ascensori sembrano semplici. Premi un pulsante, le porte si aprono, aspetti e sei a\n" +"il pavimento che hai richiesto. Ma l'implementazione di un controller per ascensori è sorprendente\n" +"difficile! Questo esercizio prevede la costruzione di un semplice controllo dell'ascensore\n" +"opera in un semplice simulatore." + +#: src/exercises/concurrency/elevator.md:8 +#, fuzzy +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 "" +"Il progetto complessivo di questo ascensore utilizza il modello dell'attore: implementerai a\n" +"attività del controller che comunica con altri componenti del sistema di ascensori\n" +"inviando e ricevendo messaggi." + +#: src/exercises/concurrency/elevator.md:12 +#, fuzzy +msgid "## Getting Started" +msgstr "## Iniziare" + +#: src/exercises/concurrency/elevator.md:14 +#, fuzzy +msgid "" +"Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the `elevator`\n" +"directory for the following files." +msgstr "" +"Scarica il [modello di esercizio](../../comprehensive-rust-exercises.zip) e guarda nell'\"ascensore\"\n" +"directory per i seguenti file." + +#: src/exercises/concurrency/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/concurrency/elevator.md:47 +#, fuzzy +msgid "`src/building.rs`:" +msgstr "`src/edificio.rs`:" + +#: src/exercises/concurrency/elevator.md:49 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/concurrency/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/concurrency/elevator.md:288 +#, fuzzy +msgid "`src/driver.rs`:" +msgstr "`src/driver.rs`:" + +#: src/exercises/concurrency/elevator.md:290 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/concurrency/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/concurrency/elevator.md:330 +#, fuzzy +msgid "`src/controller.rs`:" +msgstr "`src/controllore.rs`:" + +#: src/exercises/concurrency/elevator.md:332 +#, fuzzy +msgid "" +msgstr "" + +#: src/exercises/concurrency/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/concurrency/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/concurrency/elevator.md:381 +#, fuzzy +msgid "Use `cargo run` to run the elevator simulation." +msgstr "Usa `cargo run` per eseguire la simulazione dell'ascensore." + +#: src/exercises/concurrency/elevator.md:383 +#, fuzzy +msgid "## Exercises" +msgstr "Esercizi" + +#: src/exercises/concurrency/elevator.md:385 +#, fuzzy +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 "" +"Inizia implementando un controller in grado di trasportare i passeggeri forniti da\n" +"il semplice conducente. C'è solo un ascensore e i passeggeri vanno sempre da\n" +"piano 0 al piano 2, uno per uno." + +#: src/exercises/concurrency/elevator.md:389 +#, fuzzy +msgid "Once you have this done, make the problem more complex. Suggested tasks:" +msgstr "Una volta fatto ciò, rendi il problema più complesso. Compiti suggeriti:" + +#: src/exercises/concurrency/elevator.md:391 +#, fuzzy +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 "" +" * Rendi il conducente più complesso, con i passeggeri che arrivano a piani casuali\n" +" destinazioni casuali in orari casuali.\n" +"\n" +" * Crea un edificio con più di un ascensore e regola il controller su\n" +" gestirlo in modo efficiente.\n" +"\n" +" * Aggiungi ulteriori eventi e metadati per analizzare l'efficienza del tuo controller.\n" +" Qual è la distribuzione del tempo di attesa per i passeggeri? Il risultato è giusto?\n" +"\n" +" * Modificare l'edificio per supportare una capacità massima di passeggeri per ciascuno\n" +" elevatore e modificare il controller per tenere conto di queste informazioni.\n" +"\n" +" * Aggiorna il conducente per simulare il traffico aziendale, con molti passeggeri in viaggio\n" +" dal piano terra allo stesso tempo, e quei passeggeri che tornano a\n" +" il piano terra qualche tempo dopo. Il tuo controller può adattarsi a questi\n" +" circostanze?\n" +"\n" +" * Modificare l'edificio per supportare la \"spedizione di destinazione\", dove i passeggeri\n" +" segnala il piano di destinazione nella hall dell'ascensore, prima di salire a bordo\n" +" ascensore.\n" +"\n" +" * Se stai frequentando il corso con altri studenti, controllori commerciali o\n" +" driver con un altro studente per vedere quanto è robusto il tuo progetto.\n" +"\n" +" * Costruisci una visualizzazione testuale o grafica degli ascensori mentre corrono." + +#: src/thanks.md:1 +#, fuzzy +msgid "# Thanks!" +msgstr "# Grazie!" + +#: src/thanks.md:3 +#, fuzzy +msgid "" +"_Thank you for taking Comprehensive Rust 🦀!_ We hope you enjoyed it and that it\n" +"was useful." +msgstr "" +"_Grazie per aver preso Comprehensive Rust 🦀!_ Ci auguriamo che ti sia piaciuto e che sia così\n" +"è stato utile." + +#: 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 "" +"Ci siamo divertiti molto a mettere insieme il corso. Il corso non è perfetto,\n" +"quindi se hai individuato errori o hai idee per miglioramenti, entra\n" +"[contattaci su\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Ci piacerebbe\n" +"avere tue notizie." + +#: src/other-resources.md:1 +#, fuzzy +msgid "# Other Rust Resources" +msgstr "# Altre risorse di ruggine" + +#: src/other-resources.md:3 +#, fuzzy +msgid "" +"The Rust community has created a wealth of high-quality and free resources\n" +"online." +msgstr "" +"La community di Rust ha creato una vasta gamma di risorse gratuite e di alta qualità\n" +"in linea." + +#: src/other-resources.md:6 +#, fuzzy +msgid "## Official Documentation" +msgstr "## Documentazione ufficiale" + +#: src/other-resources.md:8 +#, fuzzy +msgid "The Rust project hosts many resources. These cover Rust in general:" +msgstr "Il progetto Rust ospita molte risorse. Questi coprono Rust in generale:" + +#: 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 "" +"* [Il linguaggio di programmazione Rust](https://doc.rust-lang.org/book/): the\n" +" canonico libro gratuito su Rust. Copre la lingua in dettaglio e include a\n" +" pochi progetti da costruire per le persone.\n" +"* [Ruggine per esempio](https://doc.rust-lang.org/rust-by-example/): copre la Ruggine\n" +" sintassi attraverso una serie di esempi che mostrano diversi costrutti. A volte\n" +" include piccoli esercizi in cui ti viene chiesto di espandere il codice nel file\n" +" esempi.\n" +"* [Rust Standard Library](https://doc.rust-lang.org/std/): documentazione completa di\n" +" la libreria standard per Rust.\n" +"* [The Rust Reference](https://doc.rust-lang.org/reference/): un libro incompleto\n" +" che descrive la grammatica e il modello di memoria di Rust." + +#: src/other-resources.md:22 +#, fuzzy +msgid "More specialized guides hosted on the official Rust site:" +msgstr "Guide più specializzate ospitate sul sito ufficiale di Rust:" + +#: 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/): copre Rust non sicuro,\n" +" compreso il lavoro con puntatori grezzi e l'interfacciamento con altre lingue\n" +" (FFI).\n" +"* [Programmazione asincrona in Rust](https://rust-lang.github.io/async-book/):\n" +" copre il nuovo modello di programmazione asincrona che è stato introdotto dopo il\n" +" Rust Book è stato scritto.\n" +"* [The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/): an\n" +" introduzione all'utilizzo di Rust su dispositivi embedded senza sistema operativo." + +#: src/other-resources.md:33 +#, fuzzy +msgid "## Unofficial Learning Material" +msgstr "## Materiale didattico non ufficiale" + +#: src/other-resources.md:35 +#, fuzzy +msgid "A small selection of other guides and tutorial for Rust:" +msgstr "Una piccola selezione di altre guide e tutorial per 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 "" +"* [Impara la ruggine in modo pericoloso](http://cliffle.com/p/dangerust/): copre Rust\n" +" dal punto di vista dei programmatori C di basso livello.\n" +"* [Ruggine per Embedded C\n" +" Programmers](https://docs.opentitan.org/doc/ug/rust_for_c/): copre Rust da\n" +" la prospettiva degli sviluppatori che scrivono firmware in C.\n" +"* [Ruggine per professionisti](https://overexact.com/rust-for-professionals/):\n" +" copre la sintassi di Rust usando confronti fianco a fianco con altri linguaggi\n" +" come C, C++, Java, JavaScript e Python.\n" +"* [Rust on Exercism](https://exercism.org/tracks/rust): oltre 100 esercizi per aiutarti\n" +" impari Ruggine.\n" +"* [Insegnamento ferroso\n" +" Materiale](https://ferrous-systems.github.io/teaching-material/index.html): a\n" +" serie di piccole presentazioni che coprono sia la parte di base che quella avanzata del\n" +" Linguaggio ruggine. Sono disponibili anche altri argomenti come WebAssembly e async/await\n" +" coperto.\n" +"* [Serie per principianti a\n" +" Ruggine](https://docs.microsoft.com/en-us/shows/beginners-series-to-rust/) e\n" +" [Fai i tuoi primi passi con\n" +" Rust](https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/): due\n" +" Guide Rust rivolte ai nuovi sviluppatori. Il primo è un set di 35 video e il\n" +" il secondo è un set di 11 moduli che copre la sintassi di Rust ei costrutti di base.\n" +"* [Impara la ruggine con troppi collegamenti\n" +" Liste](https://rust-unofficial.github.io/too-many-lists/): approfondimento\n" +" esplorazione delle regole di gestione della memoria di Rust, implementandone alcune\n" +" diversi tipi di strutture di elenchi." + +#: 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 "" +"Si prega di consultare il [Little Book of Rust Books](https://lborb.github.io/book/) per\n" +"ancora più libri di Rust." + +#: src/credits.md:1 +#, fuzzy +msgid "# Credits" +msgstr "# Crediti" + +#: 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 "" +"Il materiale qui si basa sulle molte grandi fonti di documentazione di Rust.\n" +"Vedere la pagina su [altre risorse](other-resources.md) per un elenco completo di utili\n" +"risorse." + +#: 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 "" +"Il materiale di Comprehensive Rust è concesso in licenza secondo i termini di Apache 2.0\n" +"licenza, vedere [`LICENSE`](../LICENSE) per i dettagli." + +#: src/credits.md:10 +#, fuzzy +msgid "## Rust by Example" +msgstr "## Ruggine con l'esempio" + +#: 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 "" +"Alcuni esempi ed esercizi sono stati copiati e adattati da [Rust by\n" +"Esempio](https://doc.rust-lang.org/rust-by-example/). Si prega di consultare il\n" +"directory `Third_party/rust-by-example/` per i dettagli, inclusa la licenza\n" +"termini." + +#: src/credits.md:17 +#, fuzzy +msgid "## Rust on Exercism" +msgstr "## Ruggine sull'esercizio" + +#: 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 "" +"Alcuni esercizi sono stati copiati e adattati da [Rust on\n" +"Esercizio fisico](https://exercism.org/tracks/rust). Si prega di consultare il\n" +"directory `Third_party/rust-on-exercism/` per i dettagli, inclusa la licenza\n" +"termini." + +#: 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 "" +"La sezione [Interoperabilità con C++](android/interoperabilità/cpp.md) utilizza un file\n" +"immagine da [CXX](https://cxx.rs/). Si prega di consultare la directory `Third_party/cxx/`\n" +"per i dettagli, inclusi i termini di licenza." + +#: src/exercises/solutions.md:1 +#, fuzzy +msgid "# Solutions" +msgstr "# Soluzioni" + +#: src/exercises/solutions.md:3 +#, fuzzy +msgid "You will find solutions to the exercises on the following pages." +msgstr "Troverai le soluzioni degli esercizi nelle pagine seguenti." + +#: src/exercises/solutions.md:5 +#, fuzzy +msgid "" +"Feel free to ask questions about the solutions [on\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Let us know\n" +"if you have a different or better solution than what is presented here." +msgstr "" +"Sentiti libero di fare domande sulle soluzioni [on\n" +"GitHub](https://github.com/google/comprehensive-rust/discussions). Facci sapere\n" +"se hai una soluzione diversa o migliore di quella presentata qui." + +#: src/exercises/solutions.md:10 +#, fuzzy +msgid "" +"> **Note:** Please ignore the `// ANCHOR: label` and `// ANCHOR_END: label`\n" +"> comments you see in the solutions. They are there to make it possible to\n" +"> re-use parts of the solutions as the exercises." +msgstr "" +"> **Nota:** Si prega di ignorare `// ANCHOR: etichetta` e `// ANCHOR_END: etichetta`\n" +"> commenti che vedi nelle soluzioni. Sono lì per renderlo possibile\n" +"> riutilizzare parti delle soluzioni come esercizi." + +#: src/exercises/day-1/solutions-morning.md:1 +#, fuzzy +msgid "# Day 1 Morning Exercises" +msgstr "# Giorno 1 Esercizi mattutini" + +#: src/exercises/day-1/solutions-morning.md:3 +#, fuzzy +msgid "## Arrays and `for` Loops" +msgstr "## Array e cicli `for`" + +#: src/exercises/day-1/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](for-loops.md))" +msgstr "([torna all'esercizio](for-loops.md))" + +#: src/exercises/day-1/solutions-morning.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: transpose\n" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" // ANCHOR_END: transpose\n" +" let mut result = [[0; 3]; 3];\n" +" for i in 0..3 {\n" +" for j in 0..3 {\n" +" result[j][i] = matrix[i][j];\n" +" }\n" +" }\n" +" return result;\n" +"}\n" +"\n" +"// ANCHOR: pretty_print\n" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" // ANCHOR_END: pretty_print\n" +" for row in matrix {\n" +" println!(\"{row:?}\");\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: tests\n" +"#[test]\n" +"fn test_transpose() {\n" +" let matrix = [\n" +" [101, 102, 103], //\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +" let transposed = transpose(matrix);\n" +" assert_eq!(\n" +" transposed,\n" +" [\n" +" [101, 201, 301], //\n" +" [102, 202, 302],\n" +" [103, 203, 303],\n" +" ]\n" +" );\n" +"}\n" +"// ANCHOR_END: tests\n" +"\n" +"// ANCHOR: main\n" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:78 +#, fuzzy +msgid "### Bonus question" +msgstr "### Domanda bonus" + +#: src/exercises/day-1/solutions-morning.md:80 +#, fuzzy +msgid "" +"It requires more advanced concepts. It might seem that we could use a slice-of-slices (`&[&[i32]]`) as the input type to transpose and thus make our " +"function handle any size of matrix. However, this quickly breaks down: the return type cannot be `&[&[i32]]` since it needs to own the data you " +"return." +msgstr "" +"Richiede concetti più avanzati. Potrebbe sembrare che potremmo usare uno slice-of-slice (`&[&[i32]]`) come tipo di input da trasporre e quindi fare " +"in modo che la nostra funzione gestisca qualsiasi dimensione di matrice. Tuttavia, questo si interrompe rapidamente: il tipo restituito non può " +"essere `&[&[i32]]` poiché deve essere proprietario dei dati restituiti." + +#: src/exercises/day-1/solutions-morning.md:82 +#, fuzzy +msgid "" +"You can attempt to use something like `Vec>`, but this doesn't work out-of-the-box either: it's hard to convert from `Vec>` to " +"`&[&[i32]]` so now you cannot easily use `pretty_print` either." +msgstr "" +"Puoi provare a usare qualcosa come `Vec>`, ma neanche questo funziona immediatamente: è difficile convertire da `Vec>` a " +"`&[ &[i32]]` quindi ora non puoi nemmeno usare facilmente `pretty_print`." + +#: src/exercises/day-1/solutions-morning.md:84 +#, fuzzy +msgid "" +"Once we get to traits and generics, we'll be able to use the [`std::convert::AsRef`][1] trait to abstract over anything that can be referenced as a " +"slice." +msgstr "" +"Una volta arrivati ai tratti e ai generici, saremo in grado di usare il tratto [`std::convert::AsRef`][1] per astrarre su tutto ciò che può essere " +"referenziato come slice." + +#: src/exercises/day-1/solutions-morning.md:86 +msgid "" +"```rust\n" +"use std::convert::AsRef;\n" +"use std::fmt::Debug;\n" +"\n" +"fn pretty_print(matrix: Matrix)\n" +"where\n" +" T: Debug,\n" +" // A line references a slice of items\n" +" Line: AsRef<[T]>,\n" +" // A matrix references a slice of lines\n" +" Matrix: AsRef<[Line]>\n" +"{\n" +" for row in matrix.as_ref() {\n" +" println!(\"{:?}\", row.as_ref());\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" // &[&[i32]]\n" +" pretty_print(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" +" // [[&str; 2]; 2]\n" +" pretty_print([[\"a\", \"b\"], [\"c\", \"d\"]]);\n" +" // Vec>\n" +" pretty_print(vec![vec![1, 2], vec![3, 4]]);\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:113 +#, fuzzy +msgid "In addition, the type itself would not enforce that the child slices are of the same length, so such variable could contain an invalid matrix." +msgstr "" +"Inoltre, il tipo stesso non imporrebbe che le sezioni figlie abbiano la stessa lunghezza, quindi tale variabile potrebbe contenere una matrice non " +"valida." + +#: src/exercises/day-1/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 1 Afternoon Exercises" +msgstr "# Giorno 1 Esercizi pomeridiani" + +#: src/exercises/day-1/solutions-afternoon.md:3 +#, fuzzy +msgid "## Designing a Library" +msgstr "## Progettare una libreria" + +#: src/exercises/day-1/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](book-library.md))" +msgstr "([torna all'esercizio](book-library.md))" + +#: src/exercises/day-1/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: setup\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// Implement the methods below. Update the `self` parameter to\n" +"// indicate the method's required level of ownership over the object:\n" +"//\n" +"// - `&self` for shared read-only access,\n" +"// - `&mut self` for unique and mutable access,\n" +"// - `self` for unique access by value.\n" +"impl Library {\n" +" // ANCHOR_END: setup\n" +"\n" +" // ANCHOR: Library_new\n" +" fn new() -> Library {\n" +" // ANCHOR_END: Library_new\n" +" Library { books: Vec::new() }\n" +" }\n" +"\n" +" // ANCHOR: Library_len\n" +" //fn len(self) -> usize {\n" +" // todo!(\"Return the length of `self.books`\")\n" +" //}\n" +" // ANCHOR_END: Library_len\n" +" fn len(&self) -> usize {\n" +" self.books.len()\n" +" }\n" +"\n" +" // ANCHOR: Library_is_empty\n" +" //fn is_empty(self) -> bool {\n" +" // todo!(\"Return `true` if `self.books` is empty\")\n" +" //}\n" +" // ANCHOR_END: Library_is_empty\n" +" fn is_empty(&self) -> bool {\n" +" self.books.is_empty()\n" +" }\n" +"\n" +" // ANCHOR: Library_add_book\n" +" //fn add_book(self, book: Book) {\n" +" // todo!(\"Add a new book to `self.books`\")\n" +" //}\n" +" // ANCHOR_END: Library_add_book\n" +" fn add_book(&mut self, book: Book) {\n" +" self.books.push(book)\n" +" }\n" +"\n" +" // ANCHOR: Library_print_books\n" +" //fn print_books(self) {\n" +" // todo!(\"Iterate over `self.books` and each book's title and year\")\n" +" //}\n" +" // ANCHOR_END: Library_print_books\n" +" fn print_books(&self) {\n" +" for book in &self.books {\n" +" println!(\"{}, published in {}\", book.title, book.year);\n" +" }\n" +" }\n" +"\n" +" // ANCHOR: Library_oldest_book\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // todo!(\"Return a reference to the oldest book (if any)\")\n" +" //}\n" +" // ANCHOR_END: Library_oldest_book\n" +" fn oldest_book(&self) -> Option<&Book> {\n" +" // Using a closure and a built-in method:\n" +" // self.books.iter().min_by_key(|book| book.year)\n" +"\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" +"// ANCHOR: main\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();\n" +"\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!(\"The oldest book is {book}\"),\n" +" // None => println!(\"The library is empty!\"),\n" +" //}\n" +" //\n" +" //println!(\"The library has {} books\", library.len());\n" +" //library.print_books();\n" +"}\n" +"// ANCHOR_END: main\n" +"\n" +"#[test]\n" +"fn test_library_len() {\n" +" let mut library = Library::new();\n" +" assert_eq!(library.len(), 0);\n" +" assert!(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" +" assert_eq!(library.len(), 2);\n" +" assert!(!library.is_empty());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_is_empty() {\n" +" let mut library = Library::new();\n" +" assert!(library.is_empty());\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert!(!library.is_empty());\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_print_books() {\n" +" let mut library = Library::new();\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" // We could try and capture stdout, but let us just call the\n" +" // method to start with.\n" +" library.print_books();\n" +"}\n" +"\n" +"#[test]\n" +"fn test_library_oldest_book() {\n" +" let mut library = Library::new();\n" +" assert!(library.oldest_book().is_none());\n" +"\n" +" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Lord of the Rings\")\n" +" );\n" +"\n" +" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" assert_eq!(\n" +" library.oldest_book().map(|b| b.title.as_str()),\n" +" Some(\"Alice's Adventures in Wonderland\")\n" +" );\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:1 +#, fuzzy +msgid "# Day 2 Morning Exercises" +msgstr "# Giorno 2 Esercizi mattutini" + +#: src/exercises/day-2/solutions-morning.md:3 +#, fuzzy +msgid "## Points and Polygons" +msgstr "## Punti e poligoni" + +#: src/exercises/day-2/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](points-polygons.md))" +msgstr "([torna all'esercizio](points-polygons.md))" + +#: src/exercises/day-2/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" +"#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" +"// ANCHOR: Point\n" +"pub struct Point {\n" +" // ANCHOR_END: Point\n" +" x: i32,\n" +" y: i32,\n" +"}\n" +"\n" +"// ANCHOR: Point-impl\n" +"impl Point {\n" +" // ANCHOR_END: Point-impl\n" +" pub fn new(x: i32, y: i32) -> Point {\n" +" Point { x, y }\n" +" }\n" +"\n" +" pub fn magnitude(self) -> f64 {\n" +" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +" }\n" +"\n" +" pub fn dist(self, other: Point) -> f64 {\n" +" (self - other).magnitude()\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x + other.x,\n" +" y: self.y + other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Sub for Point {\n" +" type Output = Self;\n" +"\n" +" fn sub(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x - other.x,\n" +" y: self.y - other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Polygon\n" +"pub struct Polygon {\n" +" // ANCHOR_END: Polygon\n" +" points: Vec,\n" +"}\n" +"\n" +"// ANCHOR: Polygon-impl\n" +"impl Polygon {\n" +" // ANCHOR_END: Polygon-impl\n" +" pub fn new() -> Polygon {\n" +" Polygon { points: Vec::new() }\n" +" }\n" +"\n" +" pub fn add_point(&mut self, point: Point) {\n" +" self.points.push(point);\n" +" }\n" +"\n" +" pub fn left_most_point(&self) -> Option {\n" +" self.points.iter().min_by_key(|p| p.x).copied()\n" +" }\n" +"\n" +" pub fn iter(&self) -> impl Iterator {\n" +" self.points.iter()\n" +" }\n" +"\n" +" pub fn length(&self) -> f64 {\n" +" if self.points.is_empty() {\n" +" return 0.0;\n" +" }\n" +"\n" +" let mut result = 0.0;\n" +" let mut last_point = self.points[0];\n" +" for point in &self.points[1..] {\n" +" result += last_point.dist(*point);\n" +" last_point = *point;\n" +" }\n" +" result += last_point.dist(self.points[0]);\n" +" result\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Circle\n" +"pub struct Circle {\n" +" // ANCHOR_END: Circle\n" +" center: Point,\n" +" radius: i32,\n" +"}\n" +"\n" +"// ANCHOR: Circle-impl\n" +"impl Circle {\n" +" // ANCHOR_END: Circle-impl\n" +" pub fn new(center: Point, radius: i32) -> Circle {\n" +" Circle { center, radius }\n" +" }\n" +"\n" +" pub fn circumference(&self) -> f64 {\n" +" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +" }\n" +"\n" +" pub fn dist(&self, other: &Self) -> f64 {\n" +" self.center.dist(other.center)\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Shape\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"// ANCHOR_END: Shape\n" +"\n" +"impl From for Shape {\n" +" fn from(poly: Polygon) -> Self {\n" +" Shape::Polygon(poly)\n" +" }\n" +"}\n" +"\n" +"impl From for Shape {\n" +" fn from(circle: Circle) -> Self {\n" +" Shape::Circle(circle)\n" +" }\n" +"}\n" +"\n" +"impl Shape {\n" +" pub fn perimeter(&self) -> f64 {\n" +" match self {\n" +" Shape::Polygon(poly) => poly.length(),\n" +" Shape::Circle(circle) => circle.circumference(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 2 Afternoon Exercises" +msgstr "# Giorno 2 Esercizi pomeridiani" + +#: src/exercises/day-2/solutions-afternoon.md:3 +#, fuzzy +msgid "## Luhn Algorithm" +msgstr "## Algoritmo di Luhn" + +#: src/exercises/day-2/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](luhn.md))" +msgstr "([torna all'esercizio](luhn.md))" + +#: src/exercises/day-2/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: luhn\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" // ANCHOR_END: luhn\n" +" let mut digits_seen = 0;\n" +" let mut sum = 0;\n" +" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ').enumerate() {\n" +" match ch.to_digit(10) {\n" +" Some(d) => {\n" +" sum += if i % 2 == 1 {\n" +" let dd = d * 2;\n" +" dd / 10 + dd % 10\n" +" } else {\n" +" d\n" +" };\n" +" digits_seen += 1;\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +"\n" +" if digits_seen < 2 {\n" +" return false;\n" +" }\n" +"\n" +" sum % 10 == 0\n" +"}\n" +"\n" +"fn main() {\n" +" let cc_number = \"1234 5678 1234 5670\";\n" +" println!(\n" +" \"Is {cc_number} a valid credit card number? {}\",\n" +" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" +" );\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"```" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:97 +#, fuzzy +msgid "## Strings and Iterators" +msgstr "## Stringhe e iteratori" + +#: src/exercises/day-2/solutions-afternoon.md:99 +#, fuzzy +msgid "([back to exercise](strings-iterators.md))" +msgstr "([torna all'esercizio](strings-iterators.md))" + +#: src/exercises/day-2/solutions-afternoon.md:101 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: prefix_matches\n" +"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +" // ANCHOR_END: prefix_matches\n" +" let prefixes = prefix.split('/');\n" +" let request_paths = request_path\n" +" .split('/')\n" +" .map(|p| Some(p))\n" +" .chain(std::iter::once(None));\n" +"\n" +" for (prefix, request_path) in prefixes.zip(request_paths) {\n" +" match request_path {\n" +" Some(request_path) => {\n" +" if (prefix != \"*\") && (prefix != request_path) {\n" +" return false;\n" +" }\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +" true\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_matches_without_wildcard() {\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" +" assert!(!prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/booksByAuthor\"\n" +" ));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:1 +#, fuzzy +msgid "# Day 3 Morning Exercise" +msgstr "# Giorno 3 Esercizio mattutino" + +#: src/exercises/day-3/solutions-morning.md:3 +#, fuzzy +msgid "## A Simple GUI Library" +msgstr "## Una semplice libreria GUI" + +#: src/exercises/day-3/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](simple-gui.md))" +msgstr "([torna all'esercizio](simple-gui.md))" + +#: src/exercises/day-3/solutions-morning.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: setup\n" +"pub trait Widget {\n" +" /// Natural width of `self`.\n" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"\n" +" fn inner_width(&self) -> usize {\n" +" std::cmp::max(\n" +" self.title.chars().count(),\n" +" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" +" )\n" +" }\n" +"}\n" +"\n" +"// ANCHOR_END: setup\n" +"\n" +"// ANCHOR: Window-width\n" +"impl Widget for Window {\n" +" fn width(&self) -> usize {\n" +" // ANCHOR_END: Window-width\n" +" // Add 4 paddings for borders\n" +" self.inner_width() + 4\n" +" }\n" +"\n" +" // ANCHOR: Window-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Window-draw_into\n" +" let mut inner = String::new();\n" +" for widget in &self.widgets {\n" +" widget.draw_into(&mut inner);\n" +" }\n" +"\n" +" let inner_width = self.inner_width();\n" +"\n" +" // TODO: after learning about error handling, you can change\n" +" // draw_into to return Result<(), std::fmt::Error>. Then use\n" +" // the ?-operator here instead of .unwrap().\n" +" writeln!(buffer, \"+-{:- usize {\n" +" // ANCHOR_END: Button-width\n" +" self.label.width() + 8 // add a bit of padding\n" +" }\n" +"\n" +" // ANCHOR: Button-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Button-draw_into\n" +" let width = self.width();\n" +" let mut label = String::new();\n" +" self.label.draw_into(&mut label);\n" +"\n" +" writeln!(buffer, \"+{:- usize {\n" +" // ANCHOR_END: Label-width\n" +" self.label\n" +" .lines()\n" +" .map(|line| line.chars().count())\n" +" .max()\n" +" .unwrap_or(0)\n" +" }\n" +"\n" +" // ANCHOR: Label-draw_into\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" // ANCHOR_END: Label-draw_into\n" +" writeln!(buffer, \"{}\", &self.label).unwrap();\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"fn main() {\n" +" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" +" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" +" window.add_widget(Box::new(Button::new(\n" +" \"Click me!\",\n" +" Box::new(|| println!(\"You clicked the button!\")),\n" +" )));\n" +" window.draw();\n" +"}\n" +"// ANCHOR_END: main\n" +"```" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:1 +#, fuzzy +msgid "# Day 3 Afternoon Exercises" +msgstr "# Giorno 3 Esercizi pomeridiani" + +#: src/exercises/day-3/solutions-afternoon.md:3 +#, fuzzy +msgid "## Safe FFI Wrapper" +msgstr "## Involucro FFI sicuro" + +#: src/exercises/day-3/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](safe-ffi-wrapper.md))" +msgstr "([torna all'esercizio](safe-ffi-wrapper.md))" + +#: src/exercises/day-3/solutions-afternoon.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: ffi\n" +"mod ffi {\n" +" use std::os::raw::{c_char, c_int};\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" use std::os::raw::{c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" +" #[cfg(not(target_os = \"macos\"))]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" // Layout as per man entry for dirent\n" +" #[cfg(target_os = \"macos\")]\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: u64,\n" +" pub d_seekoff: u64,\n" +" pub d_reclen: u16,\n" +" pub d_namlen: u16,\n" +" pub d_type: u8,\n" +" pub d_name: [c_char; 1024],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" +"#[derive(Debug)]\n" +"struct DirectoryIterator {\n" +" path: CString,\n" +" dir: *mut ffi::DIR,\n" +"}\n" +"// ANCHOR_END: ffi\n" +"\n" +"// ANCHOR: DirectoryIterator\n" +"impl DirectoryIterator {\n" +" fn new(path: &str) -> Result {\n" +" // Call opendir and return a Ok value if that worked,\n" +" // otherwise return Err with a message.\n" +" // ANCHOR_END: DirectoryIterator\n" +" let path = CString::new(path).map_err(|err| format!(\"Invalid path: {err}\"))?;\n" +" // SAFETY: path.as_ptr() cannot be NULL.\n" +" let dir = unsafe { ffi::opendir(path.as_ptr()) };\n" +" if dir.is_null() {\n" +" Err(format!(\"Could not open {:?}\", path))\n" +" } else {\n" +" Ok(DirectoryIterator { path, dir })\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Iterator\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" +" fn next(&mut self) -> Option {\n" +" // Keep calling readdir until we get a NULL pointer back.\n" +" // ANCHOR_END: Iterator\n" +" // SAFETY: self.dir is never NULL.\n" +" let dirent = unsafe { ffi::readdir(self.dir) };\n" +" if dirent.is_null() {\n" +" // We have reached the end of the directory.\n" +" return None;\n" +" }\n" +" // SAFETY: dirent is not NULL and dirent.d_name is NUL\n" +" // terminated.\n" +" let d_name = unsafe { CStr::from_ptr((*dirent).d_name.as_ptr()) };\n" +" let os_str = OsStr::from_bytes(d_name.to_bytes());\n" +" Some(os_str.to_owned())\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Drop\n" +"impl Drop for DirectoryIterator {\n" +" fn drop(&mut self) {\n" +" // Call closedir as needed.\n" +" // ANCHOR_END: Drop\n" +" if !self.dir.is_null() {\n" +" // SAFETY: self.dir is not NULL.\n" +" if unsafe { ffi::closedir(self.dir) } != 0 {\n" +" panic!(\"Could not close {:?}\", self.path);\n" +" }\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: main\n" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"files: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"// ANCHOR_END: main\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +" use std::error::Error;\n" +"\n" +" #[test]\n" +" fn test_nonexisting_directory() {\n" +" let iter = DirectoryIterator::new(\"no-such-directory\");\n" +" assert!(iter.is_err());\n" +" }\n" +"\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" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-morning.md:1 +#, fuzzy +msgid "# Bare Metal Rust Morning Exercise" +msgstr "# Esercizio mattutino ruggine metallo nudo" + +#: src/exercises/bare-metal/solutions-morning.md:3 +#, fuzzy +msgid "## Compass" +msgstr "## Bussola" + +#: src/exercises/bare-metal/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](compass.md))" +msgstr "([torna all'esercizio](compass.md))" + +#: src/exercises/bare-metal/solutions-morning.md:7 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"extern crate panic_halt as _;\n" +"\n" +"use core::fmt::Write;\n" +"use cortex_m_rt::entry;\n" +"// ANCHOR_END: top\n" +"use core::cmp::{max, min};\n" +"use lsm303agr::{AccelOutputDataRate, Lsm303agr, MagOutputDataRate};\n" +"use microbit::display::blocking::Display;\n" +"use microbit::hal::prelude::*;\n" +"use microbit::hal::twim::Twim;\n" +"use microbit::hal::uarte::{Baudrate, Parity, Uarte};\n" +"use microbit::hal::Timer;\n" +"use microbit::pac::twim0::frequency::FREQUENCY_A;\n" +"use microbit::Board;\n" +"\n" +"const COMPASS_SCALE: i32 = 30000;\n" +"const ACCELEROMETER_SCALE: i32 = 700;\n" +"\n" +"// ANCHOR: main\n" +"#[entry]\n" +"fn main() -> ! {\n" +" let board = Board::take().unwrap();\n" +"\n" +" // Configure serial port.\n" +" let mut serial = Uarte::new(\n" +" board.UARTE0,\n" +" board.uart.into(),\n" +" Parity::EXCLUDED,\n" +" Baudrate::BAUD115200,\n" +" );\n" +"\n" +" // Set up the I2C controller and Inertial Measurement Unit.\n" +" // ANCHOR_END: main\n" +" writeln!(serial, \"Setting up IMU...\").unwrap();\n" +" let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100);\n" +" let mut imu = Lsm303agr::new_with_i2c(i2c);\n" +" imu.init().unwrap();\n" +" imu.set_mag_odr(MagOutputDataRate::Hz50).unwrap();\n" +" imu.set_accel_odr(AccelOutputDataRate::Hz50).unwrap();\n" +" let mut imu = imu.into_mag_continuous().ok().unwrap();\n" +"\n" +" // Set up display and timer.\n" +" let mut timer = Timer::new(board.TIMER0);\n" +" let mut display = Display::new(board.display_pins);\n" +"\n" +" let mut mode = Mode::Compass;\n" +" let mut button_pressed = false;\n" +"\n" +" // ANCHOR: loop\n" +" writeln!(serial, \"Ready.\").unwrap();\n" +"\n" +" loop {\n" +" // Read compass data and log it to the serial port.\n" +" // ANCHOR_END: loop\n" +" while !(imu.mag_status().unwrap().xyz_new_data\n" +" && imu.accel_status().unwrap().xyz_new_data)\n" +" {}\n" +" let compass_reading = imu.mag_data().unwrap();\n" +" let accelerometer_reading = imu.accel_data().unwrap();\n" +" writeln!(\n" +" serial,\n" +" \"{},{},{}\\t{},{},{}\",\n" +" compass_reading.x,\n" +" compass_reading.y,\n" +" compass_reading.z,\n" +" accelerometer_reading.x,\n" +" accelerometer_reading.y,\n" +" accelerometer_reading.z,\n" +" )\n" +" .unwrap();\n" +"\n" +" let mut image = [[0; 5]; 5];\n" +" let (x, y) = match mode {\n" +" Mode::Compass => (\n" +" scale(-compass_reading.x, -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize,\n" +" scale(compass_reading.y, -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize,\n" +" ),\n" +" Mode::Accelerometer => (\n" +" scale(\n" +" accelerometer_reading.x,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" scale(\n" +" -accelerometer_reading.y,\n" +" -ACCELEROMETER_SCALE,\n" +" ACCELEROMETER_SCALE,\n" +" 0,\n" +" 4,\n" +" ) as usize,\n" +" ),\n" +" };\n" +" image[y][x] = 255;\n" +" display.show(&mut timer, image, 100);\n" +"\n" +" // If button A is pressed, switch to the next mode and briefly blink all LEDs on.\n" +" if board.buttons.button_a.is_low().unwrap() {\n" +" if !button_pressed {\n" +" mode = mode.next();\n" +" display.show(&mut timer, [[255; 5]; 5], 200);\n" +" }\n" +" button_pressed = true;\n" +" } else {\n" +" button_pressed = false;\n" +" }\n" +" }\n" +"}\n" +"\n" +"#[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" +"enum Mode {\n" +" Compass,\n" +" Accelerometer,\n" +"}\n" +"\n" +"impl Mode {\n" +" fn next(self) -> Self {\n" +" match self {\n" +" Self::Compass => Self::Accelerometer,\n" +" Self::Accelerometer => Self::Compass,\n" +" }\n" +" }\n" +"}\n" +"\n" +"fn scale(value: i32, min_in: i32, max_in: i32, min_out: i32, max_out: i32) -> i32 {\n" +" let range_in = max_in - min_in;\n" +" let range_out = max_out - min_out;\n" +" cap(\n" +" min_out + range_out * (value - min_in) / range_in,\n" +" min_out,\n" +" max_out,\n" +" )\n" +"}\n" +"\n" +"fn cap(value: i32, min_value: i32, max_value: i32) -> i32 {\n" +" max(min_value, min(value, max_value))\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:1 +#, fuzzy +msgid "# Bare Metal Rust Afternoon" +msgstr "# Bare Metal Ruggine Pomeriggio" + +#: src/exercises/bare-metal/solutions-afternoon.md:3 +#, fuzzy +msgid "## RTC driver" +msgstr "## Driver RTC" + +#: src/exercises/bare-metal/solutions-afternoon.md:5 +#, fuzzy +msgid "([back to exercise](rtc.md))" +msgstr "([torna all'esercizio](rtc.md))" + +#: src/exercises/bare-metal/solutions-afternoon.md:7 +#, fuzzy +msgid "`main.rs`:" +msgstr "`principale.rs`:" + +#: src/exercises/bare-metal/solutions-afternoon.md:9 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"// ANCHOR: top\n" +"#![no_main]\n" +"#![no_std]\n" +"\n" +"mod exceptions;\n" +"mod logger;\n" +"mod pl011;\n" +"// ANCHOR_END: top\n" +"mod pl031;\n" +"\n" +"use crate::pl031::Rtc;\n" +"use arm_gic::gicv3::{IntId, Trigger};\n" +"use arm_gic::{irq_enable, wfi};\n" +"use chrono::{TimeZone, Utc};\n" +"use core::hint::spin_loop;\n" +"// ANCHOR: imports\n" +"use crate::pl011::Uart;\n" +"use arm_gic::gicv3::GicV3;\n" +"use core::panic::PanicInfo;\n" +"use log::{error, info, trace, LevelFilter};\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" +"const GICR_BASE_ADDRESS: *mut u64 = 0x80A_0000 as _;\n" +"\n" +"/// Base address of the primary PL011 UART.\n" +"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" +"// ANCHOR_END: imports\n" +"\n" +"/// Base address of the PL031 RTC.\n" +"const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;\n" +"/// The IRQ used by the PL031 RTC.\n" +"const PL031_IRQ: IntId = IntId::spi(2);\n" +"\n" +"// ANCHOR: main\n" +"#[no_mangle]\n" +"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" +" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" +" // and nothing else accesses that address range.\n" +" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" +" logger::init(uart, LevelFilter::Trace).unwrap();\n" +"\n" +" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" +"\n" +" // Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base\n" +" // addresses of a GICv3 distributor and redistributor respectively, and\n" +" // nothing else accesses those address ranges.\n" +" let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, GICR_BASE_ADDRESS) };\n" +" gic.setup();\n" +" // ANCHOR_END: main\n" +"\n" +" // Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 device,\n" +" // and nothing else accesses that address range.\n" +" let mut rtc = unsafe { Rtc::new(PL031_BASE_ADDRESS) };\n" +" let timestamp = rtc.read();\n" +" let time = Utc.timestamp_opt(timestamp.into(), 0).unwrap();\n" +" info!(\"RTC: {time}\");\n" +"\n" +" GicV3::set_priority_mask(0xff);\n" +" gic.set_interrupt_priority(PL031_IRQ, 0x80);\n" +" gic.set_trigger(PL031_IRQ, Trigger::Level);\n" +" irq_enable();\n" +" gic.enable_interrupt(PL031_IRQ, true);\n" +"\n" +" // Wait for 3 seconds, without interrupts.\n" +" let target = timestamp + 3;\n" +" rtc.set_match(target);\n" +" info!(\n" +" \"Waiting for {}\",\n" +" Utc.timestamp_opt(target.into(), 0).unwrap()\n" +" );\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" while !rtc.matched() {\n" +" spin_loop();\n" +" }\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" info!(\"Finished waiting\");\n" +"\n" +" // Wait another 3 seconds for an interrupt.\n" +" let target = timestamp + 6;\n" +" info!(\n" +" \"Waiting for {}\",\n" +" Utc.timestamp_opt(target.into(), 0).unwrap()\n" +" );\n" +" rtc.set_match(target);\n" +" rtc.clear_interrupt();\n" +" rtc.enable_interrupt(true);\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" while !rtc.interrupt_pending() {\n" +" wfi();\n" +" }\n" +" trace!(\n" +" \"matched={}, interrupt_pending={}\",\n" +" rtc.matched(),\n" +" rtc.interrupt_pending()\n" +" );\n" +" info!(\"Finished waiting\");\n" +"\n" +" // ANCHOR: main_end\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[panic_handler]\n" +"fn panic(info: &PanicInfo) -> ! {\n" +" error!(\"{info}\");\n" +" system_off::().unwrap();\n" +" loop {}\n" +"}\n" +"// ANCHOR_END: main_end\n" +"```" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:149 +#, fuzzy +msgid "`pl031.rs`:" +msgstr "`pl031.rs`:" + +#: src/exercises/bare-metal/solutions-afternoon.md:151 +msgid "" +"```rust\n" +"// Copyright 2023 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"use core::ptr::{addr_of, addr_of_mut};\n" +"\n" +"#[repr(C, align(4))]\n" +"struct Registers {\n" +" /// Data register\n" +" dr: u32,\n" +" /// Match register\n" +" mr: u32,\n" +" /// Load register\n" +" lr: u32,\n" +" /// Control register\n" +" cr: u8,\n" +" _reserved0: [u8; 3],\n" +" /// Interrupt Mask Set or Clear register\n" +" imsc: u8,\n" +" _reserved1: [u8; 3],\n" +" /// Raw Interrupt Status\n" +" ris: u8,\n" +" _reserved2: [u8; 3],\n" +" /// Masked Interrupt Status\n" +" mis: u8,\n" +" _reserved3: [u8; 3],\n" +" /// Interrupt Clear Register\n" +" icr: u8,\n" +" _reserved4: [u8; 3],\n" +"}\n" +"\n" +"/// Driver for a PL031 real-time clock.\n" +"#[derive(Debug)]\n" +"pub struct Rtc {\n" +" registers: *mut Registers,\n" +"}\n" +"\n" +"impl Rtc {\n" +" /// Constructs a new instance of the RTC driver for a PL031 device at the\n" +" /// given base address.\n" +" ///\n" +" /// # Safety\n" +" ///\n" +" /// The given base address must point to the MMIO control registers of a\n" +" /// PL031 device, which must be mapped into the address space of the process\n" +" /// as device memory and not have any other aliases.\n" +" pub unsafe fn new(base_address: *mut u32) -> Self {\n" +" Self {\n" +" registers: base_address as *mut Registers,\n" +" }\n" +" }\n" +"\n" +" /// Reads the current RTC value.\n" +" pub fn read(&self) -> u32 {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of!((*self.registers).dr).read_volatile() }\n" +" }\n" +"\n" +" /// Writes a match value. When the RTC value matches this then an interrupt\n" +" /// will be generated (if it is enabled).\n" +" pub fn set_match(&mut self, value: u32) {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of_mut!((*self.registers).mr).write_volatile(value) }\n" +" }\n" +"\n" +" /// Returns whether the match register matches the RTC value, whether or not\n" +" /// the interrupt is enabled.\n" +" pub fn matched(&self) -> bool {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" let ris = unsafe { addr_of!((*self.registers).ris).read_volatile() };\n" +" (ris & 0x01) != 0\n" +" }\n" +"\n" +" /// Returns whether there is currently an interrupt pending.\n" +" ///\n" +" /// This should be true iff `matched` returns true and the interrupt is\n" +" /// masked.\n" +" pub fn interrupt_pending(&self) -> bool {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" let ris = unsafe { addr_of!((*self.registers).mis).read_volatile() };\n" +" (ris & 0x01) != 0\n" +" }\n" +"\n" +" /// Sets or clears the interrupt mask.\n" +" ///\n" +" /// When the mask is true the interrupt is enabled; when it is false the\n" +" /// interrupt is disabled.\n" +" pub fn enable_interrupt(&mut self, mask: bool) {\n" +" let imsc = if mask { 0x01 } else { 0x00 };\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of_mut!((*self.registers).imsc).write_volatile(imsc) }\n" +" }\n" +"\n" +" /// Clears a pending interrupt, if any.\n" +" pub fn clear_interrupt(&mut self) {\n" +" // Safe because we know that self.registers points to the control\n" +" // registers of a PL031 device which is appropriately mapped.\n" +" unsafe { addr_of_mut!((*self.registers).icr).write_volatile(0x01) }\n" +" }\n" +"}\n" +"\n" +"// Safe because it just contains a pointer to device memory, which can be\n" +"// accessed from any context.\n" +"unsafe impl Send for Rtc {}\n" +"```" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:1 +#, fuzzy +msgid "# Concurrency Morning Exercise" +msgstr "# Esercizio mattutino in concorrenza" + +#: src/exercises/concurrency/solutions-morning.md:3 +#, fuzzy +msgid "## Dining Philosophers" +msgstr "## Filosofi a tavola" + +#: src/exercises/concurrency/solutions-morning.md:5 +#, fuzzy +msgid "([back to exercise](dining-philosophers.md))" +msgstr "([torna all'esercizio](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 "" diff --git a/po/ko.po b/po/ko.po index 12587bb..e2132da 100644 --- a/po/ko.po +++ b/po/ko.po @@ -25,759 +25,763 @@ msgid "Course Structure" msgstr "강의 구성" #: src/SUMMARY.md:6 +msgid "Day 4" +msgstr "4일차" + +#: src/SUMMARY.md:7 msgid "Keyboard Shortcuts" msgstr "단축키" -#: src/SUMMARY.md:7 +#: src/SUMMARY.md:8 msgid "Translations" msgstr "다른 언어들" -#: src/SUMMARY.md:8 +#: src/SUMMARY.md:9 msgid "Using Cargo" msgstr "카고 사용하기" -#: src/SUMMARY.md:9 +#: src/SUMMARY.md:10 msgid "Rust Ecosystem" msgstr "러스트 생태계" -#: src/SUMMARY.md:10 +#: src/SUMMARY.md:11 msgid "Code Samples" msgstr "코드 샘플" -#: src/SUMMARY.md:11 +#: src/SUMMARY.md:12 msgid "Running Cargo Locally" msgstr "카고(Cargo) 수행하기" -#: src/SUMMARY.md:14 +#: src/SUMMARY.md:15 msgid "Day 1: Morning" msgstr "1일차 오전" -#: src/SUMMARY.md:18 src/SUMMARY.md:74 src/SUMMARY.md:127 src/SUMMARY.md:183 +#: src/SUMMARY.md:19 src/SUMMARY.md:75 src/SUMMARY.md:128 src/SUMMARY.md:184 msgid "Welcome" msgstr "개요" -#: src/SUMMARY.md:19 +#: src/SUMMARY.md:20 msgid "What is Rust?" msgstr "러스트란?" -#: src/SUMMARY.md:20 +#: src/SUMMARY.md:21 msgid "Hello World!" msgstr "Hello World!" -#: src/SUMMARY.md:21 +#: src/SUMMARY.md:22 msgid "Small Example" msgstr "작은 예제" -#: src/SUMMARY.md:22 +#: src/SUMMARY.md:23 msgid "Why Rust?" msgstr "러스트를 써야하는 이유" -#: src/SUMMARY.md:23 +#: src/SUMMARY.md:24 msgid "Compile Time Guarantees" msgstr "컴파일 시 보장되는 것들" -#: src/SUMMARY.md:24 +#: src/SUMMARY.md:25 msgid "Runtime Guarantees" msgstr "런타임 시 보장되는 것들" -#: src/SUMMARY.md:25 +#: src/SUMMARY.md:26 msgid "Modern Features" msgstr "현대적인 특징" -#: src/SUMMARY.md:26 +#: src/SUMMARY.md:27 msgid "Basic Syntax" msgstr "기본 문법" -#: src/SUMMARY.md:27 +#: src/SUMMARY.md:28 msgid "Scalar Types" msgstr "스칼라 타입" -#: src/SUMMARY.md:28 +#: src/SUMMARY.md:29 msgid "Compound Types" msgstr "복합 타입" -#: src/SUMMARY.md:29 +#: src/SUMMARY.md:30 msgid "References" msgstr "참조" -#: src/SUMMARY.md:30 +#: src/SUMMARY.md:31 msgid "Dangling References" msgstr "허상(dangling) 참조" -#: src/SUMMARY.md:31 +#: src/SUMMARY.md:32 msgid "Slices" msgstr "슬라이스" -#: src/SUMMARY.md:32 +#: src/SUMMARY.md:33 msgid "String vs str" msgstr "String과 str" -#: src/SUMMARY.md:33 +#: src/SUMMARY.md:34 msgid "Functions" msgstr "함수" -#: src/SUMMARY.md:34 src/SUMMARY.md:81 +#: src/SUMMARY.md:35 src/SUMMARY.md:82 msgid "Methods" msgstr "메서드" -#: src/SUMMARY.md:35 +#: src/SUMMARY.md:36 msgid "Overloading" msgstr "오버로딩" -#: src/SUMMARY.md:36 src/SUMMARY.md:65 src/SUMMARY.md:89 src/SUMMARY.md:118 -#: src/SUMMARY.md:147 src/SUMMARY.md:175 src/SUMMARY.md:198 src/SUMMARY.md:225 +#: src/SUMMARY.md:37 src/SUMMARY.md:66 src/SUMMARY.md:90 src/SUMMARY.md:119 +#: src/SUMMARY.md:148 src/SUMMARY.md:176 src/SUMMARY.md:199 src/SUMMARY.md:226 msgid "Exercises" msgstr "연습문제" -#: src/SUMMARY.md:37 +#: src/SUMMARY.md:38 msgid "Implicit Conversions" msgstr "묵시적 형변환" -#: src/SUMMARY.md:38 +#: src/SUMMARY.md:39 msgid "Arrays and for Loops" msgstr "배열과 for 반복문" -#: src/SUMMARY.md:40 +#: src/SUMMARY.md:41 msgid "Day 1: Afternoon" msgstr "1일차 오후" -#: src/SUMMARY.md:42 +#: src/SUMMARY.md:43 msgid "Variables" msgstr "변수" -#: src/SUMMARY.md:43 +#: src/SUMMARY.md:44 msgid "Type Inference" msgstr "타입 추론" -#: src/SUMMARY.md:44 +#: src/SUMMARY.md:45 msgid "static & const" msgstr "정적변수(static)와 상수(const)" -#: src/SUMMARY.md:45 +#: src/SUMMARY.md:46 msgid "Scopes and Shadowing" msgstr "범위(Scopes)와 쉐도잉(Shadowing)" -#: src/SUMMARY.md:46 +#: src/SUMMARY.md:47 msgid "Memory Management" msgstr "메모리 관리" -#: src/SUMMARY.md:47 +#: src/SUMMARY.md:48 msgid "Stack vs Heap" msgstr "스택(Stack)과 힙(Heap)" -#: src/SUMMARY.md:48 +#: src/SUMMARY.md:49 msgid "Stack Memory" msgstr "스택 메모리" -#: src/SUMMARY.md:49 +#: src/SUMMARY.md:50 msgid "Manual Memory Management" msgstr "수동 메모리 관리" -#: src/SUMMARY.md:50 +#: src/SUMMARY.md:51 msgid "Scope-Based Memory Management" msgstr "범위기반 메모리 관리" -#: src/SUMMARY.md:51 +#: src/SUMMARY.md:52 msgid "Garbage Collection" msgstr "가비지 컬렉션" -#: src/SUMMARY.md:52 +#: src/SUMMARY.md:53 msgid "Rust Memory Management" msgstr "러스트의 메모리 관리" -#: src/SUMMARY.md:53 +#: src/SUMMARY.md:54 msgid "Comparison" msgstr "비교" -#: src/SUMMARY.md:54 +#: src/SUMMARY.md:55 msgid "Ownership" msgstr "소유권" -#: src/SUMMARY.md:55 +#: src/SUMMARY.md:56 msgid "Move Semantics" msgstr "Move 문법" -#: src/SUMMARY.md:56 +#: src/SUMMARY.md:57 msgid "Moved Strings in Rust" msgstr "러스트에서의 문자열 이동" -#: src/SUMMARY.md:57 +#: src/SUMMARY.md:58 msgid "Double Frees in Modern C++" msgstr "Modern C++에서 이중해제 문제" -#: src/SUMMARY.md:58 +#: src/SUMMARY.md:59 msgid "Moves in Function Calls" msgstr "함수 호출에서의 이동(Move)" -#: src/SUMMARY.md:59 +#: src/SUMMARY.md:60 msgid "Copying and Cloning" msgstr "복사와 복제" -#: src/SUMMARY.md:60 +#: src/SUMMARY.md:61 msgid "Borrowing" msgstr "빌림" -#: src/SUMMARY.md:61 +#: src/SUMMARY.md:62 msgid "Shared and Unique Borrows" msgstr "공유와 고유 빌림" -#: src/SUMMARY.md:62 +#: src/SUMMARY.md:63 msgid "Lifetimes" msgstr "수명" -#: src/SUMMARY.md:63 +#: src/SUMMARY.md:64 msgid "Lifetimes in Function Calls" msgstr "함수 호출에서의 수명" -#: src/SUMMARY.md:64 +#: src/SUMMARY.md:65 msgid "Lifetimes in Data Structures" msgstr "구조체에서의 수명" -#: src/SUMMARY.md:66 +#: src/SUMMARY.md:67 msgid "Designing a Library" msgstr "도서관 설계" -#: src/SUMMARY.md:67 +#: src/SUMMARY.md:68 msgid "Iterators and Ownership" msgstr "반복자와 소유권" -#: src/SUMMARY.md:70 +#: src/SUMMARY.md:71 msgid "Day 2: Morning" msgstr "2일차 오전" -#: src/SUMMARY.md:75 +#: src/SUMMARY.md:76 msgid "Structs" msgstr "구조체" -#: src/SUMMARY.md:76 +#: src/SUMMARY.md:77 msgid "Tuple Structs" msgstr "튜플" -#: src/SUMMARY.md:77 +#: src/SUMMARY.md:78 msgid "Field Shorthand Syntax" msgstr "필드 할당 단축 문법" -#: src/SUMMARY.md:78 +#: src/SUMMARY.md:79 msgid "Enums" msgstr "열거형" -#: src/SUMMARY.md:79 +#: src/SUMMARY.md:80 msgid "Variant Payloads" msgstr "데이터를 포함하는 열거형(Variant Payloads)" -#: src/SUMMARY.md:80 +#: src/SUMMARY.md:81 msgid "Enum Sizes" msgstr "열거형의 크기" -#: src/SUMMARY.md:82 +#: src/SUMMARY.md:83 msgid "Method Receiver" msgstr "메서드 리시버(Receiver)" -#: src/SUMMARY.md:83 src/SUMMARY.md:158 src/SUMMARY.md:193 +#: src/SUMMARY.md:84 src/SUMMARY.md:159 src/SUMMARY.md:194 msgid "Example" msgstr "예제" -#: src/SUMMARY.md:84 +#: src/SUMMARY.md:85 msgid "Pattern Matching" msgstr "패턴 매칭" -#: src/SUMMARY.md:85 +#: src/SUMMARY.md:86 msgid "Destructuring Enums" msgstr "열거형 분해(역구조화)" -#: src/SUMMARY.md:86 +#: src/SUMMARY.md:87 msgid "Destructuring Structs" msgstr "구조체 분해(역구조화)" -#: src/SUMMARY.md:87 +#: src/SUMMARY.md:88 msgid "Destructuring Arrays" msgstr "배열 분해(역구조화)" -#: src/SUMMARY.md:88 +#: src/SUMMARY.md:89 msgid "Match Guards" msgstr "매치 가드" -#: src/SUMMARY.md:90 +#: src/SUMMARY.md:91 msgid "Health Statistics" msgstr "건강상태 모니터링 시스템" -#: src/SUMMARY.md:91 +#: src/SUMMARY.md:92 msgid "Points and Polygons" msgstr "점과 다각형" -#: src/SUMMARY.md:93 +#: src/SUMMARY.md:94 msgid "Day 2: Afternoon" msgstr "2일차 오후" -#: src/SUMMARY.md:95 +#: src/SUMMARY.md:96 msgid "Control Flow" msgstr "흐름 제어" -#: src/SUMMARY.md:96 +#: src/SUMMARY.md:97 msgid "Blocks" msgstr "블록" -#: src/SUMMARY.md:97 +#: src/SUMMARY.md:98 msgid "if expressions" msgstr "if 표현식" -#: src/SUMMARY.md:98 +#: src/SUMMARY.md:99 msgid "if let expressions" msgstr "if let 표현식" -#: src/SUMMARY.md:99 +#: src/SUMMARY.md:100 msgid "while expressions" msgstr "while 표현식" -#: src/SUMMARY.md:100 +#: src/SUMMARY.md:101 msgid "while let expressions" msgstr "while let 표현식" -#: src/SUMMARY.md:101 +#: src/SUMMARY.md:102 msgid "for expressions" msgstr "for 표현식" -#: src/SUMMARY.md:102 +#: src/SUMMARY.md:103 msgid "loop expressions" msgstr "loop 표현식" -#: src/SUMMARY.md:103 +#: src/SUMMARY.md:104 msgid "match expressions" msgstr "match 표현식" -#: src/SUMMARY.md:104 +#: src/SUMMARY.md:105 msgid "break & continue" msgstr "break와 continue" -#: src/SUMMARY.md:105 +#: src/SUMMARY.md:106 msgid "Standard Library" msgstr "표준 라이브러리" -#: src/SUMMARY.md:106 +#: src/SUMMARY.md:107 msgid "Option and Result" msgstr "Option과 Result" -#: src/SUMMARY.md:107 +#: src/SUMMARY.md:108 msgid "String" msgstr "String" -#: src/SUMMARY.md:108 +#: src/SUMMARY.md:109 msgid "Vec" msgstr "Vec" -#: src/SUMMARY.md:109 +#: src/SUMMARY.md:110 msgid "HashMap" msgstr "HashMap" -#: src/SUMMARY.md:110 +#: src/SUMMARY.md:111 msgid "Box" msgstr "Box" -#: src/SUMMARY.md:111 +#: src/SUMMARY.md:112 msgid "Recursive Data Types" msgstr "재귀적 자료구조" -#: src/SUMMARY.md:112 +#: src/SUMMARY.md:113 msgid "Niche Optimization" msgstr "니치(틈새) 최적화(Niche Optimization)" -#: src/SUMMARY.md:113 +#: src/SUMMARY.md:114 msgid "Rc" msgstr "Rc" -#: src/SUMMARY.md:114 +#: src/SUMMARY.md:115 msgid "Modules" msgstr "모듈" -#: src/SUMMARY.md:115 +#: src/SUMMARY.md:116 msgid "Visibility" msgstr "가시성" -#: src/SUMMARY.md:116 +#: src/SUMMARY.md:117 msgid "Paths" msgstr "경로" -#: src/SUMMARY.md:117 +#: src/SUMMARY.md:118 msgid "Filesystem Hierarchy" msgstr "파일시스템 계층" -#: src/SUMMARY.md:119 +#: src/SUMMARY.md:120 msgid "Luhn Algorithm" msgstr "룬 알고리즘" -#: src/SUMMARY.md:120 +#: src/SUMMARY.md:121 msgid "Strings and Iterators" msgstr "문자열과 반복자" -#: src/SUMMARY.md:123 +#: src/SUMMARY.md:124 msgid "Day 3: Morning" msgstr "3일차 오전" -#: src/SUMMARY.md:128 +#: src/SUMMARY.md:129 msgid "Traits" msgstr "트레잇(Trait)" -#: src/SUMMARY.md:129 +#: src/SUMMARY.md:130 msgid "Deriving Traits" msgstr "트레잇 상속하기" -#: src/SUMMARY.md:130 +#: src/SUMMARY.md:131 msgid "Default Methods" msgstr "기본 메서드" -#: src/SUMMARY.md:131 +#: src/SUMMARY.md:132 msgid "Important Traits" msgstr "중요한 트레잇" -#: src/SUMMARY.md:132 +#: src/SUMMARY.md:133 msgid "Iterator" msgstr "Iterator" -#: src/SUMMARY.md:133 +#: src/SUMMARY.md:134 msgid "FromIterator" msgstr "FromIterator" -#: src/SUMMARY.md:134 +#: src/SUMMARY.md:135 msgid "From and Into" msgstr "From과 Into" -#: src/SUMMARY.md:135 +#: src/SUMMARY.md:136 msgid "Read and Write" msgstr "Read와 Write" -#: src/SUMMARY.md:136 +#: src/SUMMARY.md:137 msgid "Add, Mul, ..." msgstr "Add, Mul, ..." -#: src/SUMMARY.md:137 +#: src/SUMMARY.md:138 msgid "Drop" msgstr "Drop" -#: src/SUMMARY.md:138 +#: src/SUMMARY.md:139 msgid "Default" msgstr "Default" -#: src/SUMMARY.md:139 +#: src/SUMMARY.md:140 msgid "Generics" msgstr "제네릭" -#: src/SUMMARY.md:140 +#: src/SUMMARY.md:141 msgid "Generic Data Types" msgstr "제네릭 데이터 타입" -#: src/SUMMARY.md:141 +#: src/SUMMARY.md:142 msgid "Generic Methods" msgstr "제네릭 메서드" -#: src/SUMMARY.md:142 +#: src/SUMMARY.md:143 msgid "Trait Bounds" msgstr "제네릭 타입 제한(트레잇 경계)" -#: src/SUMMARY.md:143 +#: src/SUMMARY.md:144 msgid "impl Trait" msgstr "트레잇 구현하기" -#: src/SUMMARY.md:144 +#: src/SUMMARY.md:145 msgid "Closures" msgstr "클로저" -#: src/SUMMARY.md:145 +#: src/SUMMARY.md:146 msgid "Monomorphization" msgstr "단형화" -#: src/SUMMARY.md:146 +#: src/SUMMARY.md:147 msgid "Trait Objects" msgstr "트레잇 객체" -#: src/SUMMARY.md:148 +#: src/SUMMARY.md:149 msgid "A Simple GUI Library" msgstr "간단한 GUI 라이브러리" -#: src/SUMMARY.md:150 +#: src/SUMMARY.md:151 msgid "Day 3: Afternoon" msgstr "3일차 오후" -#: src/SUMMARY.md:152 +#: src/SUMMARY.md:153 msgid "Error Handling" msgstr "오류처리" -#: src/SUMMARY.md:153 +#: src/SUMMARY.md:154 msgid "Panics" msgstr "패닉" -#: src/SUMMARY.md:154 +#: src/SUMMARY.md:155 msgid "Catching Stack Unwinding" msgstr "스택 되감기" -#: src/SUMMARY.md:155 +#: src/SUMMARY.md:156 msgid "Structured Error Handling" msgstr "구조화된 오류처리" -#: src/SUMMARY.md:156 +#: src/SUMMARY.md:157 msgid "Propagating Errors with ?" msgstr "'?'를 이용한 오류 전파" -#: src/SUMMARY.md:157 +#: src/SUMMARY.md:158 msgid "Converting Error Types" msgstr "오류타입 변환" -#: src/SUMMARY.md:159 +#: src/SUMMARY.md:160 msgid "Deriving Error Enums" msgstr "또다른 오류 열거형" -#: src/SUMMARY.md:160 +#: src/SUMMARY.md:161 msgid "Dynamic Error Types" msgstr "동적인 에러 타입" -#: src/SUMMARY.md:161 +#: src/SUMMARY.md:162 msgid "Adding Context to Errors" msgstr "오류에 상황정보 추가" -#: src/SUMMARY.md:162 +#: src/SUMMARY.md:163 msgid "Testing" msgstr "테스트" -#: src/SUMMARY.md:163 +#: src/SUMMARY.md:164 msgid "Unit Tests" msgstr "단위 테스트" -#: src/SUMMARY.md:164 +#: src/SUMMARY.md:165 msgid "Test Modules" msgstr "테스트 모듈" -#: src/SUMMARY.md:165 +#: src/SUMMARY.md:166 msgid "Documentation Tests" msgstr "문서화주석 테스트" -#: src/SUMMARY.md:166 +#: src/SUMMARY.md:167 msgid "Integration Tests" msgstr "통합 테스트" -#: src/SUMMARY.md:167 +#: src/SUMMARY.md:168 msgid "Unsafe Rust" msgstr "안전하지 않은 러스트" -#: src/SUMMARY.md:168 +#: src/SUMMARY.md:169 msgid "Dereferencing Raw Pointers" msgstr "원시 포인터 역참조(따라가기)" -#: src/SUMMARY.md:169 +#: src/SUMMARY.md:170 msgid "Mutable Static Variables" msgstr "정적 가변 변수" -#: src/SUMMARY.md:170 +#: src/SUMMARY.md:171 msgid "Unions" msgstr "Unions" -#: src/SUMMARY.md:171 +#: src/SUMMARY.md:172 msgid "Calling Unsafe Functions" msgstr "안전하지 않은 함수 호출" -#: src/SUMMARY.md:172 +#: src/SUMMARY.md:173 msgid "Writing Unsafe Functions" msgstr "안전하지 않은 함수 작성하기" -#: src/SUMMARY.md:173 +#: src/SUMMARY.md:174 msgid "Extern Functions" msgstr "외부(다른언어) 함수들" -#: src/SUMMARY.md:174 +#: src/SUMMARY.md:175 msgid "Implementing Unsafe Traits" msgstr "안전하지 않은 트레잇 구현하기" -#: src/SUMMARY.md:176 +#: src/SUMMARY.md:177 msgid "Safe FFI Wrapper" msgstr "FFI래퍼" -#: src/SUMMARY.md:179 +#: src/SUMMARY.md:180 msgid "Day 4: Morning" msgstr "4일차 오전" -#: src/SUMMARY.md:184 +#: src/SUMMARY.md:185 msgid "Concurrency" msgstr "동시성" -#: src/SUMMARY.md:185 +#: src/SUMMARY.md:186 msgid "Threads" msgstr "스레드" -#: src/SUMMARY.md:186 +#: src/SUMMARY.md:187 msgid "Scoped Threads" msgstr "범위 스레드(Scoped Threads)" -#: src/SUMMARY.md:187 +#: src/SUMMARY.md:188 msgid "Channels" msgstr "채널" -#: src/SUMMARY.md:188 +#: src/SUMMARY.md:189 msgid "Unbounded Channels" msgstr "무경계 채널" -#: src/SUMMARY.md:189 +#: src/SUMMARY.md:190 msgid "Bounded Channels" msgstr "경계 채널" -#: src/SUMMARY.md:190 +#: src/SUMMARY.md:191 msgid "Shared State" msgstr "상태 공유" -#: src/SUMMARY.md:191 +#: src/SUMMARY.md:192 msgid "Arc" msgstr "Arc" -#: src/SUMMARY.md:192 +#: src/SUMMARY.md:193 msgid "Mutex" msgstr "Mutex" -#: src/SUMMARY.md:194 +#: src/SUMMARY.md:195 msgid "Send and Sync" msgstr "Send와 Sync" -#: src/SUMMARY.md:194 +#: src/SUMMARY.md:195 msgid "Send" msgstr "Send" -#: src/SUMMARY.md:194 +#: src/SUMMARY.md:195 msgid "Sync" msgstr "Sync" -#: src/SUMMARY.md:197 +#: src/SUMMARY.md:198 msgid "Examples" msgstr "예제" -#: src/SUMMARY.md:199 +#: src/SUMMARY.md:200 msgid "Dining Philosophers" msgstr "식사하는 철학자들" -#: src/SUMMARY.md:200 +#: src/SUMMARY.md:201 msgid "Multi-threaded Link Checker" msgstr "멀티스레드 링크 검사기" -#: src/SUMMARY.md:202 -msgid "Day 4: Afternoon" -msgstr "4일차 오후" +#: src/SUMMARY.md:203 +msgid "Day 4: Afternoon (Android)" +msgstr "4일차 오후 (안드로이드)" -#: src/SUMMARY.md:206 +#: src/SUMMARY.md:203 msgid "Android" msgstr "안드로이드" -#: src/SUMMARY.md:207 +#: src/SUMMARY.md:208 msgid "Setup" msgstr "설치" -#: src/SUMMARY.md:208 +#: src/SUMMARY.md:209 msgid "Build Rules" msgstr "빌드 규칙" -#: src/SUMMARY.md:209 +#: src/SUMMARY.md:210 msgid "Binary" msgstr "바이너리" -#: src/SUMMARY.md:210 +#: src/SUMMARY.md:211 msgid "Library" msgstr "라이브러리" -#: src/SUMMARY.md:211 +#: src/SUMMARY.md:212 msgid "AIDL" msgstr "AIDL" -#: src/SUMMARY.md:212 +#: src/SUMMARY.md:213 msgid "Interface" msgstr "AIDL 인터페이스" -#: src/SUMMARY.md:213 +#: src/SUMMARY.md:214 msgid "Implementation" msgstr "서비스 구현" -#: src/SUMMARY.md:214 +#: src/SUMMARY.md:215 msgid "Server" msgstr "AIDL 서버" -#: src/SUMMARY.md:215 +#: src/SUMMARY.md:216 msgid "Deploy" msgstr "배포" -#: src/SUMMARY.md:216 +#: src/SUMMARY.md:217 msgid "Client" msgstr "클라이언트" -#: src/SUMMARY.md:217 +#: src/SUMMARY.md:218 msgid "Changing API" msgstr "API 수정" -#: src/SUMMARY.md:218 +#: src/SUMMARY.md:219 msgid "Logging" msgstr "로깅" -#: src/SUMMARY.md:219 +#: src/SUMMARY.md:220 msgid "Interoperability" msgstr "상호운용성" -#: src/SUMMARY.md:220 +#: src/SUMMARY.md:221 msgid "With C" msgstr "C와의 상호운용성" -#: src/SUMMARY.md:221 +#: src/SUMMARY.md:222 msgid "Calling C with Bindgen" msgstr "Bindgen을 사용한 C호출" -#: src/SUMMARY.md:222 +#: src/SUMMARY.md:223 msgid "Calling Rust from C" msgstr "C에서 러스트 호출" -#: src/SUMMARY.md:223 +#: src/SUMMARY.md:224 msgid "With C++" -msgstr "C++ 와의 상호운용성" +msgstr "C++와의 상호운용성" -#: src/SUMMARY.md:224 +#: src/SUMMARY.md:225 msgid "With Java" msgstr "Java와의 상호운용성" -#: src/SUMMARY.md:227 +#: src/SUMMARY.md:228 msgid "Final Words" msgstr "끝으로..." -#: src/SUMMARY.md:229 +#: src/SUMMARY.md:230 msgid "Thanks!" msgstr "감사인사" -#: src/SUMMARY.md:230 +#: src/SUMMARY.md:231 msgid "Other Resources" msgstr "러스트 참고 자료" -#: src/SUMMARY.md:231 +#: src/SUMMARY.md:232 msgid "Credits" msgstr "도와주신 분들" -#: src/SUMMARY.md:235 +#: src/SUMMARY.md:236 msgid "Solutions" msgstr "해답" -#: src/SUMMARY.md:240 +#: src/SUMMARY.md:241 msgid "Day 1 Morning" msgstr "1일차 오전" -#: src/SUMMARY.md:241 +#: src/SUMMARY.md:242 msgid "Day 1 Afternoon" msgstr "1일차 오후" -#: src/SUMMARY.md:242 +#: src/SUMMARY.md:243 msgid "Day 2 Morning" msgstr "2일차 오전" -#: src/SUMMARY.md:243 +#: src/SUMMARY.md:244 msgid "Day 2 Afternoon" msgstr "2일차 오후" -#: src/SUMMARY.md:244 +#: src/SUMMARY.md:245 msgid "Day 3 Morning" msgstr "3일차 오전" -#: src/SUMMARY.md:245 +#: src/SUMMARY.md:246 msgid "Day 3 Afternoon" msgstr "3일차 오후" -#: src/SUMMARY.md:246 +#: src/SUMMARY.md:247 msgid "Day 4 Morning" msgstr "4일차 오전" @@ -786,19 +790,55 @@ msgid "# Welcome to Comprehensive Rust 🦀" msgstr "# Welcome to Comprehensive Rust 🦀" #: src/welcome.md:3 +msgid "[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/google/comprehensive-rust/actions/workflows/build.yml)" +msgstr "" + +#: src/welcome.md:3 +msgid "Build workflow" +msgstr "" + +#: src/welcome.md:3 +msgid "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/google/comprehensive-rust/actions/workflows/build.yml)\n" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/graphs/contributors)" +msgstr "" +"[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/google/comprehensive-rust/actions/workflows/build.yml)\n" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/graphs/contributors)" + +#: src/welcome.md:4 +msgid "GitHub contributors" +msgstr "" + +#: src/welcome.md:4 +msgid "" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/graphs/contributors)\n" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/stargazers)" +msgstr "" +"[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/graphs/contributors)\n" +"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/stargazers)" + +#: src/welcome.md:5 +msgid "GitHub stars" +msgstr "GitHub stars" + +#: src/welcome.md:5 +msgid "[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/stargazers)" +msgstr "[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/stargazers)" + +#: src/welcome.md:7 msgid "" "This is a four 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 "이 4일짜리 러스트 강의는 안드로이드 팀이 만들었습니다. 기본 문법부터 제네릭, 에러 핸들링과 같은 고급주제까지 러스트의 모든 것을 포함합니다. 마지막 날에는 안드로이드에 대한 것 까지 다룹니다." -#: src/welcome.md:7 +#: src/welcome.md:11 msgid "" "The goal of the course is to teach you Rust. We assume you don't know anything\n" "about Rust and hope to:" msgstr "강의는 당신이 러스트에 대해서 아무것도 모른다고 가정하고 아래의 목표를 가지고 있습니다:" -#: src/welcome.md:10 +#: src/welcome.md:14 msgid "" "* Give you a comprehensive understanding of the Rust syntax and language.\n" "* Enable you to modify existing programs and write new programs in Rust.\n" @@ -808,11 +848,11 @@ msgstr "" "* 기존 프로그램을 수정하고 러스트에서 새 프로그램을 작성할 수 있습니다.\n" "* 일반적인 러스트 관용구를 보여줍니다." -#: src/welcome.md:14 +#: src/welcome.md:18 msgid "On Day 4, we will cover Android-specific things such as:" msgstr "4일차 강의에 우리는 아래와 같은 안드로이드 특화된 내용들도 설명합니다:" -#: src/welcome.md:16 +#: src/welcome.md:20 msgid "" "* Building Android components in Rust.\n" "* AIDL servers and clients.\n" @@ -822,24 +862,24 @@ msgstr "" "* AIDL 서버 및 클라이언트.\n" "* C, C++ 및 Java와의 상호 운용성." -#: src/welcome.md:20 +#: src/welcome.md:24 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 "이 강의에서는 러스트로 안드로이드 **애플리케이션**을 개발하는 것은 다루지 않습니다. 이 강의에서 다루는 안드로이드 특화된 내용은 안드로이드 OS의 일부를 러스트로 개발하는 것에 대한 것입니다. " -#: src/welcome.md:24 +#: src/welcome.md:28 msgid "## Non-Goals" msgstr "## 제외사항" -#: src/welcome.md:26 +#: src/welcome.md:30 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:" msgstr "러스트는 며칠만에 모든 것을 다루기에는 너무 큰 언어입니다. 그래서 아래와 같은것을 목표로 하지 않습니다:" -#: src/welcome.md:29 +#: src/welcome.md:33 msgid "" "* Learn how to use async Rust --- we'll only mention async Rust when\n" " covering traditional concurrency primitives. Please see [Asynchronous\n" @@ -852,24 +892,24 @@ msgstr "" "* 비동기적 러스트 사용법. 간단하게 언급정도는 하겠지만 좀 더 자세한 내용은 [Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/)를 참조해주세요.\n" "* 매크로를 개발하는 방법. [Chapter 19.5 in the Rust Book](https://doc.rust-lang.org/book/ch19-06-macros.html)와 [Rust by Example](https://doc.rust-lang.org/rust-by-example/macros.html)를 참조하세요." -#: src/welcome.md:37 +#: src/welcome.md:41 msgid "## Assumptions" msgstr "## 독자 수준에 대한 가정" -#: src/welcome.md:39 +#: src/welcome.md:43 msgid "" "The course assumes that you already know how to program. Rust is a statically\n" "typed language and we will sometimes make comparisons with C and C++ to better\n" "explain or contrast the Rust approach." msgstr "본 강의는 여러분이 프로그래밍 자체에 대해서는 알고 있다고 가정합니다. 러스트는 정적타입 언어이며, 강좌에서는 C/C++ 와의 비교, 대조를 통해 러스트를 설명할 것입니다." -#: src/welcome.md:43 +#: src/welcome.md:47 msgid "" "If you know how to program in a dynamically typed language such as Python or\n" "JavaScript, then you will be able to follow along just fine too." msgstr "C/C++을 모르더라도 동적 타입 언어(Python이나 JavaScript 등) 프로그래밍 경험이 있다면 따라오는데 큰 문제는 없을 것입니다." -#: src/welcome.md:46 src/cargo/rust-ecosystem.md:19 +#: src/welcome.md:50 src/cargo/rust-ecosystem.md:19 #: src/cargo/code-samples.md:22 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 @@ -886,26 +926,31 @@ msgstr "C/C++을 모르더라도 동적 타입 언어(Python이나 JavaScript #: 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/structs/tuple-structs.md:35 -#: src/structs/field-shorthand.md:25 src/enums/variant-payloads.md:33 -#: src/methods.md:28 src/pattern-matching/destructuring-enums.md:33 +#: 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/match-expressions.md:25 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:24 -#: src/exercises/day-2/afternoon.md:5 src/traits.md:39 -#: src/traits/iterator.md:30 src/traits/from-iterator.md:15 -#: src/traits/operators.md:24 src/traits/drop.md:32 src/traits/default.md:38 -#: src/generics/methods.md:23 src/generics/trait-bounds.md:33 -#: src/generics/impl-trait.md:22 src/generics/closures.md:23 -#: src/exercises/day-3/morning.md:5 src/error-handling/result.md:25 -#: src/error-handling/try-operator.md:48 +#: 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:24 src/exercises/day-2/afternoon.md:5 +#: src/traits.md:39 src/traits/iterator.md:30 src/traits/from-iterator.md:15 +#: src/traits/from-into.md:27 src/traits/operators.md:24 src/traits/drop.md:32 +#: src/traits/default.md:38 src/generics/methods.md:23 +#: src/generics/trait-bounds.md:33 src/generics/impl-trait.md:22 +#: src/generics/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/error-handling/deriving-error-enums.md:37 #: src/error-handling/dynamic-errors.md:34 @@ -913,54 +958,67 @@ msgstr "C/C++을 모르더라도 동적 타입 언어(Python이나 JavaScript #: src/unsafe/raw-pointers.md:24 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/concurrency/threads.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/afternoon.md:10 +#: src/exercises/day-4/android.md:10 msgid "
" msgstr "
" -#: src/welcome.md:48 +#: src/welcome.md:52 msgid "" "This is an example of a _speaker note_. We will use these to add additional\n" "information to the slides. This could be key points which the instructor should\n" "cover as well as answers to typical questions which come up in class." msgstr "이것은 \"발표자 노트\"의 예제입니다. 이 부분을 이용해서 추가 정보를 제공합니다. 주로 강의실에서 제기되는 일반적인 질문에 대한 답변과 강사가 다루어야 할 키 포인트일 수 있습니다." -#: src/welcome.md:52 src/cargo/rust-ecosystem.md:67 +#: src/welcome.md:56 src/cargo/rust-ecosystem.md:67 #: src/cargo/code-samples.md:35 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:36 src/hello-world/small-example.md:44 src/why-rust.md:24 +#: 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/functions.md:54 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/string-slices.md:44 src/basic-syntax/functions.md:54 +#: 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 #: src/memory-management/rust.md:18 src/ownership/move-semantics.md:26 -#: src/ownership/moves-function-calls.md:26 src/ownership/borrowing.md:51 -#: src/ownership/shared-unique-borrows.md:29 +#: 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/field-shorthand.md:41 src/enums/sizes.md:155 -#: src/methods/example.md:53 src/pattern-matching/destructuring-enums.md:39 +#: src/structs.md:41 src/structs/tuple-structs.md:43 +#: src/structs/field-shorthand.md:72 src/enums.md:41 +#: 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/pattern-matching/destructuring-arrays.md:46 -#: src/exercises/day-2/morning.md:15 src/exercises/day-2/points-polygons.md:125 +#: 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:26 +#: src/control-flow/while-let-expressions.md:30 #: src/control-flow/for-expressions.md:29 -#: src/control-flow/loop-expressions.md:27 src/std.md:31 +#: 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/rc.md:69 src/modules.md:32 -#: src/modules/visibility.md:48 src/modules/filesystem.md:53 -#: src/exercises/day-2/afternoon.md:11 src/traits.md:54 -#: src/traits/from-iterator.md:26 src/traits/operators.md:38 -#: src/traits/drop.md:42 src/traits/default.md:47 src/generics/methods.md:31 +#: 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:53 src/exercises/day-2/afternoon.md:11 +#: src/traits.md:53 src/traits/iterator.md:39 src/traits/from-iterator.md:26 +#: src/traits/from-into.md:33 src/traits/operators.md:38 src/traits/drop.md:42 +#: src/traits/default.md:47 src/generics/methods.md:31 +#: src/generics/trait-bounds.md:50 src/generics/impl-trait.md:38 #: src/generics/closures.md:38 src/exercises/day-3/morning.md:11 -#: src/error-handling/try-operator.md:55 +#: 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/deriving-error-enums.md:45 #: src/error-handling/dynamic-errors.md:41 @@ -968,12 +1026,14 @@ msgstr "이것은 \"발표자 노트\"의 예제입니다. 이 부분을 이용 #: src/unsafe/raw-pointers.md:42 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/concurrency/threads.md:45 +#: 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/example.md:60 +#: 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/afternoon.md:15 +#: src/exercises/day-4/android.md:15 msgid "
" msgstr "
" @@ -982,6 +1042,7 @@ msgid "# Running the Course" msgstr "# 강의 진행 방식" #: 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 "> 강사를 위한 안내 페이지입니다." @@ -992,94 +1053,73 @@ msgid "" msgstr "다음은 구글 내부에서 이 과정을 어떤식으로 운영해왔는지에 대한 배경 정보입니다." #: src/running-the-course.md:8 -msgid "To run the course, you need to:" +msgid "Before you run the course, you will want to:" msgstr "강의를 실행하기 위한 준비:" #: src/running-the-course.md:10 msgid "" "1. Make yourself familiar with the course material. We've included speaker notes\n" -" on some of the pages to help highlight the key points (please help us by\n" -" contributing more speaker notes!). You should make sure to open the speaker\n" -" notes in a popup (click the link with a little arrow next to \"Speaker\n" -" Notes\"). This way you have a clean screen to present to the class." -msgstr "1. 강의 자료를 숙지합니다. 주요 요점을 강조하기 위해 일부 페이지에 강의 참조노트를 포함하였습니다. (추가적인 노트를 작성하여 제공해 주시면 감사하겠습니다.) 강의 참조 노트의 링크를 누르면 강의노트가 별도의 팝업으로 분리가 되며, 메인 화면에서는 사라집니다." - -#: src/running-the-course.md:16 -msgid "" -"2. Decide on the dates. Since the course is large, we recommend that you\n" +" to help highlight the key points (please help us by contributing more speaker\n" +" notes!). When presenting, you should make sure to open the speaker notes in a\n" +" 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" " they find it helpful to have a gap in the course since it helps them process\n" -" all the information we give them." -msgstr "2. 강의 날짜를 정합니다. 강의 내용이 많고 수강생들이 모든 정보를 공부할 수 있도록 중간에 틈을 두어 2주에 걸쳐 4일을 잡는 것을 추천합니다." - -#: src/running-the-course.md:21 -msgid "" -"3. Find a room large enough for your in-person participants. We recommend a\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" " asking questions --- it's also small enough that one instructor will have\n" -" time to answer the questions." -msgstr "3. 충분한 공간을 확보합니다. 수강생과 강사가 질의를 하기에 충분한 시간과 공간이어야 합니다. 15에서 20명 규모의 공간을 추천합니다." - -#: src/running-the-course.md:26 -msgid "" -"4. On the day of your course, show up to the room a little early to set things\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" +" In particular, you will be doing a lot of live-coding as an instructor, so a lectern won't\n" +" be very helpful for you.\n" +"\n" +"1. On the day of your course, show up to the room a little early to set things\n" " up. We recommend presenting directly using `mdbook serve` running on your\n" -" laptop (see the [installation instructions][5]). This ensures optimal performance with no lag as you change pages.\n" +" laptop (see the [installation instructions][3]). This ensures optimal performance with no lag as you change pages.\n" " Using your laptop will also allow you to fix typos as you or the course\n" -" participants spot them." -msgstr "4. 강의 당일 조금 일찍 와서 준비합니다. 강사 노트북에서 `mdbook serve -d book/ko`를 이용해 직접 프레젠테이션 하면 페이지 이동 시의 지연이 없습니다.([설치 방법][5]을 참조하세요.) 또한, 그렇게 하면 강의 도중 오타를 발견했을 때 그 자리에서 바로 수정 가능하다는 장점도 있습니다." - -#: src/running-the-course.md:32 -msgid "" -"5. Let people solve the exercises by themselves or in small groups. Make sure to\n" +" participants spot them.\n" +"\n" +"1. Let people solve the exercises by themselves or in small groups. 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." -msgstr "5. 수강생들이 직접 (개별 혹은 그룹으로) 연습문제를 풀도록 합니다. 진행이 막혀 도움을 필요로 하는 수강생이 없는지 수시로 확인합니다. 만약 같은 문제를 여러 사람이 겪고 있다면, 그 문제를 강의실 전체 인원에게 알리고 해결책을 제시합니다. 예를 들어 표준 라이브러리 어디에 가면 그 문제에 대한 해답을 찾을 수 있는지 알려 줍니다." - -#: src/running-the-course.md:38 -msgid "" -"6. If you don't skip the Android specific parts on Day 4, you will need an [AOSP\n" -" checkout][1]. Make a checkout of the [course repository][2] on the same\n" -" machine and move the `src/android/` directory into the root of your AOSP\n" -" checkout. This will ensure that the Android build system sees the\n" -" `Android.bp` files in `src/android/`." -msgstr "6. 4일차에 있을 안드로이드 부분을 건너띄지 않는다면 [AOSP 코드][1]를 체크아웃해야 합니다. 그런 다음, 같은 컴퓨터에서 [과정 저장소][2]를 체크아웃하고 `src/android/` 디렉터리를 AOSP 코드의 루트로 이동합니다. 이렇게 하면 안드로이드 빌드 시스템에서 과제용으로 추가된 `Android.bp`파일을 인식할 수 있습니다." - -#: src/running-the-course.md:44 -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." -msgstr " `adb sync` 명렁어가 에뮬레이터 혹은 실제 장치와 작동하는지 확인합니다. 그리고 `src/android/build_all.sh`를 수행해서 모든 안드로이드 예제를 미리 빌드해 보세요. 그 쉘 스크립트를 읽고, 그 안에서 수행되는 명령어들을 확인한 후 각 명령어들을 수동으로 실행해도 잘 되는지 확인하세요." +" information in the standard library.\n" +"\n" +"1. Prepare anything you need to have available for the afternoon of day 4." +msgstr "" +"1. 강의 자료를 숙지합니다. 주요 요점을 강조하기 위해 강의 참조 노트를 포함하였습니다. (추가적인 노트를 작성하여 제공해 주시면 감사하겠습니다.) 강의 참조 노트의 링크를 누르면 별도의 팝업으로 분리가 되며, 메인 화면에서는 사라집니다. 깔끔한 화면으로 강의를 진행할 수 있습니다.\n" +"\n" +"1. 4일차 오후의 주제를 선택합니다. 수강생들이 원하는, 혹은 여러분이 자신있는 주제를 고르세요.\n" +"\n" +"1. 강의 날짜를 정합니다. 강의 내용이 많고 수강생들이 모든 정보를 공부할 수 있도록 중간에 틈을 두어 2주에 걸쳐 4일을 잡는 것을 추천합니다.\n" +"\n" +"1. 충분한 공간을 확보합니다. 15에서 20명 규모의 공간을 추천합니다. 수강생과 강사가 질의를 하기에 충분한 시간과 공간이어야 합니다. 강사나 수강생 모두 책상을 사용할 수 있는 강의실이면 좋습니다. 강의 중에 강사가 라이브 코딩을 하게 될 경우가 많으며, 이때 자리에 앉아 노트북을 사용하는 것이 도움이 됩니다.\n" +"\n" +"1. 강의 당일 조금 일찍 와서 준비합니다. 강사 노트북에서 `mdbook serve -d book/ko`를 이용해 직접 프레젠테이션 하면 페이지 이동 시의 지연이 없습니다.([설치 방법][3]을 참조하세요.) 또한, 그렇게 하면 강의 도중 오타를 발견했을 때 그 자리에서 바로 수정 가능하다는 장점도 있습니다.\n" +"\n" +"1. 수강생들이 직접 (개별 혹은 그룹으로) 연습문제를 풀도록 합니다. 진행이 막혀 도움을 필요로 하는 수강생이 없는지 수시로 확인합니다. 만약 같은 문제를 여러 사람이 겪고 있다면, 그 문제를 강의실 전체 인원에게 알리고 해결책을 제시합니다. 예를 들어 표준 라이브러리 어디에 가면 그 문제에 대한 해답을 찾을 수 있는지 알려 줍니다.\n" +"\n" +"1. 4일차 오후에 필요한 것들을 준비하세요." -#: src/running-the-course.md:48 +#: src/running-the-course.md:46 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!" msgstr "이제 준비는 끝났습니다. 우리가 그랬듯이 여러분들도 이 강의를 즐기시길 바랍니다!" -#: src/running-the-course.md:51 +#: src/running-the-course.md:49 msgid "" -"Please [provide feedback][3] afterwards so that we can keep improving the\n" +"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" -"better. Your students are also very welcome to [send us feedback][4]!" -msgstr "강의를 계속 개선할 수 있도록 [피드백][3]을 제공해 주십시오. 우리는 무엇이 좋았고, 무엇이 모자랐는지 듣고 싶습니다. 수강생들로 부터의 [피드백][4]도 환영합니다!" - -#: src/running-the-course.md:55 -msgid "" -"[1]: https://source.android.com/docs/setup/download/downloading\n" -"[2]: https://github.com/google/comprehensive-rust\n" -"[3]: https://github.com/google/comprehensive-rust/discussions/86\n" -"[4]: https://github.com/google/comprehensive-rust/discussions/100\n" -"[5]: https://github.com/google/comprehensive-rust#building" -msgstr "" -"[1]: https://source.android.com/docs/setup/download/downloading\n" -"[2]: https://github.com/google/comprehensive-rust\n" -"[3]: https://github.com/google/comprehensive-rust/discussions/86\n" -"[4]: https://github.com/google/comprehensive-rust/discussions/100\n" -"[5]: https://github.com/google/comprehensive-rust#building" +"better. Your students are also very welcome to [send us feedback][2]!" +msgstr "강의를 계속 개선할 수 있도록 [피드백][1]을 제공해 주십시오. 우리는 무엇이 좋았고, 무엇이 모자랐는지 듣고 싶습니다. 수강생들로 부터의 [피드백][2]도 환영합니다!" #: src/running-the-course/course-structure.md:1 msgid "# Course Structure" @@ -1094,30 +1134,75 @@ 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 interoperability with other languages" +"* Day 4: Concurrency in Rust and seeing Rust in action." msgstr "" "* 1일차: 러스트 기본, 소유권(ownership)과 빌림(borrow) 체크\n" "* 2일차: 복합 데이터 유형, 패턴 매칭, 표준 라이브러리\n" "* 3일차: 트레잇(trait)와 제네릭(generic), 오류 처리, 테스트, 안전하지 않은 러스트\n" -"* 4일차: 러스트의 동시성 및 다른 언어와의 상호 운용성" +"* 4일차: 러스트의 동시성 및 러스트가 실제 활용되는 사례 살펴보기" #: src/running-the-course/course-structure.md:12 -msgid "" -"> **Exercise for Day 4:** Do you interface with some C/C++ code in your project\n" -"> which we could attempt to move to Rust? The fewer dependencies the better.\n" -"> Parsing code would be ideal." -msgstr "> **4일차 연습문제:** 러스트 프로젝트에서 C/C++로 작성된 코드를 이전해서 연결하려고 한다면 종속성이 적을 수록 좋습니다. 구문 분석 코드라면 이상적입니다." - -#: src/running-the-course/course-structure.md:16 msgid "## Format" msgstr "## 강의 형식" -#: src/running-the-course/course-structure.md:18 +#: src/running-the-course/course-structure.md:14 msgid "" "The course is meant to be very interactive and we recommend letting the\n" "questions drive the exploration of Rust!" msgstr "이 강의는 강사와 수강생이 양방향으로 소통하면서 진행하도록 디자인 되었습니다. 다양한 질문을 통해 러스트의 여러 부분을 탐험할 수 있도록 하세요!" +#: src/running-the-course/day-4.md:1 +msgid "# Day 4" +msgstr "# 4일차" + +#: src/running-the-course/day-4.md:5 +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 "4일차 오후에는 여러분의 선택에 따라 다른 주제를 다룰 수 있습니다. 강의를 안내할 때 4일차 오후의 주제를 포함하여 수강생들이 미리 알 수 있게 하세요." + +#: src/running-the-course/day-4.md:9 +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 "4일차 쯤이면, 실제 코드 베이스를 통해 러스트가 활용되는 모습을 살펴보면 좋습니다. 이미 준비된 주제 중에서 고를 수도 있고, 여러분이 직접 준비한 주제를 다룰 수도 있습니다." + +#: src/running-the-course/day-4.md:13 +msgid "Some topics need additional preparation:" +msgstr "준비된 주제 (어떤 주제는 추가적인 준비가 필요합니다):" + +#: src/running-the-course/day-4.md:15 +msgid "## Android" +msgstr "## 안드로이드" + +#: 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/`." +msgstr "4일차 오후에 안드로이드를 다루기로 했다면, [AOSP 코드][1]를 체크아웃해야 합니다. 그런 다음, 같은 컴퓨터에서 [과정 저장소][2]를 체크아웃하고 `src/android/` 디렉터리를 AOSP 코드의 루트로 이동합니다. 이렇게 하면 안드로이드 빌드 시스템에서 과제용으로 추가된 `Android.bp`파일을 인식할 수 있습니다." + +#: src/running-the-course/day-4.md:22 +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." +msgstr "`adb sync` 명렁어가 에뮬레이터 혹은 실제 장치와 작동하는지 확인합니다. 그리고 `src/android/build_all.sh`를 수행해서 모든 안드로이드 예제를 미리 빌드해 보세요. 그 쉘 스크립트를 읽고, 그 안에서 수행되는 명령어들을 확인한 후 각 명령어들을 수동으로 실행해도 잘 되는지 확인하세요." + +#: src/running-the-course/day-4.md:26 +msgid "## Async" +msgstr "## 비동기" + +#: src/running-the-course/day-4.md:28 +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." +msgstr "4일 차 오후에 비동기를 다루기로 했다면, 새 크레이트를 설정하고 몇 가지 의존성을 다운로드해 두어야 합니다. 그런 다음 예제를 `src/main.rs`에 복사/붙여넣기 하여 실험할 수 있습니다." + #: src/running-the-course/keyboard-shortcuts.md:1 msgid "# Keyboard Shortcuts" msgstr "# 단축키" @@ -1169,29 +1254,6 @@ msgstr "" "이 과정의 번역 작업에 도움을 주고 싶다면 [여기][our instructions] 설명된 내용을 참고하세요.\n" "진행 중인 번역 작업에 대한 내용은 [이슈 트래커][issue tracker]를 참고하세요." -#: src/running-the-course/translations.md:14 -msgid "" -"[pt-BR]: https://google.github.io/comprehensive-rust/pt-BR/\n" -"[ko]: https://google.github.io/comprehensive-rust/ko/\n" -"[@rastringer]: https://github.com/rastringer\n" -"[@hugojacob]: https://github.com/hugojacob\n" -"[@keispace]: https://github.com/keispace\n" -"[@jiyongp]: https://github.com/jiyongp\n" -"[@jooyunghan]: https://github.com/jooyunghan\n" -"[our instructions]: https://github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md\n" -"[issue tracker]: https://github.com/google/comprehensive-rust/issues/282" -msgstr "" -"[en]: https://google.github.io/comprehensive-rust/\n" -"[pt-BR]: https://google.github.io/comprehensive-rust/pt-BR/\n" -"[ko]: https://google.github.io/comprehensive-rust/ko/\n" -"[@rastringer]: https://github.com/rastringer\n" -"[@hugojacob]: https://github.com/hugojacob\n" -"[@keispace]: https://github.com/keispace\n" -"[@jiyongp]: https://github.com/jiyongp\n" -"[@jooyunghan]: https://github.com/jooyunghan\n" -"[our instructions]: https://github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md\n" -"[issue tracker]: https://github.com/google/comprehensive-rust/issues/282" - #: src/cargo.md:1 msgid "# Using Cargo" msgstr "# 카고(Cargo) 사용하기" @@ -1252,22 +1314,6 @@ msgstr "이렇게 하면 [rust-analyzer][1]를 이용해서 특정 심볼이 정 msgid "Some folks also like to use the [JetBrains][4] family of IDEs, which do their own analysis but have their own tradeoffs. If you prefer them, you can install the [Rust Plugin][5]. Please take note that as of January 2023 debugging only works on the CLion version of the JetBrains IDEA suite." msgstr "어떤 사람들은 [JetBrains][4] 제품군을 선호하기도 합니다. 이 제품들은 rust-analyzer 를 활용하지 않고 IDE 자체적으로 구문분석을 합니다. 만약 이 IDE를 설치하셨다면 [Rust Plugin][5]를 설치하시기 바랍니다. 다만 2023년 1월 기준, 디버깅은 JetBrains IDEA suite의 CLion 버전에서만 작동한다는 점에 유의하시기 바랍니다." -#: src/cargo.md:31 -msgid "" -"[1]: https://rust-analyzer.github.io/\n" -"[2]: https://code.visualstudio.com/\n" -"[3]: https://rustup.rs/\n" -"[4]: https://www.jetbrains.com/clion/\n" -"[5]: https://www.jetbrains.com/rust/\n" -"[6]: https://github.com/rust-lang/rustfmt" -msgstr "" -"[1]: https://rust-analyzer.github.io/\n" -"[2]: https://code.visualstudio.com/\n" -"[3]: https://rustup.rs/\n" -"[4]: https://www.jetbrains.com/clion/\n" -"[5]: https://www.jetbrains.com/rust/\n" -"[6]: https://github.com/rust-lang/rustfmt" - #: src/cargo/rust-ecosystem.md:1 msgid "# The Rust Ecosystem" msgstr "# 러스트 생태계" @@ -1279,29 +1325,29 @@ msgstr "러스트의 생태계는 여러가지 도구들로 구성되어 있으 #: src/cargo/rust-ecosystem.md:5 msgid "" "* `rustc`: the Rust compiler which turns `.rs` files into binaries and other\n" -" intermediate formats." -msgstr "* `rustc`: `.rs` 확장자 파일을 바이너리 혹은 다른 중간 형식으로 변환해주는 Rust 컴파일러입니다." - -#: src/cargo/rust-ecosystem.md:8 -msgid "" +" intermediate formats.\n" +"\n" "* `cargo`: the Rust dependency manager and build tool. Cargo knows how to\n" " download dependencies hosted on and it will pass them to\n" " `rustc` when building your project. Cargo also comes with a built-in test\n" -" runner which is used to execute unit tests." -msgstr "* `cargo`: 러스트 의존성 관리자 및 빌드도구 입니다. 여러분의 프로젝트에 명시된 의존성들을 에서 자동으로 다운로드 받고, 그 소스코드를 `rustc`로 전달하여 빌드를 시킵니다. 또한 유닛 테스트를 실행하는 테스트 러너를 내장하고 있습니다." - -#: src/cargo/rust-ecosystem.md:13 -msgid "" +" runner which is used to execute unit tests.\n" +"\n" "* `rustup`: the Rust toolchain installer and updater. This tool is used to\n" " install and update `rustc` and `cargo` when new versions of Rust is released.\n" " In addition, `rustup` can also download documentation for the standard\n" " library. You can have multiple versions of Rust installed at once and `rustup`\n" " will let you switch between them as needed." -msgstr "* `rustup`: 러스트 툴체인 설치 프로그램 및 업데이트 프로그램. 이 도구는 새 버전의 러스트가 출시될 때 `rustc` 및 `cargo` 설치하고 업데이트하는 데 사용됩니다. 또한 `rustup`은 표준 라이브러리에 대한 문서를 다운로드할 수도 있습니다. 한 번에 여러 버전의 러스트를 설치할 수 있으며 `rustup`을 통해 필요에 따라 이들 버전을 전환할 수 있습니다." +msgstr "" +"* `rustc`: `.rs` 확장자 파일을 바이너리 혹은 다른 중간 형식으로 변환해주는 Rust 컴파일러입니다.\n" +"\n" +"* `cargo`: 러스트 의존성 관리자 및 빌드도구 입니다. 여러분의 프로젝트에 명시된 의존성들을 에서 자동으로 다운로드 받고, 그 소스코드를 `rustc`로 전달하여 빌드를 시킵니다. 또한 유닛 테스트를 실행하는 테스트 러너를 내장하고 있습니다.\n" +"\n" +"* `rustup`: 러스트 툴체인 설치 프로그램 및 업데이트 프로그램. 이 도구는 새 버전의 러스트가 출시될 때 `rustc` 및 `cargo` 설치하고 업데이트하는 데 사용됩니다. 또한 `rustup`은 표준 라이브러리에 대한 문서를 다운로드할 수도 있습니다. 한 번에 여러 버전의 러스트를 설치할 수 있으며 `rustup`을 통해 필요에 따라 이들 버전을 전환할 수 있습니다." #: 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 @@ -1312,49 +1358,27 @@ msgstr "키 포인트:" msgid "" "* Rust has a rapid release schedule with a new release coming out\n" " every six weeks. New releases maintain backwards compatibility with\n" -" old releases --- plus they enable new functionality." -msgstr "* 러스트는 6주마다 새로운 릴리즈가 발표되며 이전 릴리즈와의 호환성을 유지하고 있습니다." - -#: src/cargo/rust-ecosystem.md:27 -msgid "* There are three release channels: \"stable\", \"beta\", and \"nightly\"." -msgstr "* 릴리즈는 3가지 버전으로 제공됩니다: \"stable\", \"beta\" 그리고 \"nightly\"." - -#: src/cargo/rust-ecosystem.md:29 -msgid "" +" old releases --- plus they enable new functionality.\n" +"\n" +"* There are three release channels: \"stable\", \"beta\", and \"nightly\".\n" +"\n" "* New features are being tested on \"nightly\", \"beta\" is what becomes\n" -" \"stable\" every six weeks." -msgstr "* 새로운 기능은 \"nightly\" -> \"beta\" -(6주 후)-> \"stable\" 로 변경됩니다." - -#: src/cargo/rust-ecosystem.md:32 -msgid "" +" \"stable\" every six weeks.\n" +"\n" "* Rust also has [editions]: the current edition is Rust 2021. Previous\n" -" editions were Rust 2015 and Rust 2018." -msgstr "* 러스트는 [에디션][editions]으로 구분됩니다. 현재는 Rust 2021 에디션입니다. 이 전 에디션으로 Rust 2015와 Rust 2018이 있습니다." - -#: src/cargo/rust-ecosystem.md:35 -msgid "" +" editions were Rust 2015 and Rust 2018.\n" +"\n" " * The editions are allowed to make backwards incompatible changes to\n" -" the language." -msgstr " * 에디션은 이전 에디션과 호환이 되지 않을 수 있습니다." - -#: src/cargo/rust-ecosystem.md:38 -msgid "" +" the language.\n" +"\n" " * To prevent breaking code, editions are opt-in: you select the\n" -" edition for your crate via the `Cargo.toml` file." -msgstr " * 에디션이 바뀌면서 프로그램이 의도치 않게 깨지는 문제를 막기 위해, 각 프로그램은 자신이 빌드될 에디션을 명시적으로 `Cargo.toml`에 지정해야 합니다." - -#: src/cargo/rust-ecosystem.md:41 -msgid "" +" edition for your crate via the `Cargo.toml` file.\n" +"\n" " * To avoid splitting the ecosystem, Rust compilers can mix code\n" -" written for different editions." -msgstr " * 러스트 생태계가 에디션 별로 파편회 되는 것을 막기 위해, 러스트 컴파일러는 서로 다른 에디션에서 작성된 코드들을 하나의 바이너리로 묶을 수 있습니다." - -#: src/cargo/rust-ecosystem.md:44 -msgid " * Mention that it is quite rare to ever use the compiler directly not through `cargo` (most users never do)." -msgstr " * `cargo`를 사용하지 않고 컴파일러를 직접 사용하는 경우는 거의 없음을 언급해 주시기 바랍니다." - -#: src/cargo/rust-ecosystem.md:46 -msgid "" +" written for different editions.\n" +"\n" +" * Mention that it is quite rare to ever use the compiler directly not through `cargo` (most users never do).\n" +"\n" " * It might be worth alluding that Cargo itself is an extremely powerful and comprehensive tool. It is capable of many advanced features including but not limited to: \n" " * Project/package structure\n" " * [workspaces]\n" @@ -1364,6 +1388,22 @@ msgid "" " * It is also extensible with sub command plugins as well (such as [cargo clippy]).\n" " * Read more from the [official Cargo Book]" msgstr "" +"* 러스트는 6주마다 새로운 릴리즈가 발표되며 이전 릴리즈와의 호환성을 유지하고 있습니다.\n" +"\n" +"* 릴리즈는 3가지 버전으로 제공됩니다: \"stable\", \"beta\" 그리고 \"nightly\".\n" +"\n" +"* 새로운 기능은 \"nightly\" -> \"beta\" -(6주 후)-> \"stable\" 로 변경됩니다.\n" +"\n" +"* 러스트는 [에디션][editions]으로 구분됩니다. 현재는 Rust 2021 에디션입니다. 이 전 에디션으로 Rust 2015와 Rust 2018이 있습니다.\n" +"\n" +" * 에디션은 이전 에디션과 호환이 되지 않을 수 있습니다.\n" +"\n" +" * 에디션이 바뀌면서 프로그램이 의도치 않게 깨지는 문제를 막기 위해, 각 프로그램은 자신이 빌드될 에디션을 명시적으로 `Cargo.toml`에 지정해야 합니다.\n" +"\n" +" * 러스트 생태계가 에디션 별로 파편회 되는 것을 막기 위해, 러스트 컴파일러는 서로 다른 에디션에서 작성된 코드들을 하나의 바이너리로 묶을 수 있습니다.\n" +"\n" +" * `cargo`를 사용하지 않고 컴파일러를 직접 사용하는 경우는 거의 없음을 언급해 주시기 바랍니다.\n" +"\n" " * 카고 자체가 매우 강력하고 포괄적인 도구임을 적극적으로 알리세요.\n" " 카고는 다음과 같은 다양한 고급 기능을 제공합니다.\n" " * 프로젝트/패키지 구조화\n" @@ -1374,30 +1414,6 @@ msgstr "" " * [cargo clippy]와 같은 하위 플러그인으로 확장 가능\n" " * [공식 Cargo Book][official Cargo Book]에서 자세한 사항을 확인하시기 바랍니다." -#: src/cargo/rust-ecosystem.md:55 -msgid "[editions]: https://doc.rust-lang.org/edition-guide/" -msgstr "[editions]: https://doc.rust-lang.org/edition-guide/" - -#: src/cargo/rust-ecosystem.md:57 -msgid "[workspaces]: https://doc.rust-lang.org/cargo/reference/workspaces.html" -msgstr "[workspaces]: https://doc.rust-lang.org/cargo/reference/workspaces.html" - -#: src/cargo/rust-ecosystem.md:59 -msgid "[build scripting]: https://doc.rust-lang.org/cargo/reference/build-scripts.html" -msgstr "[build scripting]: https://doc.rust-lang.org/cargo/reference/build-scripts.html" - -#: src/cargo/rust-ecosystem.md:61 -msgid "[global installation]: https://doc.rust-lang.org/cargo/commands/cargo-install.html" -msgstr "[global installation]: https://doc.rust-lang.org/cargo/commands/cargo-install.html" - -#: src/cargo/rust-ecosystem.md:63 -msgid "[cargo clippy]: https://github.com/rust-lang/rust-clippy" -msgstr "[cargo clippy]: https://github.com/rust-lang/rust-clippy" - -#: src/cargo/rust-ecosystem.md:65 -msgid "[official Cargo Book]: https://doc.rust-lang.org/cargo/" -msgstr "[official Cargo Book]: https://doc.rust-lang.org/cargo/" - #: src/cargo/code-samples.md:1 msgid "# Code Samples in This Training" msgstr "# 강의에서의 코드 샘플" @@ -1449,16 +1465,16 @@ msgstr "강의에서 대부분의 코드 샘플은 위와 같이 수정할수 #: src/cargo/code-samples.md:27 msgid "" "* The embedded playgrounds cannot execute unit tests. Copy-paste the\n" -" code and open it in the real Playground to demonstrate unit tests." -msgstr "* 유닛 테스트는 내장 플레이그라운드에서 실행이 안됩니다. 외부 플레이그라운드 사이트에 붙여넣어 테스트를 실행하시기 바랍니다." - -#: src/cargo/code-samples.md:30 -msgid "" +" code and open it in the real Playground to demonstrate unit tests.\n" +"\n" "* The embedded playgrounds lose their state the moment you navigate\n" " away from the page! This is the reason that the students should\n" " solve the exercises using a local Rust installation or via the\n" " Playground." -msgstr "* 내장된 플레이그라운드에서는 페이지 이동시 작성된 모든 내용이 사라집니다. 따라서 로컬 환경이나 외부 플레이그라운드 사이트에서 연습문제를 해결하는 것이 좋습니다." +msgstr "" +"* 유닛 테스트는 내장 플레이그라운드에서 실행이 안됩니다. 외부 플레이그라운드 사이트에 붙여넣어 테스트를 실행하시기 바랍니다.\n" +"\n" +"* 내장된 플레이그라운드에서는 페이지 이동시 작성된 모든 내용이 사라집니다. 따라서 로컬 환경이나 외부 플레이그라운드 사이트에서 연습문제를 해결하는 것이 좋습니다." #: src/cargo/running-locally.md:1 msgid "# Running Code Locally with Cargo" @@ -1489,27 +1505,18 @@ msgid "" msgstr "정상적으로 설치가 되었으면 강의의 코드 블록중 하나를 아래 단계를 따라 로컬에서 실행할 수 있습니다:" #: src/cargo/running-locally.md:18 -msgid "1. Click the \"Copy to clipboard\" button on the example you want to copy." -msgstr "1. 예시 블록에 있는 \"Copy to clipboard\"버튼을 클릭해서 복사합니다." - -#: src/cargo/running-locally.md:20 -msgid "2. Use `cargo new exercise` to create a new `exercise/` directory for your code:" -msgstr "2. 터미널에서 `cargo new exercise`를 입력해서 새로운 `exercise/` 폴더를 만듭니다:" - -#: src/cargo/running-locally.md:22 msgid "" +"1. Click the \"Copy to clipboard\" button on the example you want to copy.\n" +"\n" +"2. Use `cargo new exercise` to create a new `exercise/` directory for your code:\n" +"\n" " ```shell\n" " $ cargo new exercise\n" " Created binary (application) `exercise` package\n" -" ```" -msgstr "" - -#: src/cargo/running-locally.md:27 -msgid "3. Navigate into `exercise/` and use `cargo run` to build and run your binary:" -msgstr "3. `exercise/` 폴더로 이동한 후, `cargo run` 커맨드로 코드를 실행합니다:" - -#: src/cargo/running-locally.md:29 -msgid "" +" ```\n" +"\n" +"3. Navigate into `exercise/` and use `cargo run` to build and run your binary:\n" +"\n" " ```shell\n" " $ cd exercise\n" " $ cargo run\n" @@ -1517,57 +1524,77 @@ msgid "" " Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" " Running `target/debug/exercise`\n" " Hello, world!\n" -" ```" -msgstr "" - -#: src/cargo/running-locally.md:38 -msgid "" +" ```\n" +"\n" "4. Replace the boiler-plate code in `src/main.rs` with your own code. For\n" -" example, using the example on the previous page, make `src/main.rs` look like" -msgstr "4. `src/main.rs`에 코드를 작성합니다. 예를 들어 이전 페이지의 소스를 아래와 같이 `src/main.rs`에 작성합니다" - -#: src/cargo/running-locally.md:41 -msgid "" +" example, using the example on the previous page, make `src/main.rs` look like\n" +"\n" " ```rust\n" " fn main() {\n" " println!(\"Edit me!\");\n" " }\n" -" ```" -msgstr "" - -#: src/cargo/running-locally.md:47 -msgid "5. Use `cargo run` to build and run your updated binary:" -msgstr "5. `cargo run`커맨드로 소스를 빌드하고 실행합니다:" - -#: src/cargo/running-locally.md:49 -msgid "" +" ```\n" +"\n" +"5. Use `cargo run` to build and run your updated binary:\n" +"\n" " ```shell\n" " $ cargo run\n" " Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" " Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" " Running `target/debug/exercise`\n" " Edit me!\n" -" ```" -msgstr "" - -#: src/cargo/running-locally.md:57 -msgid "" +" ```\n" +"\n" "6. Use `cargo check` to quickly check your project for errors, use `cargo build`\n" " to compile it without running it. You will find the output in `target/debug/`\n" " for a normal debug build. Use `cargo build --release` to produce an optimized\n" -" release build in `target/release/`." -msgstr "6. `cargo check`커맨드는 빠르게 에러를 확인할 수 있습니다. `cargo build`는 실행없이 컴파일만 합니다. 이 경우에 `target/debug/`폴더에서 output을 확인 할 수 있습니다. `cargo build --release`커맨드는 릴리즈 버전용 최적화를 켜서 컴파일하며 `target/release/`폴더에서 확인 할 수 있습니다." - -#: src/cargo/running-locally.md:62 -msgid "" +" release build in `target/release/`.\n" +"\n" "7. You can add dependencies for your project by editing `Cargo.toml`. When you\n" " run `cargo` commands, it will automatically download and compile missing\n" " dependencies for you." -msgstr "7. `Cargo.toml`파일에는 의존성 패키지를 추가할 수 있습니다. `cargo`커맨드를 실행하면 자동으로 의존성 패키지를 다운로드하고 컴파일 까지 해 줍니다." - -#: src/cargo/running-locally.md:66 -msgid "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" msgstr "" +"1. 예시 블록에 있는 \"Copy to clipboard\" 버튼을 클릭해서 복사합니다.\n" +"\n" +"2. 터미널에서 `cargo new exercise`를 입력해서 새로운 `exercise/` 폴더를 만듭니다:\n" +"\n" +" ```shell\n" +" $ cargo new exercise\n" +" Created binary (application) `exercise` package\n" +" ```\n" +"\n" +"3. `exercise/` 폴더로 이동한 후, `cargo run` 커맨드로 코드를 실행합니다:\n" +"\n" +" ```shell\n" +" $ cd exercise\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +" Running `target/debug/exercise`\n" +" Hello, world!\n" +" ```\n" +"\n" +"4. `src/main.rs`에 코드를 작성합니다. 예를 들어 이전 페이지의 소스를 아래와 같이 `src/main.rs`에 작성합니다\n" +"\n" +" ```rust\n" +" fn main() {\n" +" println!(\"Edit me!\");\n" +" }\n" +" ```\n" +"\n" +"5. `cargo run`커맨드로 소스를 빌드하고 실행합니다:\n" +"\n" +" ```shell\n" +" $ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +" Running `target/debug/exercise`\n" +" Edit me!\n" +" ```\n" +"\n" +"6. `cargo check`커맨드는 빠르게 에러를 확인할 수 있습니다. `cargo build`는 실행없이 컴파일만 합니다. 이 경우에 `target/debug/`폴더에서 output을 확인 할 수 있습니다. `cargo build --release`커맨드는 릴리즈 버전용 최적화를 켜서 컴파일하며 `target/release/`폴더에서 확인 할 수 있습니다.\n" +"\n" +"7. `Cargo.toml`파일에는 의존성 패키지를 추가할 수 있습니다. `cargo`커맨드를 실행하면 자동으로 의존성 패키지를 다운로드하고 컴파일 까지 해 줍니다." #: src/cargo/running-locally.md:70 msgid "" @@ -1589,18 +1616,18 @@ msgstr "강의 첫 날입니다. 오늘 배울 것이 참 많습니다:" #: src/welcome-day-1.md:6 msgid "" "* Basic Rust syntax: variables, scalar and compound types, enums, structs,\n" -" references, functions, and methods." -msgstr "* 러스트 기본 문법: 변수, 스칼라 / 복합 타입, 열거형, 구조체, 참조형, 함수와 메서드." - -#: src/welcome-day-1.md:9 -msgid "" +" references, functions, and methods.\n" +"\n" "* Memory management: stack vs heap, manual memory management, scope-based memory\n" -" management, and garbage collection." -msgstr "* 메모리 관리: 스택과 힙, 수동 메모리 관리, 스코프(범위)기반 메모리 관리, 가비지 컬렉션(GC)" - -#: src/welcome-day-1.md:12 -msgid "* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." -msgstr "* 소유권: Move 문법, 복사와 복제, 빌림, 수명." +" management, and garbage collection.\n" +"\n" +"* Ownership: move semantics, copying and cloning, borrowing, and lifetimes." +msgstr "" +"* 러스트 기본 문법: 변수, 스칼라 / 복합 타입, 열거형, 구조체, 참조형, 함수와 메서드.\n" +"\n" +"* 메모리 관리: 스택과 힙, 수동 메모리 관리, 스코프(범위)기반 메모리 관리, 가비지 컬렉션(GC)\n" +"\n" +"* 소유권: Move 문법, 복사와 복제, 빌림, 수명." #: src/welcome-day-1.md:16 msgid "Please remind the students that:" @@ -1636,7 +1663,7 @@ msgstr "첫 날 강의의 목표는, 러스트에서 그 유명한 빌림 확인 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 "만약 당신이 강의실에서 가르치고 있다면, 이 슬라이드는 일정을 검토하기에 적합한 곳입니다. 하루치 강의를 아래처럼 오전 오후로 나누어 진행하는 것을 추천합니다. (슬라이드가 그런식으로나뉘어 있습니다.)" +msgstr "만약 당신이 강의실에서 가르치고 있다면, 이 슬라이드는 일정을 검토하기에 적합한 곳입니다. 하루치 강의를 아래처럼 오전 오후로 나누어 진행하는 것을 추천합니다. (슬라이드가 그런식으로 나뉘어 있습니다.)" #: src/welcome-day-1.md:36 msgid "" @@ -1705,10 +1732,6 @@ msgstr "" "* 별도의 런타임을 필요로 하지 않으며, 가비지 컬렉션도 없음.\n" "* 성능을 타협하지 않으면서도 안정성과 안전에 중점을 둠." -#: src/welcome-day-1/what-is-rust.md:31 -msgid "[1]: https://blog.rust-lang.org/2015/05/15/Rust-1.0.html" -msgstr "" - #: src/hello-world.md:1 msgid "# Hello World!" msgstr "# Hello World!" @@ -1756,18 +1779,24 @@ msgstr "이 슬라이드는 학생들이 러스트 코드에 익숙해지기 위 msgid "" "* Rust is very much like other languages in the C/C++/Java tradition. It is\n" " imperative (not functional) and it doesn't try to reinvent things unless\n" -" absolutely necessary." -msgstr "* 러스트는 C/C++/Java와 같은 전통적인 다른 언어와 매우 유사합니다. 러스트는 절차적(함수형 아님) 언어입니다. 정말로 필요한 경우가 아니라면, 러스트는 이미 존재하는 것을 새로 구현하려고 하지 않습니다." - -#: src/hello-world.md:31 -msgid "* Rust is modern with full support for things like Unicode." -msgstr "* 러스트는 유니코드 지원과 같은 현대 언어의 특징을 전부 지원합니다." - -#: src/hello-world.md:33 -msgid "" +" absolutely necessary.\n" +"\n" +"* Rust is modern with full support for things like Unicode.\n" +"\n" "* Rust uses macros for situations where you want to have a variable number of\n" -" arguments (no function [overloading](basic-syntax/functions-interlude.md))." -msgstr "* 러스트는 인자의 개수를 사전에 지정할 수 없는 상황에서 함수 [오버로딩](basic-syntax/functions-interlude.md)대신 매크로를 사용합니다." +" arguments (no function [overloading](basic-syntax/functions-interlude.md)).\n" +"\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)." +msgstr "" +"* 러스트는 C/C++/Java와 같은 전통적인 다른 언어와 매우 유사합니다. 러스트는 절차적(함수형 아님) 언어입니다. 정말로 필요한 경우가 아니라면, 러스트는 이미 존재하는 것을 새로 구현하려고 하지 않습니다.\n" +"\n" +"* 러스트는 유니코드 지원과 같은 현대 언어의 특징을 전부 지원합니다.\n" +"\n" +"* 러스트는 인자의 개수를 사전에 지정할 수 없는 상황에서 함수 [오버로딩](basic-syntax/functions-interlude.md)대신 매크로를 사용합니다.\n" +"\n" +"* 똑똑한 매크로(hygienic macro)는 매크로가 사용되는 스코프에서 의도치 않게 변수를 가로채지 않습니다. 사실 러스트 매크로는 완전히 hygenic하지는 않습니다. [링크](https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene.html)를 참고하세요." #: src/hello-world/small-example.md:1 msgid "# Small Example" @@ -1821,31 +1850,29 @@ msgstr "이 코드는 콜라츠 추측(Collatz conjecture)으로 구현됩니다 #: src/hello-world/small-example.md:29 msgid "" "* Explain that all variables are statically typed. Try removing `i32` to trigger\n" -" type inference. Try with `i8` instead and trigger a runtime integer overflow." -msgstr "* 모든 변수가 컴파일 시 정해진 타입을 가짐을 설명합니다. `i32`를 삭제하여 컴파일러가 타입 추론을 하도록 해 봅니다. `i32`을 `i8`로 변경하여 런타임 오버플로를 유발해 볼 수 있습니다." - -#: src/hello-world/small-example.md:32 -msgid "* Change `let mut x` to `let x`, discuss the compiler error." -msgstr "* `let mut x`를 `let x`로 수정하여 컴파일 오류에 대해 토론합니다." - -#: src/hello-world/small-example.md:34 -msgid "" +" type inference. Try with `i8` instead and trigger a runtime integer overflow.\n" +"\n" +"* Change `let mut x` to `let x`, discuss the compiler error.\n" +"\n" "* Show how `print!` gives a compilation error if the arguments don't match the\n" -" format string." -msgstr "* 인자가 포맷 문자열과 일치하지 않는 경우 `print!`에서 컴파일 오류가 발생함을 언급하는 것도 좋습니다." - -#: src/hello-world/small-example.md:37 -msgid "" +" format string.\n" +"\n" "* Show how you need to use `{}` as a placeholder if you want to print an\n" -" expression which is more complex than just a single variable." -msgstr "* 단일 변수보다 복잡한 식을 출려하려면 `{}`을 자리 표시자로 사용하는 방법을 보여 줍니다." - -#: src/hello-world/small-example.md:40 -msgid "" +" expression which is more complex than just a single variable.\n" +"\n" "* Show the students the standard library, show them how to search for `std::fmt`\n" " 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 "* 학생들에게 표준 라이브러리가 어디 있는지 알려 주고는, `print!`가 지원하는 포맷팅 언어의 문법을 알기 위해 `std::fmt`를 검색해야 한다는 것을 가르치세요.학생들이 표준 라이브러리의 검색 기능에 익숙해 지도록 하는 것이 중요합니다." +msgstr "" +"* 모든 변수가 컴파일 시 정해진 타입을 가짐을 설명합니다. `i32`를 삭제하여 컴파일러가 타입 추론을 하도록 해 봅니다. `i32`을 `i8`로 변경하여 런타임 오버플로를 유발해 볼 수 있습니다.\n" +"\n" +"* `let mut x`를 `let x`로 수정하여 컴파일 오류에 대해 토론합니다.\n" +"\n" +"* 인자가 포맷 문자열과 일치하지 않는 경우 `print!`에서 컴파일 오류가 발생함을 언급하는 것도 좋습니다.\n" +"\n" +"* 단일 변수보다 복잡한 식을 출려하려면 `{}`을 자리 표시자로 사용하는 방법을 보여 줍니다.\n" +"\n" +"* 학생들에게 표준 라이브러리가 어디 있는지 알려 주고는, `print!`가 지원하는 포맷팅 언어의 문법을 알기 위해 `std::fmt`를 검색해야 한다는 것을 가르치세요.학생들이 표준 라이브러리의 검색 기능에 익숙해 지도록 하는 것이 중요합니다." #: src/why-rust.md:1 msgid "# Why Rust?" @@ -1876,16 +1903,16 @@ 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" " have the memory unsafety issues. In addition, you get a modern language with\n" -" constructs like pattern matching and built-in dependency management." -msgstr "* C/C++: 러스트는 '빌림'검사기를 통해서 수행중에 발생할 수 있는 모든 에러를 제거합니다. 러스트는 C와 C++과 비슷한 수준의 성능을 보여주면서도, 그 언어들에서 종종 발생하는 메모리 관련 오류가 없습니다. 또한, 패턴 매칭이나, 기본적으로 제공되는 종속성 관리와 같은 현대적인 언어의 기능들을 제공합니다." - -#: src/why-rust.md:19 -msgid "" +" constructs like pattern matching and built-in dependency management.\n" +"\n" "* Experience with Java, Go, Python, JavaScript...: You get the same memory safety\n" " as in those languages, plus a similar high-level language feeling. In addition\n" " 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 "* Java, Go, Python, JaveScript: 이 언어들과 동일한 메모리 안정성과 함께, '하이레벨'언어의 느낌을 느낄 수 있습니다. 거기에 더해, 가비지 컬렉터가 없는 C/C++와 유사한 수준의 빠르고 예측 가능한 성능을 기대할 수 있습니다. 그리고 필요한 경우 저수준 하드웨어를 다루는 코드로 작성할 수 있습니다." +msgstr "" +"* C/C++: 러스트는 '빌림'검사기를 통해서 수행중에 발생할 수 있는 모든 에러를 제거합니다. 러스트는 C와 C++과 비슷한 수준의 성능을 보여주면서도, 그 언어들에서 종종 발생하는 메모리 관련 오류가 없습니다. 또한, 패턴 매칭이나, 기본적으로 제공되는 종속성 관리와 같은 현대적인 언어의 기능들을 제공합니다.\n" +"\n" +"* Java, Go, Python, JaveScript: 이 언어들과 동일한 메모리 안정성과 함께, '하이레벨'언어의 느낌을 느낄 수 있습니다. 거기에 더해, 가비지 컬렉터가 없는 C/C++와 유사한 수준의 빠르고 예측 가능한 성능을 기대할 수 있습니다. 그리고 필요한 경우 저수준 하드웨어를 다루는 코드로 작성할 수 있습니다." #: src/why-rust/compile-time.md:1 msgid "# Compile Time Guarantees" @@ -1943,13 +1970,6 @@ msgid "" "as \"Pretty much no *accidental* memory leaks\"." msgstr "본 강의에서는 \"메모리 누출 없음\"을 \"우발적인 메모리 누출 없음\"으로 이해해야 합니다." -#: src/why-rust/compile-time.md:31 -msgid "" -"[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak\n" -"[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n" -"[reference cycle]: https://doc.rust-lang.org/book/ch15-06-reference-cycles.html" -msgstr "" - #: src/why-rust/runtime.md:1 msgid "# Runtime Guarantees" msgstr "# 런타임 시 보장되는 것들" @@ -1971,16 +1991,16 @@ 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" " semantics. By default, you get panics in debug mode (`cargo build`)\n" -" and wrap-around in release mode (`cargo build --release`)." -msgstr "* 정수형 오버플로우는 컴파일 타임 플레그를 통해 정의됩니다. 옵션은 패닉(프로그램 크레시) 혹은 올림(wrap-around)입니다. 기본적으로 디버그 모드(`cargo build`)에서는 패닉이, 릴리즈 모드(`cargo build --release`)에서는 wrap-around가 발생합니다." - -#: src/why-rust/runtime.md:17 -msgid "" +" and wrap-around in release mode (`cargo build --release`).\n" +"\n" "* Bounds checking cannot be disabled with a compiler flag. It can also\n" " not be disabled directly with the `unsafe` keyword. However,\n" " `unsafe` allows you to call functions such as `slice::get_unchecked`\n" " which does not do bounds checking." -msgstr "* 컴파일 플래그를 사용하여 경계체크를 무력화 할 수 없습니다. `unsafe`를 사용하더라도 마찬가지입니다. 하지만 `unsafe`에서 호출 가능한 `slice::get_unchecked`같은 함수는 경계 검사를 수행하지 않습니다." +msgstr "" +"* 정수형 오버플로우는 컴파일 타임 플레그를 통해 정의됩니다. 옵션은 패닉(프로그램 크레시) 혹은 올림(wrap-around)입니다. 기본적으로 디버그 모드(`cargo build`)에서는 패닉이, 릴리즈 모드(`cargo build --release`)에서는 wrap-around가 발생합니다.\n" +"\n" +"* 컴파일 플래그를 사용하여 경계체크를 무력화 할 수 없습니다. `unsafe`를 사용하더라도 마찬가지입니다. 하지만 `unsafe`에서 호출 가능한 `slice::get_unchecked`같은 함수는 경계 검사를 수행하지 않습니다." #: src/why-rust/modern.md:1 msgid "# Modern Features" @@ -2028,58 +2048,34 @@ msgid "" "* Zero-cost abstractions, similar to C++, means that you don't have to 'pay'\n" " for higher-level programming constructs with memory or CPU. For example,\n" " writing a loop using `for` should result in roughly the same low level\n" -" instructions as using the `.iter().fold()` construct." -msgstr "* C++ 와 유사하게 제로 코스트 추상화는 CPU나 메모리를 사용하여 상위레벨 프로그래밍 구조를 만드는데 '비용'을 지불할 필요가 없습니다. 예를 들어 `for` 루프와와 `iter().fold()` 구조를 사용하는 것과 거의 동일한 낮은 수준의 명령어가 생성될 것 입니다." - -#: src/why-rust/modern.md:28 -msgid "" +" instructions as using the `.iter().fold()` construct.\n" +"\n" "* It may be worth mentioning that Rust enums are 'Algebraic Data Types', also\n" " known as 'sum types', which allow the type system to express things like\n" -" `Option` and `Result`." -msgstr "* 러스트의 열거형(enum)은 합계 타입(sum type)으로 알려진 대수학적 데이터형(Algebraic Data Type)으로, 타입 시스템이 `Option`와 `Result`등을 표현할 수 있게 해줍니다." - -#: src/why-rust/modern.md:32 -msgid "" +" `Option` and `Result`.\n" +"\n" "* Remind people to read the errors --- many developers have gotten used to\n" " ignore lengthy compiler output. The Rust compiler is significantly more\n" " talkative than other compilers. It will often provide you with _actionable_\n" -" feedback, ready to copy-paste into your code." -msgstr "* 오류를 읽어보시기 바랍니다 --- 오랜기간 많은 개발자들이 컴파일러 출력을 무시하는데 익숙해져 있습니다. 러스트 컴파일러는 다른 컴파일러보다 더 수다스럽고, 복사-붙여넣기 할 수 있는 정도의 코드 피드백을 제공하는 경우가 많습니다." - -#: src/why-rust/modern.md:37 -msgid "" +" feedback, ready to copy-paste into your code.\n" +"\n" "* The Rust standard library is small compared to languages like Java, Python,\n" " and Go. Rust does not come with several things you might consider standard and\n" -" essential:" -msgstr "* 러스트 표준 라이브러리는 Java, Python이나 Go와 같은 언어에 비해서 규모가 작습니다. 당연히 포함되어야 한다고 생각할 수도 있는 아래와 같은 것들이 러스트의 표준 라이브러리에 없습니다:" - -#: src/why-rust/modern.md:41 -msgid "" +" essential:\n" +"\n" " * a random number generator, but see [rand].\n" " * support for SSL or TLS, but see [rusttls].\n" -" * support for JSON, but see [serde_json]." -msgstr "" -" * 난수 생성기, 하지만 [rand]문서를 참조하시기 바랍니다.\n" -" * SSL 또는 TLS지원, 하지만 [rusttls]문서를 참조하시기 바랍니다.\n" -" * JSON 지원, 하지만 [serde_json] 문서를 참조하시기 바랍니다." - -#: src/why-rust/modern.md:45 -msgid "" +" * support for JSON, but see [serde_json].\n" +"\n" " The reasoning behind this is that functionality in the standard library cannot\n" " go away, so it has to be very stable. For the examples above, the Rust\n" " community is still working on finding the best solution --- and perhaps there\n" -" isn't a single \"best solution\" for some of these things." -msgstr " 그 이유는 표준 라이브러리에서 한 번 어떤 기능을 제공하면 뺄 수 없으며, 매우 안정적이어야 하기 때문입니다. 위에 언급한 기능들은 아직 러스트 커뮤니티가 최고의 솔루션을 찾지 못했기 때문에 표준 라이브러리에 포함되지 않았습니다. 어쩌면 이들 중 몇 개는 '최고의 솔루션'이 아예 존재할 수 없을 지도 모릅니다." - -#: src/why-rust/modern.md:50 -msgid "" +" isn't a single \"best solution\" for some of these things.\n" +"\n" " Rust comes with a built-in package manager in the form of Cargo and this makes\n" " it trivial to download and compile third-party crates. A consequence of this\n" -" is that the standard library can be smaller." -msgstr " 러스트는 카고라는 패키지 관리자가 내장되어 있고, 서드파티 크레이트를 다운로드, 컴파일 하기 매우 쉽습니다. 이 또한 표준 라이브러리가 작은 이유입니다." - -#: src/why-rust/modern.md:54 -msgid "" +" is that the standard library can be smaller.\n" +"\n" " Discovering good third-party crates can be a problem. Sites like\n" " help with this by letting you compare health metrics for\n" " crates to find a good and trusted one.\n" @@ -2087,21 +2083,26 @@ msgid "" "* [rust-analyzer] is a well supported LSP implementation used in major\n" " IDEs and text editors." msgstr "" +"* C++ 와 유사하게 제로 코스트 추상화는 CPU나 메모리를 사용하여 상위레벨 프로그래밍 구조를 만드는데 '비용'을 지불할 필요가 없습니다. 예를 들어 `for` 루프와와 `iter().fold()` 구조를 사용하는 것과 거의 동일한 낮은 수준의 명령어가 생성될 것 입니다.\n" +"\n" +"* 러스트의 열거형(enum)은 합계 타입(sum type)으로 알려진 대수학적 데이터형(Algebraic Data Type)으로, 타입 시스템이 `Option`와 `Result`등을 표현할 수 있게 해줍니다.\n" +"\n" +"* 오류를 읽어보시기 바랍니다 --- 오랜기간 많은 개발자들이 컴파일러 출력을 무시하는데 익숙해져 있습니다. 러스트 컴파일러는 다른 컴파일러보다 더 수다스럽고, 복사-붙여넣기 할 수 있는 정도의 코드 피드백을 제공하는 경우가 많습니다.\n" +"\n" +"* 러스트 표준 라이브러리는 Java, Python이나 Go와 같은 언어에 비해서 규모가 작습니다. 당연히 포함되어야 한다고 생각할 수도 있는 아래와 같은 것들이 러스트의 표준 라이브러리에 없습니다:\n" +"\n" +" * 난수 생성기, 하지만 [rand]문서를 참조하시기 바랍니다.\n" +" * SSL 또는 TLS지원, 하지만 [rusttls]문서를 참조하시기 바랍니다.\n" +" * JSON 지원, 하지만 [serde_json] 문서를 참조하시기 바랍니다.\n" +"\n" +" 그 이유는 표준 라이브러리에서 한 번 어떤 기능을 제공하면 뺄 수 없으며, 매우 안정적이어야 하기 때문입니다. 위에 언급한 기능들은 아직 러스트 커뮤니티가 최고의 솔루션을 찾지 못했기 때문에 표준 라이브러리에 포함되지 않았습니다. 어쩌면 이들 중 몇 개는 '최고의 솔루션'이 아예 존재할 수 없을 지도 모릅니다.\n" +"\n" +" 러스트는 카고라는 패키지 관리자가 내장되어 있고, 서드파티 크레이트를 다운로드, 컴파일 하기 매우 쉽습니다. 이 또한 표준 라이브러리가 작은 이유입니다.\n" +"\n" " 좋은 서드파티 크레이트를 찾는 것은 어렵습니다. 와 같은 사이트가 신뢰할수 있는 좋은 크레이트를 비교하여 찾는데 좋습니다.\n" +"\n" "* [rust-analyzer]는 주요 IDE나 텍스트 에디터에서 사용되는 러스트용 LSP서버 입니다." -#: src/why-rust/modern.md:61 -msgid "" -"[rand]: https://docs.rs/rand/\n" -"[rusttls]: https://docs.rs/rustls/\n" -"[serde_json]: https://docs.rs/serde_json/\n" -"[rust-analyzer]: https://rust-analyzer.github.io/" -msgstr "" -"[rand]: https://docs.rs/rand/\n" -"[rusttls]: https://docs.rs/rustls/\n" -"[serde_json]: https://docs.rs/serde_json/\n" -"[rust-analyzer]: https://rust-analyzer.github.io/" - #: src/basic-syntax.md:1 msgid "# Basic Syntax" msgstr "# 기본 문법" @@ -2220,43 +2221,37 @@ msgstr "배열:" msgid "" "* Arrays have elements of the same type, `T`, and length, `N`, which is a compile-time constant.\n" " Note that the length of the array is *part of its type*, which means that `[u8; 3]` and\n" -" `[u8; 4]` are considered two different types." -msgstr "* 배열은, 같은 타입 `T`의 값이 `N`개 있는 것입니다. 여기서 `N`은 컴파일 타임에 결정된 값이어야 합니다. 이 길이도 타입의 일부입니다. 따라서, `[u8; 3]`와 `[u8; 4]`은 서로 다른 타입입니다." - -#: src/basic-syntax/compound-types.md:38 -msgid "* We can use literals to assign values to arrays." -msgstr "* 리터럴을 사용하여 배열에 값을 할당할 수 있습니다." - -#: src/basic-syntax/compound-types.md:40 -msgid "" +" `[u8; 4]` are considered two different types.\n" +"\n" +"* We can use literals to assign values to arrays.\n" +"\n" "* In the main function, the print statement asks for the debug implementation with the `?` format\n" " parameter: `{}` gives the default output, `{:?}` gives the debug output. We\n" " could also have used `{a}` and `{a:?}` without specifying the value after the\n" -" format string." -msgstr "* 포매팅 문자열에서 `?`는 디버깅 출력을 의미합니다. `{}`는 기본 출력이며, `{:?}`는 디버깅 출력입니다. `{a}`와 `{a:?}`와 같이 출력할 변수 이름을 포매팅 문자열에 포함시킬 수도 있으며, 이 경우 인자 `a`는 별도의 인자로 추가하지 않습니다." - -#: src/basic-syntax/compound-types.md:45 -msgid "* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read." -msgstr "* `#`을 추가하면(`{a:#?}`) 좀 더 읽기 쉬운 \"이쁜\" 형태로 출력이 됩니다." +" format string.\n" +"\n" +"* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read." +msgstr "" +"* 배열은, 같은 타입 `T`의 값이 `N`개 있는 것입니다. 여기서 `N`은 컴파일 타임에 결정된 값이어야 합니다. 이 길이도 타입의 일부입니다. 따라서, `[u8; 3]`와 `[u8; 4]`은 서로 다른 타입입니다.\n" +"\n" +"* 리터럴을 사용하여 배열에 값을 할당할 수 있습니다.\n" +"\n" +"* 포매팅 문자열에서 `?`는 디버깅 출력을 의미합니다. `{}`는 기본 출력이며, `{:?}`는 디버깅 출력입니다. `{a}`, `{a:?}`와 같이 출력할 변수 이름을 포매팅 문자열에 포함시킬 수도 있으며, 이 경우 인자 `a`는 별도의 인자로 추가하지 않습니다.\n" +"\n" +"* `#`을 추가하면(`{a:#?}`) 좀 더 읽기 쉬운 \\\"이쁜\\\" 형태로 출력이 됩니다." #: src/basic-syntax/compound-types.md:47 msgid "Tuples:" msgstr "튜플:" #: src/basic-syntax/compound-types.md:49 -msgid "* Like arrays, tuples have a fixed length." -msgstr "* 배열과 마찬가지로 튜플은 고정 길이를 갖습니다." - -#: src/basic-syntax/compound-types.md:51 -msgid "* Tuples group together values of different types into a compound type." -msgstr "* 튜플은 서로 다른 타입의 값들을 하나의 복합 타입으로 묶습니다." - -#: src/basic-syntax/compound-types.md:53 -msgid "* Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`." -msgstr "* 튜플에 속한 값은 `t.0`, `t.1`과 같이 인덱스로 접근할 수 있습니다." - -#: src/basic-syntax/compound-types.md:55 msgid "" +"* Like arrays, tuples have a fixed length.\n" +"\n" +"* Tuples group together values of different types into a compound type.\n" +"\n" +"* Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`.\n" +"\n" "* The empty tuple `()` is also known as the \"unit type\". It is both a type, and\n" " the only valid value of that type - that is to say both the type and its value\n" " are expressed as `()`. It is used to indicate, for example, that a function or\n" @@ -2264,6 +2259,12 @@ msgid "" " * You can think of it as `void` that can be familiar to you from other \n" " programming languages." msgstr "" +"* 배열과 마찬가지로 튜플은 고정 길이를 갖습니다.\n" +"\n" +"* 튜플은 서로 다른 타입의 값들을 하나의 복합 타입으로 묶습니다.\n" +"\n" +"* 튜플에 속한 값은 `t.0`, `t.1`과 같이 인덱스로 접근할 수 있습니다.\n" +"\n" "* 비어있는 튜플`()`은 단위 타입(unit type)이라고도 합니다. 이는 타입이면서 해당 타입의 유일하며 유효한 값입니다. 즉 타입과 값이 모두 `()`입니다. 예를 들어 함수나 식에서 반환 값이 없음을 나타낼 때 사용합니다.\n" " * 다른 언어에서 익숙한 `void` 개념으로 생각할 수 있습니다." @@ -2363,16 +2364,22 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" -" println!(\"a: {a:?}\");" -msgstr "" - -#: src/basic-syntax/slices.md:10 -msgid "" +" println!(\"a: {a:?}\");\n" +"\n" " let s: &[i32] = &a[2..4];\n" " println!(\"s: {s:?}\");\n" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" +" println!(\"a: {a:?}\");\n" +"\n" +" let s: &[i32] = &a[2..4];\n" +" println!(\"s: {s:?}\");\n" +"}\n" +"```" #: src/basic-syntax/slices.md:15 msgid "" @@ -2383,24 +2390,15 @@ msgstr "" "* 질문: `a[3]`을 수정하면 무슨 일이 있어날까요?" #: src/basic-syntax/slices.md:20 -msgid "* We create a slice by borrowing `a` and specifying the starting and ending indexes in brackets." -msgstr "* 슬라이스는 우선 `a`를 빌린다음, 시작과 끝 인덱스를 브래킷(`[]`)안에 지정해서 만듭니다." - -#: src/basic-syntax/slices.md:22 msgid "" +"* We create a slice by borrowing `a` and specifying the starting and ending indexes in brackets.\n" +"\n" "* If the slice starts at index 0, Rust’s range syntax allows us to drop the starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are identical.\n" " \n" -"* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are identical." -msgstr "" -"* 슬라이스가 인덱스 0부터 시작한다면 시작 인덱스는 생략 가능합니다. 즉 `&a[0..a.len()]`와 `&a[..a.len()]` 는 동일합니다.\n" -"* 마지막 인덱스도 생략 가능합니다. 그래서 `&a[2..a.len()]` 와 `&a[2..]`는 동일합니다." - -#: src/basic-syntax/slices.md:26 -msgid "* To easily create a slice of the full array, we can therefore use `&a[..]`." -msgstr "* 따라서 전체 배열에 대한 슬라이스는 `&a[..]`가 됩니다." - -#: src/basic-syntax/slices.md:28 -msgid "" +"* The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are identical.\n" +"\n" +"* To easily create a slice of the full array, we can therefore use `&a[..]`.\n" +"\n" "* `s` is a reference to a slice of `i32`s. Notice that the type of `s` (`&[i32]`) no longer mentions the array length. This allows us to perform computation on slices of different sizes.\n" " \n" "* Slices always borrow from another object. In this example, `a` has to remain 'alive' (in scope) for at least as long as our slice. \n" @@ -2409,8 +2407,18 @@ msgid "" " you cannot do it through `a` after you created a slice, but you can read the data from both `a` and `s` safely. \n" " More details will be explained in the borrow checker section." msgstr "" +"* 슬라이스는 우선 `a`를 빌린다음, 시작과 끝 인덱스를 브래킷(`[]`)안에 지정해서 만듭니다.\n" +"\n" +"* 슬라이스가 인덱스 0부터 시작한다면 시작 인덱스는 생략 가능합니다. 즉 `&a[0..a.len()]`와 `&a[..a.len()]` 는 동일합니다.\n" +"\n" +"* 마지막 인덱스도 생략 가능합니다. 그래서 `&a[2..a.len()]` 와 `&a[2..]`는 동일합니다.\n" +"\n" +"* 따라서 전체 배열에 대한 슬라이스는 `&a[..]`가 됩니다.\n" +"\n" "* `s`는 `i32`들로 이루어진 슬라이스에 대한 참조입니다. `s`의 타입(`&[i32]`)에 배열의 크기가 빠져있음에 주목하시기 바랍니다. 즉, 슬라이스를 이용하면 다양한 길이의 데이터를 다룰 수 있습니다.\n" +"\n" "* 슬라이스는 항상 다른 객체로부터 '빌려' 옵니다. 이 예시에서 객체 `a`는 슬라이스 `s`보다 더 오래 살아 있어야만 합니다.\n" +"\n" "* `a[3]`의 값을 바꿀 수 있냐는 질문은 좋은 질문입니다. 여기에 대한 답은 `a`와 `s`를 통해 데이터를 읽을 수는 있지만 수정할 수는 없으며, 이는 메모리 안전을 위해서라는 것입니다. 왜 그런지에 대한 좀더 구체적인 답은 빌림 검사 부분에서 자세히 설명합니다." #: src/basic-syntax/string-slices.md:1 @@ -2426,11 +2434,8 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let s1: &str = \"World\";\n" -" println!(\"s1: {s1}\");" -msgstr "" - -#: src/basic-syntax/string-slices.md:10 -msgid "" +" println!(\"s1: {s1}\");\n" +"\n" " let mut s2: String = String::from(\"Hello \");\n" " println!(\"s2: {s2}\");\n" " s2.push_str(s1);\n" @@ -2457,21 +2462,13 @@ msgstr "" #: src/basic-syntax/string-slices.md:27 msgid "" "* `&str` introduces a string slice, which is an immutable reference to UTF-8 encoded string data \n" -" stored in a block of memory. String literals (`”Hello”`), are stored in the program’s binary." -msgstr "* `&str`은 문자열 슬라이스의 불변 참조입니다. 러스트에서 문자열은 UTF-8로 인코딩된 데이터를 의미합니다. 문자열 리터럴(`\"Hello\"`)은 프로그램 바이너리에 저장됩니다." - -#: src/basic-syntax/string-slices.md:30 -msgid "" +" stored in a block of memory. String literals (`”Hello”`), are stored in the program’s binary.\n" +"\n" "* Rust’s `String` type is a wrapper around a vector of bytes. As with a `Vec`, it is owned.\n" " \n" "* As with many other types `String::from()` creates a string from a string literal; `String::new()` \n" -" creates a new empty string, to which string data can be added using the `push()` and `push_str()` methods." -msgstr "" -"* 러스트의 `String`타입은 실제로는 문자열을 이루는 바이트에 대한 백터(`Vec`)입니다. `Vec`가 `T`를 소유하고 있듯이, `String`이 가리키고 있는 문자열은 `String`의 소유입니다.\n" -"* 다른 많은 타입들처럼 `String::from`는 문자열 리터럴로부터 문자열을 생성합니다. `String::new()`는 새로운 빈 문자열을 생성합니다. `push()`와 `push_str()`메서드를 사용하여 문자열 데이터를 추가 할 수 있습니다." - -#: src/basic-syntax/string-slices.md:35 -msgid "" +" creates a new empty string, to which string data can be added using the `push()` and `push_str()` methods.\n" +"\n" "* The `format!()` macro is a convenient way to generate an owned string from dynamic values. It \n" " accepts the same format specification as `println!()`.\n" " \n" @@ -2480,14 +2477,19 @@ msgid "" "* For C++ programmers: think of `&str` as `const char*` from C++, but the one that always points \n" " to a valid string in memory. Rust `String` is a rough equivalent of `std::string` from C++ \n" " (main difference: it can only contain UTF-8 encoded bytes and will never use a small-string optimization).\n" -" \n" -"
" +" " msgstr "" +"* `&str`은 문자열 슬라이스의 불변 참조입니다. 러스트에서 문자열은 UTF-8로 인코딩된 데이터를 의미합니다. 문자열 리터럴(`\"Hello\"`)은 프로그램 바이너리에 저장됩니다.\n" +"\n" +"* 러스트의 `String`타입은 실제로는 문자열을 이루는 바이트에 대한 백터(`Vec`)입니다. `Vec`가 `T`를 소유하고 있듯이, `String`이 가리키고 있는 문자열은 `String`의 소유입니다.\n" +"\n" +"* 다른 많은 타입들처럼 `String::from`는 문자열 리터럴로부터 문자열을 생성합니다. `String::new()`는 새로운 빈 문자열을 생성합니다. `push()`와 `push_str()`메서드를 사용하여 문자열 데이터를 추가 할 수 있습니다.\n" +"\n" "* `format!()` 매크로는 변수의 값을 문자열로 변환하는 편리한 방법입니다. 이 매크로는 `println!()` 매크로와 동일한 포맷팅 형식을 지원합니다.\n" +"\n" "* `&`와 범위 연산자를 이용하여 `String`에서 `&str`슬라이스를 빌려올 수 있습니다.\n" -"* 당신이 C++ 프로그래머 라면: `&str`는 C++의 `const char*`와 유사하지만 항상 유효한 문자열을 가리킨다는 점이 다릅니다. 러스트의 `String`은 C++의 `std::string` 과 대략 거의 동일합니다. (주요 차이점: 러스트의 `String`은 UTF-8 인코딩 바이트만 포함할 수 있으며 작은 문자열 최적화(small-string optimization)는 사용하지 않습니다.\n" -" \n" -"
" +"\n" +"* 당신이 C++ 프로그래머 라면: `&str`는 C++의 `const char*`와 유사하지만 항상 유효한 문자열을 가리킨다는 점이 다릅니다. 러스트의 `String`은 C++의 `std::string` 과 대략 거의 동일합니다. (주요 차이점: 러스트의 `String`은 UTF-8 인코딩 바이트만 포함할 수 있으며 작은 문자열 최적화(small-string optimization)는 사용하지 않습니다." #: src/basic-syntax/functions.md:1 msgid "# Functions" @@ -2502,31 +2504,15 @@ msgid "" "```rust,editable\n" "fn main() {\n" " fizzbuzz_to(20); // Defined below, no forward declaration needed\n" -"}" -msgstr "" -"```rust,editable\n" -"fn main() {\n" -" fizzbuzz_to(20); //C/C++ 와 달리 호출부 하단에 정의해도 문제 없습니다.\n" -"}" - -#: src/basic-syntax/functions.md:10 -msgid "" +"}\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" -"}" -msgstr "" -"fn is_divisible_by(lhs: u32, rhs: u32) -> bool {\n" -" if rhs == 0 {\n" -" return false; // Corner case이므로 반환합니다.\n" -" }\n" -" lhs % rhs == 0 // 마지막 표현식은 반환 값입니다.(;없음에 주목)\n" -"}" - -#: src/basic-syntax/functions.md:17 -msgid "" +"}\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" @@ -2534,26 +2520,36 @@ msgid "" " (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) -> () { // `()`는 반환값이 없다는 것을 의미합니다. \n" +"```rust,editable\n" +"fn main() {\n" +" fizzbuzz_to(20); // C/C++ 와 달리 호출부 하단에 정의해도 문제 없습니다.\n" +"}\n" +"\n" +"fn is_divisible_by(lhs: u32, rhs: u32) -> bool {\n" +" if rhs == 0 {\n" +" return false; // Corner case이므로 반환합니다.\n" +" }\n" +" lhs % rhs == 0 // 마지막 표현식은 반환 값입니다.(;없음에 주목)\n" +"}\n" +"\n" +"fn fizzbuzz(n: u32) -> () { // `()`는 반환값이 없다는 것을 의미합니다.\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" -"}" - -#: src/basic-syntax/functions.md:26 -msgid "" -"fn fizzbuzz_to(n: u32) { // `-> ()` is normally omitted\n" -" for i in 1..=n {\n" -" fizzbuzz(i);\n" -" }\n" "}\n" -"```" -msgstr "" +"\n" "fn fizzbuzz_to(n: u32) { // `-> ()` 는 일반적으로 생략합니다.\n" " for i in 1..=n {\n" " fizzbuzz(i);\n" @@ -2568,33 +2564,38 @@ msgid "" "* The last expression in a function body (or any block) becomes the return value. Simply omit the `;` at the end of the expression.\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." +"* 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" +" " msgstr "" "* `main` 함수에서 그 다음에 오는 함수들을 사용할 수 있습니다. 상단에 선언이나 헤더 같은건 필요 없습니다.\n" "* 매개변수를 선언할 때에는 이름을 먼저 쓰고, 타입을 나중에 씁니다. 이름과 타입은 `:` 로 구분합니다. 이는 일부 언어(예를 들어 C)와 반대임에 유의하시기 바랍니다. 마찬가지로, 리턴 타입도 함수의 시작이 아닌 가장 뒷부분에 선언합니다.\n" "* 함수 본문의 마지막 표현식은 반환 값이 됩니다. 간단히, 식 끝에 있는 `;`를 생략하면 됩니다.\n" "* 반환값이 없는 함수의 경우, 유닛 타입 `()`을 반환합니다. `-> ()`가 생략된 경우 컴파일러는 이를 추론합니다.\n" "* `fizzbuzz_to()`함수 내 `for` 반목문의 범위 표현식 중 `=n`은 n까지 포함한다는 의미입니다.\n" -"* `fizzbuzz()`함수의 `match` 표현식은 많은 일을 합니다. 무슨 일이 일어나는지 조금 더 이해하기 쉽도록 아래 코드를 확인하시기 바랍니다." - -#: src/basic-syntax/functions.md:42 -msgid " (Type annotations added for clarity, but they can be elided.)" -msgstr " (명확한 설명을 위해 타입이 명시적으로 선언 되었지만 생략 가능합니다.)" - -#: src/basic-syntax/functions.md:44 -msgid "" +"* `fizzbuzz()`함수의 `match` 표현식은 많은 일을 합니다. 무슨 일이 일어나는지 조금 더 이해하기 쉽도록 아래 코드를 확인하시기 바랍니다.\n" +"\n" +" (명확한 설명을 위해 타입이 명시적으로 선언 되었지만 생략 가능합니다.)\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" -" ```" -msgstr "" - -#: src/basic-syntax/functions.md:52 -msgid " " -msgstr "" +" ```\n" +"\n" +" " #: src/basic-syntax/methods.md:1 src/methods.md:1 msgid "# Methods" @@ -2612,27 +2613,18 @@ msgid "" "struct Rectangle {\n" " width: u32,\n" " height: u32,\n" -"}" -msgstr "" - -#: src/basic-syntax/methods.md:12 -msgid "" +"}\n" +"\n" "impl Rectangle {\n" " fn area(&self) -> u32 {\n" " self.width * self.height\n" -" }" -msgstr "" - -#: src/basic-syntax/methods.md:17 -msgid "" +" }\n" +"\n" " fn inc_width(&mut self, delta: u32) {\n" " self.width += delta;\n" " }\n" -"}" -msgstr "" - -#: src/basic-syntax/methods.md:22 -msgid "" +"}\n" +"\n" "fn main() {\n" " let mut rect = Rectangle { width: 10, height: 5 };\n" " println!(\"old area: {}\", rect.area());\n" @@ -2679,11 +2671,8 @@ msgid "" "```rust,editable\n" "fn pick_one(a: T, b: T) -> T {\n" " if std::process::id() % 2 == 0 { a } else { b }\n" -"}" -msgstr "" - -#: src/basic-syntax/functions-interlude.md:19 -msgid "" +"}\n" +"\n" "fn main() {\n" " println!(\"coin toss: {}\", pick_one(\"heads\", \"tails\"));\n" " println!(\"cash prize: {}\", pick_one(500, 1000));\n" @@ -2699,7 +2688,7 @@ msgstr "* 제네릭을 사용할 때 표준 라이브러리의 `Into`은 타 #: src/basic-syntax/functions-interlude.md:30 msgid "" -msgstr "" +msgstr "" #: src/exercises/day-1/morning.md:1 msgid "# Day 1: Morning Exercises" @@ -2710,12 +2699,14 @@ msgid "In these exercises, we will explore two parts of Rust:" msgstr "이번 연습문제는 러스트의 두 부분을 알아볼 것입니다:" #: src/exercises/day-1/morning.md:5 -msgid "* Implicit conversions between types." -msgstr "* 타입의 묵시적 변환." - -#: src/exercises/day-1/morning.md:7 -msgid "* Arrays and `for` loops." -msgstr "* 배열과 `for` 반복문." +msgid "" +"* Implicit conversions between types.\n" +"\n" +"* Arrays and `for` loops." +msgstr "" +"* 타입의 묵시적 변환.\n" +"\n" +"* 배열과 `for` 반복문." #: src/exercises/day-1/morning.md:11 msgid "A few things to consider while solving the exercises:" @@ -2725,12 +2716,13 @@ msgstr "연습문제를 해결하는데 고려해야 할 사항들:" msgid "" "* Use a local Rust installation, if possible. This way you can get\n" " auto-completion in your editor. See the page about [Using Cargo] for details\n" -" on installing Rust." -msgstr "* 가능하다면 러스트가 설치된 로컬 환경에서 진행하세요. 그러는 편이 텍스트 에디터의 자동완성 기능의 도움을 받을 수 있어서 좋습니다. [카고 사용하기][Using Cargo] 을 참조하시기 바랍니다." - -#: src/exercises/day-1/morning.md:17 -msgid "* Alternatively, use the Rust Playground." -msgstr "* 혹은 러스트 플레이그라운드를 이용할 수 있습니다." +" on installing Rust.\n" +"\n" +"* Alternatively, use the Rust Playground." +msgstr "" +"* 가능하다면 러스트가 설치된 로컬 환경에서 진행하세요. 그러는 편이 텍스트 에디터의 자동완성 기능의 도움을 받을 수 있어서 좋습니다. [카고 사용하기][Using Cargo] 을 참조하시기 바랍니다.\n" +"\n" +"* 혹은 러스트 플레이그라운드를 이용할 수 있습니다." #: src/exercises/day-1/morning.md:19 msgid "" @@ -2744,15 +2736,6 @@ msgstr "페이지 밖으로 이동할 경우 작성한 내용이 소실되기 msgid "After looking at the exercises, you can look at the [solutions] provided." msgstr "연습문제를 살펴 본 후, 제공된 [해답][solutions]을 살펴볼 수 있습니다." -#: src/exercises/day-1/morning.md:24 src/exercises/day-2/morning.md:13 -#: src/exercises/day-3/morning.md:9 src/exercises/day-4/morning.md:14 -msgid "[solutions]: solutions-morning.md" -msgstr "" - -#: src/exercises/day-1/morning.md:26 -msgid "[Using Cargo]: ../../cargo.md" -msgstr "" - #: src/exercises/day-1/implicit-conversions.md:1 msgid "# Implicit Conversions" msgstr "# 묵시적 형변환" @@ -2768,18 +2751,12 @@ msgid "" "```rust,editable,compile_fail\n" "fn multiply(x: i16, y: i16) -> i16 {\n" " x * y\n" -"}" -msgstr "" - -#: src/exercises/day-1/implicit-conversions.md:11 -msgid "" +"}\n" +"\n" "fn main() {\n" " let x: i8 = 15;\n" -" let y: i16 = 1000;" -msgstr "" - -#: src/exercises/day-1/implicit-conversions.md:15 -msgid "" +" let y: i16 = 1000;\n" +"\n" " println!(\"{x} * {y} = {}\", multiply(x, y));\n" "}\n" "```" @@ -2809,28 +2786,22 @@ msgid "" msgstr "이는 사용자 정의 타입에도 동일하게 적용되는 규칙입니다. 따라서 `From`만을 구현해도 `Into`까지 자동으로 구현이 됩니다." #: src/exercises/day-1/implicit-conversions.md:33 -msgid "1. Execute the above program and look at the compiler error." -msgstr "1. 위 예제코드를 실행하고 어떤 컴파일 에러가 발생하는지 확인해 보세요." - -#: src/exercises/day-1/implicit-conversions.md:35 -msgid "2. Update the code above to use `into()` to do the conversion." -msgstr "2. `into()`를 사용하여 코드를 수정하세요." - -#: src/exercises/day-1/implicit-conversions.md:37 msgid "" +"1. Execute the above program and look at the compiler error.\n" +"\n" +"2. Update the code above to use `into()` to do the conversion.\n" +"\n" "3. Change the types of `x` and `y` to other things (such as `f32`, `bool`,\n" " `i128`) to see which types you can convert to which other types. Try\n" " converting small types to big types and the other way around. Check the\n" " [standard library documentation][1] to see if `From` is implemented for\n" " the pairs you check." -msgstr "3. `x`와 `y`를 `f32`이나 `bool`, `i128` 등으로 바꿔서 해당 타입들로 변환이 되는지 확인해보세요. 작은 사이즈 타입에서 큰 사이즈로 변경해보시고 그 반대로도 해보세요. [표준 라이브러리 문서][1]에서 시도해 본 케이스가 구현되어 있는지 확인해 보세요." - -#: src/exercises/day-1/implicit-conversions.md:43 -msgid "" -"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" -"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" -"[3]: https://en.cppreference.com/w/cpp/language/implicit_conversion" msgstr "" +"1. 위 예제코드를 실행하고 어떤 컴파일 에러가 발생하는지 확인해 보세요.\n" +"\n" +"2. `into()`를 사용하여 코드를 수정하세요.\n" +"\n" +"3. `x`와 `y`를 `f32`이나 `bool`, `i128` 등으로 바꿔서 해당 타입들로 변환이 되는지 확인해보세요. 작은 사이즈 타입에서 큰 사이즈로 변경해보시고 그 반대로도 해보세요. [표준 라이브러리 문서][1]에서 시도해 본 케이스가 구현되어 있는지 확인해 보세요." #: src/exercises/day-1/for-loops.md:1 msgid "# Arrays and `for` Loops" @@ -2876,11 +2847,8 @@ msgid "" " for n in array {\n" " print!(\" {n}\");\n" " }\n" -" println!();" -msgstr "" - -#: src/exercises/day-1/for-loops.md:30 -msgid "" +" println!();\n" +"\n" " print!(\"Iterating over range:\");\n" " for i in 0..3 {\n" " print!(\" {}\", array[i]);\n" @@ -2916,55 +2884,62 @@ msgid "" msgstr "아래 코드를 에 복사해서 구현하시면 됩니다:" #: src/exercises/day-1/for-loops.md:52 -#: src/exercises/day-2/health-statistics.md:13 msgid "" "```rust,should_panic\n" "// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]" -msgstr "" -"```rust,should_panic\n" -"// TODO: 구현이 완료되면 아래 줄은 삭제합니다.\n" -"#![allow(unused_variables, dead_code)]" - -#: src/exercises/day-1/for-loops.md:56 -msgid "" +"#![allow(unused_variables, dead_code)]\n" +"\n" "fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" " unimplemented!()\n" -"}" -msgstr "" - -#: src/exercises/day-1/for-loops.md:60 -msgid "" +"}\n" +"\n" "fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" " unimplemented!()\n" -"}" -msgstr "" - -#: src/exercises/day-1/for-loops.md:64 -msgid "" +"}\n" +"\n" "fn main() {\n" " let matrix = [\n" " [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" " [201, 202, 203],\n" " [301, 302, 303],\n" -" ];" -msgstr "" - -#: src/exercises/day-1/for-loops.md:71 -#: src/exercises/day-1/solutions-morning.md:70 -msgid "" +" ];\n" +"\n" " println!(\"matrix:\");\n" -" pretty_print(&matrix);" -msgstr "" - -#: src/exercises/day-1/for-loops.md:74 -msgid "" +" pretty_print(&matrix);\n" +"\n" " let transposed = transpose(matrix);\n" " println!(\"transposed:\");\n" " pretty_print(&transposed);\n" "}\n" "```" msgstr "" +"```rust,should_panic\n" +"// TODO: 구현이 완료되면 아래 줄은 삭제합니다.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" unimplemented!()\n" +"}\n" +"\n" +"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +" unimplemented!()\n" +"}\n" +"\n" +"fn main() {\n" +" let matrix = [\n" +" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" +" [201, 202, 203],\n" +" [301, 302, 303],\n" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" +" let transposed = transpose(matrix);\n" +" println!(\"transposed:\");\n" +" pretty_print(&transposed);\n" +"}\n" +"```" #: src/exercises/day-1/for-loops.md:80 msgid "## Bonus Question" @@ -3040,25 +3015,16 @@ msgid "" "```rust,editable\n" "fn takes_u32(x: u32) {\n" " println!(\"u32: {x}\");\n" -"}" -msgstr "" - -#: src/basic-syntax/type-inference.md:10 -msgid "" +"}\n" +"\n" "fn takes_i8(y: i8) {\n" " println!(\"i8: {y}\");\n" -"}" -msgstr "" - -#: src/basic-syntax/type-inference.md:14 -msgid "" +"}\n" +"\n" "fn main() {\n" " let x = 10;\n" -" let y = 20;" -msgstr "" - -#: src/basic-syntax/type-inference.md:18 -msgid "" +" let y = 20;\n" +"\n" " takes_u32(x);\n" " takes_i8(y);\n" " // takes_u32(y);\n" @@ -3067,13 +3033,15 @@ msgid "" msgstr "" #: src/basic-syntax/type-inference.md:26 +msgid "This slide demonstrates how the Rust compiler infers types based on constraints given by variable declarations and usages." +msgstr "이 슬라이드는, 러스트 컴파일러가 변수가 어떻게 선언되어 있고, 어떻게 사용되는지를 제약 조건으로 삼아서 변수의 타입을 추론하는 모습을 보여줍니다." + +#: src/basic-syntax/type-inference.md:28 msgid "" -"This slide demonstrates how the Rust compiler infers types based on constraints given by variable declarations and usages.\n" -" \n" "It is very important to emphasize that variables declared like this are not of some sort of dynamic \"any type\" that can\n" "hold any data. The machine code generated by such declaration is identical to the explicit declaration of a type.\n" "The compiler does the job for us and helps us write more concise code." -msgstr "이 슬라이드는, 러스트 컴파일러가 변수가 어떻게 선언되어 있고, 어떻게 사용되는지를 제약 조건으로 삼아서 변수의 타입을 추론하는 모습을 보여줍니다. 여기서 중요한 것은, 이렇게 명시적인 타입을 생략하고 선언되었다고 해서 \"어떤 타입\"이라도 다 담을 수 있는 타입이 되는 것은 아니라는 점입니다. 명시적인 타입 선언이 있던 없던, 컴파일러가 생성한 머신코드는 동일합니다. 컴파일러는 단지 타입 선언을 생략할 수 있도록 해서 프로그래머가 더 간결한 코드를 쓸 수 있도록 도와줄 뿐입니다." +msgstr "여기서 중요한 것은, 이렇게 명시적인 타입을 생략하고 선언되었다고 해서 \"어떤 타입\"이라도 다 담을 수 있는 타입이 되는 것은 아니라는 점입니다. 명시적인 타입 선언이 있던 없던, 컴파일러가 생성한 머신코드는 동일합니다. 컴파일러는 단지 타입 선언을 생략할 수 있도록 해서 프로그래머가 더 간결한 코드를 쓸 수 있도록 도와줄 뿐입니다." #: src/basic-syntax/type-inference.md:32 msgid "The following code tells the compiler to copy into a certain generic container without the code ever explicitly specifying the contained type, using `_` as a placeholder:" @@ -3086,11 +3054,8 @@ msgid "" " let mut v = Vec::new();\n" " v.push((10, false));\n" " v.push((20, true));\n" -" println!(\"v: {v:?}\");" -msgstr "" - -#: src/basic-syntax/type-inference.md:41 -msgid "" +" println!(\"v: {v:?}\");\n" +"\n" " let vv = v.iter().collect::>();\n" " println!(\"vv: {vv:?}\");\n" "}\n" @@ -3121,22 +3086,16 @@ msgstr "컴파일 시 값이 정해지는 상수를 선언할 수 있습니다:" msgid "" "```rust,editable\n" "const DIGEST_SIZE: usize = 3;\n" -"const ZERO: Option = Some(42);" -msgstr "" - -#: src/basic-syntax/static-and-const.md:13 -msgid "" +"const ZERO: Option = Some(42);\n" +"\n" "fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {\n" " let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];\n" " for (idx, &b) in text.as_bytes().iter().enumerate() {\n" " digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE].wrapping_add(b);\n" " }\n" " digest\n" -"}" -msgstr "" - -#: src/basic-syntax/static-and-const.md:21 -msgid "" +"}\n" +"\n" "fn main() {\n" " let digest = compute_digest(\"Hello\");\n" " println!(\"Digest: {digest:?}\");\n" @@ -3159,16 +3118,20 @@ msgstr "마찬가지로 정적 변수도 선언할 수 있습니다:" #: src/basic-syntax/static-and-const.md:33 msgid "" "```rust,editable\n" -"static BANNER: &str = \"Welcome to RustOS 3.14\";" -msgstr "" - -#: src/basic-syntax/static-and-const.md:36 -msgid "" +"static BANNER: &str = \"Welcome to RustOS 3.14\";\n" +"\n" "fn main() {\n" " println!(\"{BANNER}\");\n" "}\n" "```" msgstr "" +"```rust,editable\n" +"static BANNER: &str = \"Welcome to RustOS 3.14\";\n" +"\n" +"fn main() {\n" +" println!(\"{BANNER}\");\n" +"}\n" +"```" #: src/basic-syntax/static-and-const.md:41 msgid "As noted in the [Rust RFC Book][1], these are not inlined upon use and have an actual associated memory location. This is useful for unsafe and embedded code, and the variable lives through the entirety of the program execution." @@ -3188,10 +3151,6 @@ msgstr "" "* 반면에 `static`은 C++의 `const`나 가변 정적 변수와 훨씬 더 유사합니다.\n" "* 프로그램 수행시 그 값이 정해지는 상수가 필요한 경우는 드뭅니다. 그러나 그렇다고 해도, 정적 변수를 사용하는 것 보다는 더 유용하고 안전합니다." -#: src/basic-syntax/static-and-const.md:54 -msgid "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" -msgstr "" - #: src/basic-syntax/scopes-shadowing.md:1 msgid "# Scopes and Shadowing" msgstr "# 범위(Scope)와 쉐도잉(Shadowing)" @@ -3207,25 +3166,16 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let a = 10;\n" -" println!(\"before: {a}\");" -msgstr "" - -#: src/basic-syntax/scopes-shadowing.md:11 -msgid "" +" println!(\"before: {a}\");\n" +"\n" " {\n" " let a = \"hello\";\n" -" println!(\"inner scope: {a}\");" -msgstr "" - -#: src/basic-syntax/scopes-shadowing.md:15 -msgid "" +" println!(\"inner scope: {a}\");\n" +"\n" " let a = true;\n" " println!(\"shadowed in inner scope: {a}\");\n" -" }" -msgstr "" - -#: src/basic-syntax/scopes-shadowing.md:19 -msgid "" +" }\n" +"\n" " println!(\"after: {a}\");\n" "}\n" "```" @@ -3299,21 +3249,19 @@ msgid "" " * Values have fixed sizes known at compile time.\n" " * Extremely fast: just move a stack pointer.\n" " * Easy to manage: follows function calls.\n" -" * Great memory locality." -msgstr "" -"* 스택: 지역 변수를 위한 연속적인 메모리 영역\n" -" * 여기 저장되는 값은 컴파일 시 결정되는 고정 크기를 갖습니다. \n" -" * 매우 빠름: 메모리 할당/반환이 단지 스택 포인터의 이동만으로 구현됩니다.\n" -" * 관리가 쉬움: 함수가 호출되면 할당되고, 리턴하면 반환됩니다.\n" -" * 스택에 있는 값들은 매우 높은 메모리 인접성을 가집니다(_역주_: 그래서 캐시를 효과적으로 활용할 수 있습니다)" - -#: src/memory-management/stack-vs-heap.md:9 -msgid "" +" * Great memory locality.\n" +"\n" "* Heap: Storage of values outside of function calls.\n" " * Values have dynamic sizes determined at runtime.\n" " * Slightly slower than the stack: some book-keeping needed.\n" " * No guarantee of memory locality." msgstr "" +"* 스택: 지역 변수를 위한 연속적인 메모리 영역\n" +" * 여기 저장되는 값은 컴파일 시 결정되는 고정 크기를 갖습니다. \n" +" * 매우 빠름: 메모리 할당/반환이 단지 스택 포인터의 이동만으로 구현됩니다.\n" +" * 관리가 쉬움: 함수가 호출되면 할당되고, 리턴하면 반환됩니다.\n" +" * 스택에 있는 값들은 매우 높은 메모리 인접성을 가집니다(_역주_: 그래서 캐시를 효과적으로 활용할 수 있습니다)\n" +"\n" "* 힙: 함수 호출/리턴과 상관 없이 유지되는 값이 저장되는 곳\n" " * 여기 저장되는 값은 프로그램 수행시 그 크기가 결정됩니다.\n" " * 스택 보다는 느림: 메모리 할당/반환시 해야 할 일이 좀 더 있습니다.\n" @@ -3356,56 +3304,48 @@ msgid "" msgstr "" #: src/memory-management/stack.md:28 -msgid "* Mention that a `String` is backed by a `Vec`, so it has a capacity and length and can grow if mutable via reallocation on the heap." -msgstr "* 문자열(`String`)은 실제로는 `Vec`입니다. 크기(capacity)와 현재 길이(length) 정보를 가지며, 더 큰 크기가 필요할 경우 힙에서 재 할당을 합니다." - -#: src/memory-management/stack.md:30 -msgid "* If students ask about it, you can mention that the underlying memory is heap allocated using the [System Allocator] and custom allocators can be implemented using the [Allocator API]" -msgstr "* 힙은 기본적으로 [System Allocator]를 통해 할당됩니다. 그리고 [Allocator API]를 이용해서 커스텀 메모리 할당자를 만들 수도 있습니다." - -#: src/memory-management/stack.md:32 -msgid "* We can inspect the memory layout with `unsafe` code. However, you should point out that this is rightfully unsafe!" -msgstr "* `unsafe` 코드로 메모리 레이아웃을 살펴볼 수 있습니다. 물론 이 코드가 안전하지 않다는 점을 알려주세요!" - -#: src/memory-management/stack.md:34 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut s1 = String::from(\"Hello\");\n" -" s1.push(' ');\n" -" s1.push_str(\"world\");\n" -" // DON'T DO THIS AT HOME! For educational purposes only.\n" -" // String provides no guarantees about its layout, so this could lead to\n" -" // undefined behavior.\n" -" unsafe {\n" -" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" -" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +"* Mention that a `String` is backed by a `Vec`, so it has a capacity and length and can grow if mutable via reallocation on the heap.\n" +"\n" +"* If students ask about it, you can mention that the underlying memory is heap allocated using the [System Allocator] and custom allocators can be implemented using the [Allocator API]\n" +"\n" +"* We can inspect the memory layout with `unsafe` code. However, you should point out that this is rightfully unsafe!\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could lead to\n" +" // undefined behavior.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +" }\n" " }\n" -"}\n" -"```" +" ```" msgstr "" -"```rust,editable\n" -"fn main() {\n" -" let mut s1 = String::from(\"Hello\");\n" -" s1.push(' ');\n" -" s1.push_str(\"world\");\n" -" // DON'T DO THIS AT HOME! For educational purposes only.\n" -" // String provides no guarantees about its layout, so this could lead to\n" -" // undefined behavior.\n" -" unsafe {\n" -" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" -" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +"* 문자열(`String`)은 실제로는 `Vec`입니다. 크기(capacity)와 현재 길이(length) 정보를 가지며, 더 큰 크기가 필요할 경우 힙에서 재 할당을 합니다.\n" +"\n" +"* 힙은 기본적으로 [System Allocator]를 통해 할당됩니다. 그리고 [Allocator API]를 이용해서 커스텀 메모리 할당자를 만들 수도 있습니다.\n" +"\n" +"* `unsafe` 코드로 메모리 레이아웃을 살펴볼 수 있습니다. 물론 이 코드가 안전하지 않다는 점을 알려주세요!\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could lead to\n" +" // undefined behavior.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +" }\n" " }\n" -"}\n" -"```" - -#: src/memory-management/stack.md:51 -msgid "" -"[System Allocator]: https://doc.rust-lang.org/std/alloc/struct.System.html\n" -"[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html" -msgstr "" -"[System Allocator]: https://doc.rust-lang.org/std/alloc/struct.System.html\n" -"[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html" +" ```" #: src/memory-management/manual.md:1 msgid "# Manual Memory Management" @@ -3563,21 +3503,14 @@ msgid "It achieves this by modeling _ownership_ explicitly." msgstr "러스트는 *소유권*을 언어 차원에서 명시적으로 모델링 함으로써 이를 이룹니다." #: src/memory-management/rust.md:14 -msgid "* If asked how at this point, you can mention that in Rust this is usually handled by RAII wrapper types such as [Box], [Vec], [Rc], or [Arc]. These encapsulate ownership and memory allocation via various means, and prevent the potential errors in C." -msgstr "* 이 시점에서 그게 어떻게 가능하냐는 질문이 있으면, 러스트에서 이 작업은 일반적으로 [Box], [Vec], [Rc] 또는 [Arc]와 같은 RAII 타입에 의해 처리된다고 답변할 수 있습니다. 이들은 다양한 방법을 통해 소유권과 메모리 할당에 대한 구체적인 내용을을 캡슐화하여, C 언어였다면 발생할 수 있었을 다양한 에러를 막습니다." - -#: src/memory-management/rust.md:16 -msgid "* You may be asked about destructors here, the [Drop] trait is the Rust equivalent." -msgstr "* 소멸자에 대한 질문도 있을 수 있습니다. [Drop] 트레잇이 답입니다." - -#: src/memory-management/rust.md:20 msgid "" -"[Box]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" -"[Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" -"[Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" -"[Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" -"[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html" +"* If asked how at this point, you can mention that in Rust this is usually handled by RAII wrapper types such as [Box], [Vec], [Rc], or [Arc]. These encapsulate ownership and memory allocation via various means, and prevent the potential errors in C.\n" +"\n" +"* You may be asked about destructors here, the [Drop] trait is the Rust equivalent." msgstr "" +"* 이 시점에서 그게 어떻게 가능하냐는 질문이 있으면, 러스트에서 이 작업은 일반적으로 [Box], [Vec], [Rc] 또는 [Arc]와 같은 RAII 타입에 의해 처리된다고 답변할 수 있습니다. 이들은 다양한 방법을 통해 소유권과 메모리 할당에 대한 구체적인 내용을을 캡슐화하여, C 언어였다면 발생할 수 있었을 다양한 에러를 막습니다.\n" +"\n" +"* 소멸자에 대한 질문도 있을 수 있습니다. [Drop] 트레잇이 답입니다." #: src/memory-management/comparison.md:1 msgid "# Comparison" @@ -3666,11 +3599,8 @@ msgstr "모든 변수 바인딩은 유효한 \"범위(스코프)\"를 가지며, #: src/ownership.md:6 msgid "" "```rust,editable,compile_fail\n" -"struct Point(i32, i32);" -msgstr "" - -#: src/ownership.md:9 -msgid "" +"struct Point(i32, i32);\n" +"\n" "fn main() {\n" " {\n" " let p = Point(3, 4);\n" @@ -3680,6 +3610,17 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" {\n" +" let p = Point(3, 4);\n" +" println!(\"x: {}\", p.0);\n" +" }\n" +" println!(\"y: {}\", p.1);\n" +"}\n" +"```" #: src/ownership.md:18 msgid "" @@ -3726,12 +3667,14 @@ msgstr "" "* 값(데이터)의 소유권을 갖는 변수는 항상 *단* 하나 입니다." #: src/ownership/move-semantics.md:22 -msgid "* Mention that this is the opposite of the defaults in C++, which copies by value unless you use `std::move` (and the move constructor is defined!)." -msgstr "* 이는 C++과 정반대 임을 설명하세요. C++에서는 복사가 기본이고, `std::move` 를 이용해야만 (그리고 이동 생성자가 정의되어 있어야만!) 소유권 이전이 됩니다." - -#: src/ownership/move-semantics.md:24 -msgid "* In Rust, clones are explicit (by using `clone`)." -msgstr "* 러스트에서는 복사할때에는 명시적으로 `clone`을 사용합니다." +msgid "" +"* Mention that this is the opposite of the defaults in C++, which copies by value unless you use `std::move` (and the move constructor is defined!).\n" +"\n" +"* In Rust, clones are explicit (by using `clone`)." +msgstr "" +"* 이는 C++과 정반대 임을 설명하세요. C++에서는 복사가 기본이고, `std::move` 를 이용해야만 (그리고 이동 생성자가 정의되어 있어야만!) 소유권 이전이 됩니다.\n" +"\n" +"* 러스트에서는 복사할때에는 명시적으로 `clone`을 사용합니다." #: src/ownership/moved-strings-rust.md:1 msgid "# Moved Strings in Rust" @@ -3893,11 +3836,8 @@ msgid "" "```rust,editable\n" "fn say_hello(name: String) {\n" " println!(\"Hello {name}\")\n" -"}" -msgstr "" - -#: src/ownership/moves-function-calls.md:11 -msgid "" +"}\n" +"\n" "fn main() {\n" " let name = String::from(\"Alice\");\n" " say_hello(name);\n" @@ -3952,11 +3892,8 @@ msgstr "직접 만든 타입들도 `Copy`트레잇을 구현하여 복사를 할 msgid "" "```rust,editable\n" "#[derive(Copy, Clone, Debug)]\n" -"struct Point(i32, i32);" -msgstr "" - -#: src/ownership/copy-clone.md:22 -msgid "" +"struct Point(i32, i32);\n" +"\n" "fn main() {\n" " let p1 = Point(3, 4);\n" " let p2 = p1;\n" @@ -3965,6 +3902,17 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"#[derive(Copy, Clone, Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = p1;\n" +" println!(\"p1: {p1:?}\");\n" +" println!(\"p2: {p2:?}\");\n" +"}\n" +"```" #: src/ownership/copy-clone.md:30 msgid "" @@ -4007,12 +3955,8 @@ msgstr "" #: src/ownership/copy-clone.md:48 msgid "" "If students ask about `derive`, it is sufficient to say that this is a way to generate code in Rust\n" -"at compile time. In this case the default implementations of `Copy` and `Clone` traits are generated.\n" -" \n" -"
" -msgstr "" -"만약 학생들이 `derive`에 대해 묻는다면, 컴파일 시 러스트에서 코드를 생성하는방법이라고 말하는 것으로 충분합니다. 위 경우 `Copy`와 `Clone` 트레잇에 대한 기본 구현이 생성됩니다.\n" -"
" +"at compile time. In this case the default implementations of `Copy` and `Clone` traits are generated." +msgstr "만약 학생들이 `derive`에 대해 묻는다면, 컴파일 시 러스트에서 코드를 생성하는방법이라고 말하는 것으로 충분합니다. 위 경우 `Copy`와 `Clone` 트레잇에 대한 기본 구현이 생성됩니다." #: src/ownership/borrowing.md:1 msgid "# Borrowing" @@ -4024,22 +3968,16 @@ msgid "" "function _borrow_ the value:" msgstr "함수 호출시 값의 소유권을 이동하는 대신의 함수가 값을 *빌려올 수* 있습니다:" -#: src/ownership/borrowing.md:6 src/ownership/lifetimes-function-calls.md:5 +#: src/ownership/borrowing.md:6 msgid "" "```rust,editable\n" "#[derive(Debug)]\n" -"struct Point(i32, i32);" -msgstr "" - -#: src/ownership/borrowing.md:10 -msgid "" +"struct Point(i32, i32);\n" +"\n" "fn add(p1: &Point, p2: &Point) -> Point {\n" " Point(p1.0 + p2.0, p1.1 + p2.1)\n" -"}" -msgstr "" - -#: src/ownership/borrowing.md:14 -msgid "" +"}\n" +"\n" "fn main() {\n" " let p1 = Point(3, 4);\n" " let p2 = Point(10, 20);\n" @@ -4058,31 +3996,23 @@ msgstr "" "* `p1`과 `p2`의 소유권은 여전히 호출자(`main`함수)에 있습니다." #: src/ownership/borrowing.md:27 -msgid "" -"Notes on stack returns:\n" -"* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy operation. Change the above code to print stack addresses and run it on the [Playground]. In the \"DEBUG\" optimization level, the addresses should change, while the stay the same when changing to the \"RELEASE\" setting:" -msgstr "" -"스택에 할당된 값을 리턴하는 것에 대한 참고: \n" -"* `add`에서 값을 반환하는 것은 매우 값이 싸다는 것을 설명하세요. 왜냐하면, 컴파일러가 복사 과정을 생략할 수 있기 때문입니다. 위 코드를 스택 주소를 출력하도록 수정하고 [Playground]에서 수행해 보세요. \"디버그\" 최적화 레벨에서는 주소가 바뀌지만, \"릴리즈\" 레벨에서는 바뀌지 않습니다:" +msgid "Notes on stack returns:" +msgstr "스택에 할당된 값을 리턴하는 것에 대한 참고:" -#: src/ownership/borrowing.md:30 +#: src/ownership/borrowing.md:28 msgid "" +"* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy operation. Change the above code to print stack addresses and run it on the [Playground]. In the \"DEBUG\" optimization level, the addresses should change, while they stay the same when changing to the \"RELEASE\" setting:\n" +"\n" " ```rust,editable\n" " #[derive(Debug)]\n" -" struct Point(i32, i32);" -msgstr "" - -#: src/ownership/borrowing.md:34 -msgid "" +" struct Point(i32, i32);\n" +"\n" " fn add(p1: &Point, p2: &Point) -> Point {\n" " let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" " println!(\"&p.0: {:p}\", &p.0);\n" " p\n" -" }" -msgstr "" - -#: src/ownership/borrowing.md:40 -msgid "" +" }\n" +"\n" " fn main() {\n" " let p1 = Point(3, 4);\n" " let p2 = Point(10, 20);\n" @@ -4094,6 +4024,18 @@ msgid "" "* The Rust compiler can do return value optimization (RVO).\n" "* In C++, copy elision has to be defined in the language specification because constructors can have side effects. In Rust, this is not an issue at all. If RVO did not happen, Rust will always performs a simple and efficient `memcpy` copy." msgstr "" +"* `add`에서 값을 반환하는 것은 매우 값이 싸다는 것을 설명하세요. 왜냐하면, 컴파일러가 복사 과정을 생략할 수 있기 때문입니다. 위 코드를 스택 주소를 출력하도록 수정하고 [Playground]에서 수행해 보세요. \\\"디버그\\\" 최적화 레벨에서는 주소가 바뀌지만, \\\"릴리즈\\\" 레벨에서는 바뀌지 않습니다:\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn add(p1: &Point, p2: &Point) -> Point {\n" +" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" +" println!(\"&p.0: {:p}\", &p.0);\n" +" p\n" +" }\n" +"\n" " fn main() {\n" " let p1 = Point(3, 4);\n" " let p2 = Point(10, 20);\n" @@ -4105,10 +4047,6 @@ msgstr "" "* 러스트 컴파일러는 반환값 최적화(RVO)를 수행할 수 있습니다.\n" "* C++에서 copy elision은 생성자의 부수효과 가능성이 있어 언어레벨의 정의가 필요하지만 러스트에서는 문제가 되지 않습니다. 만약 RVO가 발생하지 않으면 러스트는 항상 간단하고 효율적인 `memcpy`복사를 수행할 것입니다." -#: src/ownership/borrowing.md:53 -msgid "[Playground]: https://play.rust-lang.org/" -msgstr "" - #: src/ownership/shared-unique-borrows.md:1 msgid "# Shared and Unique Borrows" msgstr "# 공유와 고유 빌림" @@ -4130,24 +4068,32 @@ msgid "" "```rust,editable,compile_fail\n" "fn main() {\n" " let mut a: i32 = 10;\n" -" let b: &i32 = &a;" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:13 -msgid "" +" let b: &i32 = &a;\n" +"\n" " {\n" " let c: &mut i32 = &mut a;\n" " *c = 20;\n" -" }" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:18 src/std/rc.md:13 -msgid "" +" }\n" +"\n" " println!(\"a: {a}\");\n" " println!(\"b: {b}\");\n" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let mut a: i32 = 10;\n" +" let b: &i32 = &a;\n" +"\n" +" {\n" +" let c: &mut i32 = &mut a;\n" +" *c = 20;\n" +" }\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" #: src/ownership/shared-unique-borrows.md:25 msgid "" @@ -4193,15 +4139,16 @@ msgstr "# 함수 호출에서의 수명" msgid "In addition to borrowing its arguments, a function can return a borrowed value:" msgstr "함수는 인수를 빌리는 것 외에도 빌린 값을 반환할 수 있습니다:" -#: src/ownership/lifetimes-function-calls.md:9 +#: src/ownership/lifetimes-function-calls.md:5 msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" "fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" " if p1.0 < p2.0 { p1 } else { p2 }\n" -"}" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:13 -msgid "" +"}\n" +"\n" "fn main() {\n" " let p1: Point = Point(10, 10);\n" " let p2: Point = Point(20, 20);\n" @@ -4229,22 +4176,12 @@ msgid "" "* Move the declaration of `p2` and `p3` into a a new scope (`{ ... }`), resulting in the following code:\n" " ```rust,ignore\n" " #[derive(Debug)]\n" -" struct Point(i32, i32);" -msgstr "" -"* `p2`와 `p3`를 새로운 범위(`{...}`)로 아래 코드와 같이 이동해 봅니다:\n" -" ```rust,ignore\n" -" #[derive(Debug)]\n" -" struct Point(i32, i32);" - -#: src/ownership/lifetimes-function-calls.md:36 -msgid "" +" struct Point(i32, i32);\n" +"\n" " fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" " if p1.0 < p2.0 { p1 } else { p2 }\n" -" }" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:40 -msgid "" +" }\n" +"\n" " fn main() {\n" " let p1: Point = Point(10, 10);\n" " let p3: &Point;\n" @@ -4255,8 +4192,25 @@ msgid "" " println!(\"left-most point: {:?}\", p3);\n" " }\n" " ```\n" -" Note how this does not compile since `p3` outlives `p2`." +" Note how this does not compile since `p3` outlives `p2`.\n" +"\n" +"* Reset the workspace and change the function signature to `fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile because the relationship between the lifetimes `'a` and `'b` is unclear.\n" +"* Another way to explain it:\n" +" * 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" +" for longer than a variable from where the reference came from." msgstr "" +"* `p2`와 `p3`를 새로운 범위(`{...}`)로 아래 코드와 같이 이동해 봅니다:\n" +" ```rust,ignore\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +" }\n" +"\n" " fn main() {\n" " let p1: Point = Point(10, 10);\n" " let p3: &Point;\n" @@ -4267,18 +4221,8 @@ msgstr "" " println!(\"left-most point: {:?}\", p3);\n" " }\n" " ```\n" -" `p3`의 수명이 `p2` 보다 길기 때문에 이 예제는 컴파일되지 않음을 확인하시기 바랍니다." - -#: src/ownership/lifetimes-function-calls.md:52 -msgid "" -"* Reset the workspace and change the function signature to `fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile because the relationship between the lifetimes `'a` and `'b` is unclear.\n" -"* Another way to explain it:\n" -" * 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" -" for longer than a variable from where the reference came from." -msgstr "" +" `p3`의 수명이 `p2` 보다 길기 때문에 이 예제는 컴파일되지 않음을 확인하시기 바랍니다.\n" +"\n" "* 작업공간을 초기화 한 후 함수 시그니처를 `fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`로 변경해 봅니다. 이 경우 `'a`와 `'b`사이의 관계가 불분명하기 때문에 컴파일 되지 않습니다.\n" "* 이 에러를 설명하는 또 다른 방법은 다음과 같습니다:\n" " * 이 함수는 두 값을 빌려서, 새로운 참조를 반환합니다.\n" @@ -4297,18 +4241,12 @@ msgstr "어떤 타입이 빌려온 데이터를 저장하고 있다면, 반드 msgid "" "```rust,editable\n" "#[derive(Debug)]\n" -"struct Highlight<'doc>(&'doc str);" -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:9 -msgid "" +"struct Highlight<'doc>(&'doc str);\n" +"\n" "fn erase(text: String) {\n" " println!(\"Bye {text}!\");\n" -"}" -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:13 -msgid "" +"}\n" +"\n" "fn main() {\n" " let text = String::from(\"The quick brown fox jumps over the lazy dog.\");\n" " let fox = Highlight(&text[4..19]);\n" @@ -4326,15 +4264,13 @@ msgid "" "* If `text` is consumed before the end of the lifetime of `fox` (or `dog`), the borrow checker throws an error.\n" "* Types with borrowed data force users to hold on to the original data. This can be useful for creating lightweight views, but it generally makes them somewhat harder to use.\n" "* When possible, make data structures own their data directly.\n" -"* Some structs with multiple references inside can have more than one lifetime annotation. This can be necessary if there is a need to describe lifetime relationships between the references themselves, in addition to the lifetime of the struct itself. Those are very advanced use cases.\n" -"
" +"* Some structs with multiple references inside can have more than one lifetime annotation. This can be necessary if there is a need to describe lifetime relationships between the references themselves, in addition to the lifetime of the struct itself. Those are very advanced use cases." msgstr "" "* 위의 예제에서 `Highlight`의 어노테이션(`<'doc>`)은 적어도 `Highlight` 인스턴스가 살아있는 동안에는 그 내부의 `&str`가 가리키는 데이터 역시 살아있어야 한다는 것을 의미합니다.\n" "* 만약 `text`가 `fox` (혹은 `dog`)의 수명이 다하기 전에 `erase`함수 호출 등으로 사라지게 된다면 빌림 검사기가 에러를 발생합니다.\n" "* 빌린 데이터를 가지고 있는 타입은 사용자로 하여금 원본 데이터를 유지하도록 강제합니다. 이런 타입은 경량 뷰(lightweight view)를 만드는데 유용하지만, 이 제약 조건 때문에 이런 타입을 사용하는 것이 쉽지만은 않습니다.\n" "* 따라서, 가능하다면, 구조체가 자신의 데이터를 직접 소유하도록 하는 것이 좋습니다.\n" -"* 한 구조체안에 여러 참조가 있으면서, 이 참조들의 수명이 서로 다르게 지정되는 경우도 있습니다. 이는 참조와 그 구조체 간의 관계 뿐만이 아니라, 그 참조들 사이의 수명 관계를 설명해야 할 경우에 필요합니다. 매우 고급 기술입니다.\n" -"
" +"* 한 구조체안에 여러 참조가 있으면서, 이 참조들의 수명이 서로 다르게 지정되는 경우도 있습니다. 이는 참조와 그 구조체 간의 관계 뿐만이 아니라, 그 참조들 사이의 수명 관계를 설명해야 할 경우에 필요합니다. 매우 고급 기술입니다." #: src/exercises/day-1/afternoon.md:1 msgid "# Day 1: Afternoon Exercises" @@ -4345,16 +4281,14 @@ msgid "We will look at two things:" msgstr "이번 연습문제는 아래 두가지입니다:" #: src/exercises/day-1/afternoon.md:5 -msgid "* A small book library," -msgstr "* 작은 도서관" - -#: src/exercises/day-1/afternoon.md:7 -msgid "* Iterators and ownership (hard)." -msgstr "* 반복자와 소유권 (어려움)" - -#: src/exercises/day-1/afternoon.md:13 src/exercises/day-2/afternoon.md:9 -msgid "[solutions]: solutions-afternoon.md" +msgid "" +"* A small book library,\n" +"\n" +"* Iterators and ownership (hard)." msgstr "" +"* 작은 도서관\n" +"\n" +"* 반복자와 소유권 (어려움)" #: src/exercises/day-1/book-library.md:1 msgid "# Designing a Library" @@ -4387,28 +4321,18 @@ msgid "" msgstr "도서관 프로그램을 만들기 위해 아래 코드를 에 복사해서 구현하시면 됩니다:" #: src/exercises/day-1/book-library.md:20 -msgid "```rust,should_panic" -msgstr "" - -#: src/exercises/day-1/book-library.md:22 msgid "" +"```rust,should_panic\n" +"\n" "struct Library {\n" " books: Vec,\n" -"}" -msgstr "" - -#: src/exercises/day-1/book-library.md:26 -#: src/exercises/day-1/solutions-afternoon.md:27 -msgid "" +"}\n" +"\n" "struct Book {\n" " title: String,\n" " year: u16,\n" -"}" -msgstr "" - -#: src/exercises/day-1/book-library.md:31 -#: src/exercises/day-1/solutions-afternoon.md:32 -msgid "" +"}\n" +"\n" "impl Book {\n" " // This is a constructor, used below.\n" " fn new(title: &str, year: u16) -> Book {\n" @@ -4417,99 +4341,50 @@ msgid "" " year,\n" " }\n" " }\n" -"}" -msgstr "" -"impl Book {\n" -" // 아래는 Book 구조체의 생성자입니다.\n" -" fn new(title: &str, year: u16) -> Book {\n" -" Book {\n" -" title: String::from(title),\n" -" year,\n" -" }\n" -" }\n" -"}" - -#: src/exercises/day-1/book-library.md:41 -msgid "" +"}\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" -"}" -msgstr "" -"// 이 구현메서드는 {} 포맷으로 출력할 수 있게 도와줍니다.\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" -"}" - -#: src/exercises/day-1/book-library.md:48 -msgid "" +"}\n" +"\n" "impl Library {\n" " fn new() -> Library {\n" " unimplemented!()\n" -" }" -msgstr "" - -#: src/exercises/day-1/book-library.md:53 -msgid "" +" }\n" +"\n" " //fn len(self) -> usize {\n" " // unimplemented!()\n" -" //}" -msgstr "" - -#: src/exercises/day-1/book-library.md:57 -msgid "" +" //}\n" +"\n" " //fn is_empty(self) -> bool {\n" " // unimplemented!()\n" -" //}" -msgstr "" - -#: src/exercises/day-1/book-library.md:61 -msgid "" +" //}\n" +"\n" " //fn add_book(self, book: Book) {\n" " // unimplemented!()\n" -" //}" -msgstr "" - -#: src/exercises/day-1/book-library.md:65 -msgid "" +" //}\n" +"\n" " //fn print_books(self) {\n" " // unimplemented!()\n" -" //}" -msgstr "" - -#: src/exercises/day-1/book-library.md:69 -msgid "" +" //}\n" +"\n" " //fn oldest_book(self) -> Option<&Book> {\n" " // unimplemented!()\n" " //}\n" -"}" -msgstr "" - -#: src/exercises/day-1/book-library.md:74 -msgid "" +"}\n" +"\n" "// This shows the desired behavior. Uncomment the code below and\n" "// implement the missing methods. You will need to update the\n" "// method signatures, including the \"self\" parameter! You may\n" "// also need to update the variable bindings within main.\n" "fn main() {\n" -" let library = Library::new();" -msgstr "" -"// 아래 소스 주석을 제거하고 누락된 메서드를 구현하세요\n" -"// 미구현 메서드도 존재하므로 메서드 시그니처를 업데이트 하세요(self 포함)\n" -"fn main() {\n" -" let library = Library::new();" - -#: src/exercises/day-1/book-library.md:81 -#: src/exercises/day-1/solutions-afternoon.md:113 -msgid " //println!(\"Our library is empty: {}\", library.is_empty());" -msgstr "" - -#: src/exercises/day-1/book-library.md:83 -msgid "" +" 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" @@ -4530,15 +4405,9 @@ msgid "" "```" msgstr "" -#: src/exercises/day-1/book-library.md:102 -msgid "" -"
\n" -" \n" -"[Solution](solutions-afternoon.md#designing-a-library)" -msgstr "" -"
\n" -" \n" -"[해답](solutions-afternoon.md#designing-a-library)" +#: src/exercises/day-1/book-library.md:104 +msgid "[Solution](solutions-afternoon.md#designing-a-library)" +msgstr "[해답](solutions-afternoon.md#designing-a-library)" #: src/exercises/day-1/iterators-and-ownership.md:1 msgid "# Iterators and Ownership" @@ -4554,7 +4423,7 @@ msgstr "러스트의 소유권 모델은 많은 API에 반영이 되어 있습 #: src/exercises/day-1/iterators-and-ownership.md:8 msgid "## `Iterator`" -msgstr "" +msgstr "## `Iterator`" #: src/exercises/day-1/iterators-and-ownership.md:10 msgid "" @@ -4581,11 +4450,8 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:27 -msgid "" +" let mut iter = v.iter();\n" +"\n" " println!(\"v[0]: {:?}\", iter.next());\n" " println!(\"v[1]: {:?}\", iter.next());\n" " println!(\"v[2]: {:?}\", iter.next());\n" @@ -4603,17 +4469,22 @@ msgid "" "```rust,editable,compile_fail\n" "fn main() {\n" " let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:41 -#: src/exercises/day-1/iterators-and-ownership.md:78 -msgid "" +" let mut iter = v.iter();\n" +"\n" " let v0: Option<..> = iter.next();\n" " println!(\"v0: {v0:?}\");\n" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" #: src/exercises/day-1/iterators-and-ownership.md:46 msgid "Why is this type used?" @@ -4621,7 +4492,7 @@ msgstr "왜 이런 타입이 사용되는 것일까요?" #: src/exercises/day-1/iterators-and-ownership.md:48 msgid "## `IntoIterator`" -msgstr "" +msgstr "## `IntoIterator`" #: src/exercises/day-1/iterators-and-ownership.md:50 msgid "" @@ -4634,11 +4505,8 @@ msgid "" "```rust\n" "pub trait IntoIterator {\n" " type Item;\n" -" type IntoIter: Iterator;" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:58 -msgid "" +" type IntoIter: Iterator;\n" +"\n" " fn into_iter(self) -> Self::IntoIter;\n" "}\n" "```" @@ -4673,7 +4541,12 @@ msgid "" "```rust,editable,compile_fail\n" "fn main() {\n" " let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];\n" -" let mut iter = v.into_iter();" +" let mut iter = v.into_iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" msgstr "" #: src/exercises/day-1/iterators-and-ownership.md:83 @@ -4691,18 +4564,12 @@ msgstr "자, 이제 우리는 `Iterator`와 `IntoIterator`를 알았으므로 `f msgid "" "```rust,editable\n" "fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:93 -msgid "" +" let v: Vec = vec![String::from(\"foo\"), String::from(\"bar\")];\n" +"\n" " for word in &v {\n" " println!(\"word: {word}\");\n" -" }" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:97 -msgid "" +" }\n" +"\n" " for word in v {\n" " println!(\"word: {word}\");\n" " }\n" @@ -4722,10 +4589,7 @@ msgid "" "and [`impl IntoIterator for\n" "Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-Vec%3CT%2C%20A%3E)\n" "to check your answers." -msgstr "" -"위 코드에서 실험 해 본 후 다음 문서를 참조해서 답변을 확인하시기 바랍니다.\n" -"* [`impl IntoIterator for &Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E)\n" -"* [`impl IntoIterator for Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-Vec%3CT%2C%20A%3E)" +msgstr "위 코드에서 실험 해 본 후 다음 문서를 참조해서 답변을 확인하시기 바랍니다: [`impl IntoIterator for &Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E), [`impl IntoIterator for Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-for-Vec%3CT%2C%20A%3E)" #: src/welcome-day-2.md:1 msgid "# Welcome to Day 2" @@ -4736,28 +4600,28 @@ msgid "Now that we have seen a fair amount of Rust, we will continue with:" msgstr "상당한 분량의 러스트에 대해 보았고, 이어서 오늘 강의를 진행하겠습니다:" #: src/welcome-day-2.md:5 -msgid "* Structs, enums, methods." -msgstr "* 구조체, 열거형, 메서드." - -#: src/welcome-day-2.md:7 -msgid "* Pattern matching: destructuring enums, structs, and arrays." -msgstr "* 패턴 매칭: 열거형, 구조체 그리고 배열 분해." - -#: src/welcome-day-2.md:9 msgid "" +"* Structs, enums, methods.\n" +"\n" +"* Pattern matching: destructuring enums, structs, and arrays.\n" +"\n" "* Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and\n" -" `continue`." -msgstr "* 흐름 제어: `if`, `if let`, `while`, `while let`, `break`, 그리고 `continue`." - -#: src/welcome-day-2.md:12 -msgid "" +" `continue`.\n" +"\n" "* The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, `Rc`\n" -" and `Arc`." -msgstr "* 표준 라이브러리: `String`, `Option` 과 `Result`, `Vec`, `HashMap`, `Rc` 그리고 `Arc`." - -#: src/welcome-day-2.md:15 -msgid "* Modules: visibility, paths, and filesystem hierarchy." -msgstr "* 모듈: 가시성, 경로 및 파일 시스템 계층." +" and `Arc`.\n" +"\n" +"* Modules: visibility, paths, and filesystem hierarchy." +msgstr "" +"* 구조체, 열거형, 메서드.\n" +"\n" +"* 패턴 매칭: 열거형, 구조체 그리고 배열 분해.\n" +"\n" +"* 흐름 제어: `if`, `if let`, `while`, `while let`, `break`, 그리고 `continue`.\n" +"\n" +"* 표준 라이브러리: `String`, `Option` 과 `Result`, `Vec`, `HashMap`, `Rc` 그리고 `Arc`.\n" +"\n" +"* 모듈: 가시성, 경로 및 파일 시스템 계층." #: src/structs.md:1 msgid "# Structs" @@ -4773,11 +4637,8 @@ msgid "" "struct Person {\n" " name: String,\n" " age: u8,\n" -"}" -msgstr "" - -#: src/structs.md:11 -msgid "" +"}\n" +"\n" "fn main() {\n" " let mut peter = Person {\n" " name: String::from(\"Peter\"),\n" @@ -4836,17 +4697,22 @@ msgstr "각 필드 이름이 중요하지 않다면 튜플 구조체를 사용 #: src/structs/tuple-structs.md:5 msgid "" "```rust,editable\n" -"struct Point(i32, i32);" -msgstr "" - -#: src/structs/tuple-structs.md:8 -msgid "" +"struct Point(i32, i32);\n" +"\n" "fn main() {\n" " let p = Point(17, 23);\n" " println!(\"({}, {})\", p.0, p.1);\n" "}\n" "```" msgstr "" +"```rust,editable\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p = Point(17, 23);\n" +" println!(\"({}, {})\", p.0, p.1);\n" +"}\n" +"```" #: src/structs/tuple-structs.md:14 msgid "This is often used for single-field wrappers (called newtypes):" @@ -4856,34 +4722,22 @@ msgstr "튜플 구조체는 종종 단일 필드의 래퍼(wrapper, 러스트에 msgid "" "```rust,editable,compile_fail\n" "struct PoundOfForce(f64);\n" -"struct Newtons(f64);" -msgstr "" - -#: src/structs/tuple-structs.md:20 -msgid "" +"struct Newtons(f64);\n" +"\n" "fn compute_thruster_force() -> PoundOfForce {\n" " todo!(\"Ask a rocket scientist at NASA\")\n" -"}" -msgstr "" - -#: src/structs/tuple-structs.md:24 -msgid "" +"}\n" +"\n" "fn set_thruster_force(force: Newtons) {\n" " // ...\n" -"}" -msgstr "" - -#: src/structs/tuple-structs.md:28 -msgid "" +"}\n" +"\n" "fn main() {\n" " let force = compute_thruster_force();\n" " set_thruster_force(force);\n" -"}" -msgstr "" - -#: src/structs/tuple-structs.md:33 src/traits/default.md:36 -#: src/generics/trait-objects.md:86 -msgid "```" +"}\n" +"\n" +"```" msgstr "" #: src/structs/tuple-structs.md:37 @@ -4893,16 +4747,14 @@ msgid "" " * The value passed some validation when it was created, so you no longer have to validate it again at every use: 'PhoneNumber(String)` or `OddNumber(u32)`.\n" "* Demonstrate how to add a `f64` value to a `Newtons` type by accessing the single field in the newtype.\n" " * Rust generally doesn’t like inexplicit things, like automatic unwrapping or for instance using booleans as integers.\n" -" * Operator overloading is discussed on Day 3 (generics). \n" -"
" +" * Operator overloading is discussed on Day 3 (generics). " msgstr "" "* 뉴타입은 다음과 같은 원시타입 값에 특별한 의미를 부여하는 데 유용합니다.\n" " * 단위 표시를 위한 숫자: 위 예제에서는 뉴턴 단위 표기를 위해 사용합니다.\n" " * 값이 생성될 때 이미 유효성 검사를 통과 했으므로 추가적인 검사가 필요없는 경우: `PhoneNumber(String)`또는 `OddNumber(u32)`\n" "* `Newtons` 타입의 값에 `f64` 값을 더하는 방법을 보여주세요.\n" " * 러스트는 대체로 분명하지 않은 것을 싫어합니다. 예를 들면 자동으로 unwrap하거나 불리언 값을 정수 값으로 사용하는 것들이 그렇습니다.\n" -" * 연산자 재정의는 3일차 제네릭 부분에서 다룹니다.\n" -"
" +" * 연산자 재정의는 3일차 제네릭 부분에서 다룹니다." #: src/structs/field-shorthand.md:1 msgid "# Field Shorthand Syntax" @@ -4914,27 +4766,21 @@ msgid "" "struct using a shorthand:" msgstr "구조체 필드와 동일한 이름의 변수가 있다면 아래와 같이 \"짧은 문법\"으로 구조체를 생성할 수 있습니다:" -#: src/structs/field-shorthand.md:6 src/methods.md:6 +#: src/structs/field-shorthand.md:6 msgid "" "```rust,editable\n" "#[derive(Debug)]\n" "struct Person {\n" " name: String,\n" " age: u8,\n" -"}" -msgstr "" - -#: src/structs/field-shorthand.md:13 -msgid "" +"}\n" +"\n" "impl Person {\n" " fn new(name: String, age: u8) -> Person {\n" " Person { name, age }\n" " }\n" -"}" -msgstr "" - -#: src/structs/field-shorthand.md:19 -msgid "" +"}\n" +"\n" "fn main() {\n" " let peter = Person::new(String::from(\"Peter\"), 27);\n" " println!(\"{peter:?}\");\n" @@ -4943,26 +4789,93 @@ msgid "" msgstr "" #: src/structs/field-shorthand.md:27 -msgid "* The `new` function could be written using `Self` as a type, as it is interchangeable with the struct type name" -msgstr "* `new`함수를 다음처럼 구조체 이름 대신 `Self`를 사용하여 작성해도 됩니다." - -#: src/structs/field-shorthand.md:29 -msgid "" -"```rust,ignore\n" -"impl Person {\n" -" fn new(name: String, age: u8) -> Self {\n" -" Self { name, age }\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/structs/field-shorthand.md:37 msgid "" +"* The `new` function could be written using `Self` as a type, as it is interchangeable with the struct type name\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Person {\n" +" fn new(name: String, age: u8) -> Self {\n" +" Self { name, age }\n" +" }\n" +" }\n" +" ``` \n" +"* Implement the `Default` trait for the struct. Define some fields and use the default values for the other fields.\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Default for Person {\n" +" fn default() -> Person {\n" +" Person {\n" +" name: \"Bot\".to_string(),\n" +" age: 0,\n" +" }\n" +" }\n" +" }\n" +" fn create_default() {\n" +" let tmp = Person {\n" +" ..Default::default()\n" +" };\n" +" let tmp = Person {\n" +" name: \"Sam\".to_string(),\n" +" ..Default::default()\n" +" };\n" +" }\n" +" ```\n" +"\n" "* Methods are defined in the `impl` block.\n" "* Use struct update syntax to define a new structure using `peter`. Note that the variable `peter` will no longer be accessible afterwards.\n" "* Use `{:#?}` when printing structs to request the `Debug` representation." msgstr "" +"* `new`함수를 다음처럼 구조체 이름 대신 `Self`를 사용하여 작성해도 됩니다.\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Person {\n" +" fn new(name: String, age: u8) -> Self {\n" +" Self { name, age }\n" +" }\n" +" }\n" +" ``` \n" +"* `Default` 트레잇을 구현해보세요. 필드 몇개는 초기화하고 나머지 필드는 디폴트 값을 사용할 수 있습니다.\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Person {\n" +" name: String,\n" +" age: u8,\n" +" }\n" +" impl Default for Person {\n" +" fn default() -> Person {\n" +" Person {\n" +" name: \"Bot\".to_string(),\n" +" age: 0,\n" +" }\n" +" }\n" +" }\n" +" fn create_default() {\n" +" let tmp = Person {\n" +" ..Default::default()\n" +" };\n" +" let tmp = Person {\n" +" name: \"Sam\".to_string(),\n" +" ..Default::default()\n" +" };\n" +" }\n" +" ```\n" +"\n" "* 메서드는 `impl` 블록에 정의됩니다.\n" "* `peter`와 구조체 업데이트 문법을 사용하여 새로운 구조체 인스턴스를 만들어보세요. 이때, `peter`는 더이상 사용할 수 없게 됩니다.\n" "* 구조체를 `Debug` 형태로 출력하려면 `{:#?}`를 사용하세요." @@ -4982,20 +4895,14 @@ msgid "" "```rust,editable\n" "fn generate_random_number() -> i32 {\n" " 4 // Chosen by fair dice roll. Guaranteed to be random.\n" -"}" -msgstr "" - -#: src/enums.md:11 -msgid "" +"}\n" +"\n" "#[derive(Debug)]\n" "enum CoinFlip {\n" " Heads,\n" " Tails,\n" -"}" -msgstr "" - -#: src/enums.md:17 -msgid "" +"}\n" +"\n" "fn flip_coin() -> CoinFlip {\n" " let random_number = generate_random_number();\n" " if random_number % 2 == 0 {\n" @@ -5003,26 +4910,19 @@ msgid "" " } else {\n" " return CoinFlip::Tails;\n" " }\n" -"}" -msgstr "" - -#: src/enums.md:26 -msgid "" +"}\n" +"\n" "fn main() {\n" " println!(\"You got: {:?}\", flip_coin());\n" "}\n" "```" msgstr "" -#: src/enums.md:31 src/enums/sizes.md:27 -msgid "" -"
\n" -" \n" -"Key Points:" -msgstr "" -"
\n" -" \n" -"키 포인트:" +#: 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 +msgid "Key Points:" +msgstr "키 포인트:" #: src/enums.md:35 msgid "" @@ -5031,16 +4931,14 @@ msgid "" "* This might be a good time to compare Structs and Enums:\n" " * In both, you can have a simple version without fields (unit struct) or one with different types of fields (variant payloads). \n" " * In both, associated functions are defined within an `impl` block.\n" -" * You could even implement the different variants of an enum with separate structs but then they wouldn’t be the same type as they would if they were all defined in an enum. \n" -"
" +" * You could even implement the different variants of an enum with separate structs but then they wouldn’t be the same type as they would if they were all defined in an enum. " msgstr "" "* 열거형은 값들의 집합을 하나의 타입으로 표현할 수 있게 합니다.\n" "* 위의 `CoinFlip` 열거형 타입은 `Heads`와 `Tail` 두가지 variant를 가집니다. 열거형 타입의 variant는 네임스페이스를 붙여서 사용합니다.\n" "* 구조체와 열거형을 비교해 볼까요?\n" " * 구조체나 열거형 모두, 필드가 하나도 없는 단순한 형태도 가능 하고, 여러 타입의 필드를 가질 수도 있습니다.\n" " * 둘 다 연관함수를 `impl`블록으로 정의 할 수 있습니다.\n" -" * 열거형 타입의 각 variant를 별도의 구조체로 정의할 수도 있지만, 그러면 열거형을 사용했을 때처럼 하나의 타입으로 취급할 수 없습니다.\n" -"
" +" * 열거형 타입의 각 variant를 별도의 구조체로 정의할 수도 있지만, 그러면 열거형을 사용했을 때처럼 하나의 타입으로 취급할 수 없습니다." #: src/enums/variant-payloads.md:1 msgid "# Variant Payloads" @@ -5059,11 +4957,8 @@ msgid "" " PageLoad, // Variant without payload\n" " KeyPress(char), // Tuple struct variant\n" " Click { x: i64, y: i64 }, // Full struct variant\n" -"}" -msgstr "" - -#: src/enums/variant-payloads.md:13 -msgid "" +"}\n" +"\n" "#[rustfmt::skip]\n" "fn inspect(event: WebEvent) {\n" " match event {\n" @@ -5071,19 +4966,13 @@ msgid "" " WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" " WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" " }\n" -"}" -msgstr "" - -#: src/enums/variant-payloads.md:22 -msgid "" +"}\n" +"\n" "fn main() {\n" " let load = WebEvent::PageLoad;\n" " let press = WebEvent::KeyPress('x');\n" -" let click = WebEvent::Click { x: 20, y: 80 };" -msgstr "" - -#: src/enums/variant-payloads.md:27 -msgid "" +" let click = WebEvent::Click { x: 20, y: 80 };\n" +"\n" " inspect(load);\n" " inspect(press);\n" " inspect(click);\n" @@ -5102,8 +4991,7 @@ msgid "" "* It is possible to retrieve the discriminant by calling `std::mem::discriminant()`\n" " * This is useful, for example, if implementing `PartialEq` for structs where comparing field values doesn't affect equality.\n" "* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::Click(Click)` with a top level `struct Click { ... }`. The inlined version cannot implement traits, for example. \n" -" \n" -"
" +" " msgstr "" "* 열거형 안의 값은 패턴 매칭이 되고 난 이후에만 접근 가능합니다. 그 값에 대한 레퍼런스는 `=>` 이후에 사용가능합니다.\n" " * 매치 패턴들은 위에서 아래로 순서에 따라 검사합니다. C나 C++에서와 같은 fall-through는 없습니다.\n" @@ -5114,8 +5002,7 @@ msgstr "" "* `std::mem::discriminant()`를 이용하여 식별자를 얻을 수도 있습니다.\n" " * 이는 각 필드 값을 굳이 비교할 필요 없는 구조체에 대해 `PartialEq` 트레잇을 구현할 때 유용합니다.\n" "* `WebEvent::Click { ... }`은 최상위 레벨 구조체 `struct Click {...}`를 따로 정의하고 `WebEvent::Click(Click)`처럼 튜플 형태로 정의한 것과 정확히 같진 않습니다. 예를 들어 `WebEvent::Click { ... }` 로 정의한 경우, 구조체 형태와 유사하지만 트레잇을 구현 할 수 없습니다.\n" -" \n" -"" +" " #: src/enums/sizes.md:1 msgid "# Enum Sizes" @@ -5128,46 +5015,40 @@ msgstr "러스트의 열거형은 정렬(alignment)로 인한 제약을 고려 #: src/enums/sizes.md:5 msgid "" "```rust,editable\n" -"use std::mem::{align_of, size_of};" -msgstr "" -"```rust,editable\n" -"use std::mem::{align_of, size_of};" - -#: src/enums/sizes.md:8 -msgid "" +"use std::mem::{align_of, size_of};\n" +"\n" "macro_rules! dbg_size {\n" " ($t:ty) => {\n" " println!(\"{}: size {} bytes, align: {} bytes\",\n" " stringify!($t), size_of::<$t>(), align_of::<$t>());\n" " };\n" -"}" +"}\n" +"\n" +"enum Foo {\n" +" A,\n" +" B,\n" +"}\n" +"\n" +"fn main() {\n" +" dbg_size!(Foo);\n" +"}\n" +"```" msgstr "" +"```rust,editable\n" +"use std::mem::{align_of, size_of};\n" +"\n" "macro_rules! dbg_size {\n" " ($t:ty) => {\n" " println!(\"{}: size {} bytes, align: {} bytes\",\n" " stringify!($t), size_of::<$t>(), align_of::<$t>());\n" " };\n" -"}" - -#: src/enums/sizes.md:15 -msgid "" -"enum Foo {\n" -" A,\n" -" B,\n" -"}" -msgstr "" +"}\n" +"\n" "enum Foo {\n" " A,\n" " B,\n" -"}" - -#: src/enums/sizes.md:20 -msgid "" -"fn main() {\n" -" dbg_size!(Foo);\n" "}\n" -"```" -msgstr "" +"\n" "fn main() {\n" " dbg_size!(Foo);\n" "}\n" @@ -5178,11 +5059,9 @@ msgid "* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layou msgstr "* 자세한 사항은 [공식문서](https://doc.rust-lang.org/reference/type-layout.html)를 확인하세요." #: src/enums/sizes.md:31 -msgid " * Internally Rust is using a field (discriminant) to keep track of the enum variant." -msgstr "* 러스트는 열거형 variant를 구분하기 위해 내부적으로 식별자(discriminant) 필드를 사용합니다." - -#: src/enums/sizes.md:33 msgid "" +" * Internally Rust is using a field (discriminant) to keep track of the enum variant.\n" +"\n" " * You can control the discriminant if needed (e.g., for compatibility with C):\n" " \n" " ```rust,editable\n" @@ -5198,9 +5077,116 @@ msgid "" " println!(\"B: {}\", Bar::B as u32);\n" " println!(\"C: {}\", Bar::C as u32);\n" " }\n" +" ```\n" +"\n" +" Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2\n" +" bytes.\n" +"\n" +"\n" +" * Try out other types such as\n" +" \n" +" * `dbg_size!(bool)`: size 1 bytes, align: 1 bytes,\n" +" * `dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche optimization, see below),\n" +" * `dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit machine),\n" +" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer optimization, see below).\n" +"\n" +" * Niche optimization: Rust will merge use unused bit patterns for the enum\n" +" discriminant.\n" +"\n" +" * Null pointer optimization: For [some\n" +" types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees\n" +" that `size_of::()` equals `size_of::>()`.\n" +"\n" +" Example code if you want to show how the bitwise representation *may* look like in practice.\n" +" It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally unsafe.\n" +"\n" +" ```rust,editable\n" +" use std::mem::transmute;\n" +"\n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" println!(\"Bitwise representation of bool\");\n" +" dbg_bits!(false, u8);\n" +" dbg_bits!(true, u8);\n" +"\n" +" println!(\"Bitwise representation of Option\");\n" +" dbg_bits!(None::, u8);\n" +" dbg_bits!(Some(false), u8);\n" +" dbg_bits!(Some(true), u8);\n" +"\n" +" println!(\"Bitwise representation of Option>\");\n" +" dbg_bits!(Some(Some(false)), u8);\n" +" dbg_bits!(Some(Some(true)), u8);\n" +" dbg_bits!(Some(None::), u8);\n" +" dbg_bits!(None::>, u8);\n" +"\n" +" println!(\"Bitwise representation of Option<&i32>\");\n" +" dbg_bits!(None::<&i32>, usize);\n" +" dbg_bits!(Some(&0i32), usize);\n" +" }\n" +" }\n" +" ```\n" +"\n" +" More complex example if you want to discuss what happens when we chain more than 256 `Option`s together.\n" +"\n" +" ```rust,editable\n" +" #![recursion_limit = \"1000\"]\n" +"\n" +" use std::mem::transmute;\n" +" \n" +" macro_rules! dbg_bits {\n" +" ($e:expr, $bit_type:ty) => {\n" +" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" +" };\n" +" }\n" +"\n" +" // Macro to wrap a value in 2^n Some() where n is the number of \"@\" signs.\n" +" // Increasing the recursion limit is required to evaluate this macro.\n" +" macro_rules! many_options {\n" +" ($value:expr) => { Some($value) };\n" +" ($value:expr, @) => {\n" +" Some(Some($value))\n" +" };\n" +" ($value:expr, @ $($more:tt)+) => {\n" +" many_options!(many_options!($value, $($more)+), $($more)+)\n" +" };\n" +" }\n" +"\n" +" fn main() {\n" +" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" +" // representation of types.\n" +" unsafe {\n" +" assert_eq!(many_options!(false), Some(false));\n" +" assert_eq!(many_options!(false, @), Some(Some(false)));\n" +" assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));\n" +"\n" +" println!(\"Bitwise representation of a chain of 128 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" +" dbg_bits!(many_options!(true, @@@@@@@), u8);\n" +"\n" +" println!(\"Bitwise representation of a chain of 256 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(true, @@@@@@@@), u16);\n" +"\n" +" println!(\"Bitwise representation of a chain of 257 Option's.\");\n" +" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" +" }\n" +" }\n" " ```" msgstr "" -" * C와의 연동과 같은 이유로 식별자를 직접 지정할 수도 있습니다:\n" +"* 러스트는 열거형 variant를 구분하기 위해 내부적으로 식별자(discriminant) 필드를 사용합니다.\n" +"\n" +"* C와의 연동과 같은 이유로 식별자를 직접 지정할 수도 있습니다:\n" " \n" " ```rust,editable\n" " #[repr(u32)]\n" @@ -5215,228 +5201,18 @@ msgstr "" " println!(\"B: {}\", Bar::B as u32);\n" " println!(\"C: {}\", Bar::C as u32);\n" " }\n" -" ```" - -#: src/enums/sizes.md:50 -msgid "" -" Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2\n" -" bytes." -msgstr " `repr` 속성이 없다면 10001이 2 바이트로 표현가능하기 때문에 식별자의 타입 크기는 2 바이트가 됩니다." - -#: src/enums/sizes.md:54 -msgid "" -" * Try out other types such as\n" -" \n" -" * `dbg_size!(bool)`: size 1 bytes, align: 1 bytes,\n" -" * `dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche optimization, see below),\n" -" * `dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit machine),\n" -" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer optimization, see below)." -msgstr "" -" * 다른 타입들도 확인해보세요.\n" -" \n" +" ```\n" +"\n" +" `repr` 속성이 없다면 10001이 2 바이트로 표현가능하기 때문에 식별자의 타입 크기는 2 바이트가 됩니다.\n" +"\n" +"* 다른 타입들도 확인해보세요.\n" +"\n" " * `dbg_size!(bool)`: size 1 bytes, align: 1 bytes\n" " * `dbg_size!(Option)`: size 1 bytes, align: 1 bytes (니치 최적화, 아래 설명 참조)\n" " * `dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (64비트 머신인 경우)\n" -" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (널포인터 최적화, 아래 설명 참조)" - -#: src/enums/sizes.md:61 -msgid "" -" * Niche optimization: Rust will merge use unused bit patterns for the enum\n" -" discriminant." -msgstr " * 니치 최적화: 러스트는 열거형 식별자를 사용되지 않은 비트 패턴과 병합합니다." - -#: src/enums/sizes.md:64 -msgid "" -" * Null pointer optimization: For [some\n" -" types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees\n" -" that `size_of::()` equals `size_of::>()`." -msgstr " * 널포인터 최적화: `size_of::()`와 `size_of::>()`가 같음이 보장되는 타입도 있습니다. [여기](https://doc.rust-lang.org/std/option/#representation)를 참조하세요." - -#: src/enums/sizes.md:68 -msgid "" -"Example code if you want to show how the bitwise representation *may* look like in practice.\n" -"It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally unsafe." -msgstr "비트 수준에서 어떤식으로 표현되는지 보여주고 싶다면 다음 예제 코드를 사용해보세요. 컴파일러가 비트 표현까지 보장하지 않기 때문에 여기에 의존하는 것은 안전하지 않다는 점을 꼭 알려주세요." - -#: src/enums/sizes.md:71 -msgid "" -"```rust,editable\n" -"use std::mem::transmute;" -msgstr "" -"```rust,editable\n" -"use std::mem::transmute;" - -#: src/enums/sizes.md:74 src/enums/sizes.md:113 -msgid "" -"macro_rules! dbg_bits {\n" -" ($e:expr, $bit_type:ty) => {\n" -" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" -" };\n" -"}" -msgstr "" -"macro_rules! dbg_bits {\n" -" ($e:expr, $bit_type:ty) => {\n" -" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, $bit_type>($e));\n" -" };\n" -"}" - -#: src/enums/sizes.md:80 -msgid "" -"fn main() {\n" -" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" -" // representation of types.\n" -" unsafe {\n" -" println!(\"Bitwise representation of bool\");\n" -" dbg_bits!(false, u8);\n" -" dbg_bits!(true, u8);" -msgstr "" -"fn main() {\n" -" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" -" // representation of types.\n" -" unsafe {\n" -" println!(\"Bitwise representation of bool\");\n" -" dbg_bits!(false, u8);\n" -" dbg_bits!(true, u8);" - -#: src/enums/sizes.md:88 -msgid "" -" println!(\"Bitwise representation of Option\");\n" -" dbg_bits!(None::, u8);\n" -" dbg_bits!(Some(false), u8);\n" -" dbg_bits!(Some(true), u8);" -msgstr "" -" println!(\"Bitwise representation of Option\");\n" -" dbg_bits!(None::, u8);\n" -" dbg_bits!(Some(false), u8);\n" -" dbg_bits!(Some(true), u8);" - -#: src/enums/sizes.md:93 -msgid "" -" println!(\"Bitwise representation of Option>\");\n" -" dbg_bits!(Some(Some(false)), u8);\n" -" dbg_bits!(Some(Some(true)), u8);\n" -" dbg_bits!(Some(None::), u8);\n" -" dbg_bits!(None::>, u8);" -msgstr "" -" println!(\"Bitwise representation of Option>\");\n" -" dbg_bits!(Some(Some(false)), u8);\n" -" dbg_bits!(Some(Some(true)), u8);\n" -" dbg_bits!(Some(None::), u8);\n" -" dbg_bits!(None::>, u8);" - -#: src/enums/sizes.md:99 -msgid "" -" println!(\"Bitwise representation of Option<&i32>\");\n" -" dbg_bits!(None::<&i32>, usize);\n" -" dbg_bits!(Some(&0i32), usize);\n" -" }\n" -"}\n" -"```" -msgstr "" -" println!(\"Bitwise representation of Option<&i32>\");\n" -" dbg_bits!(None::<&i32>, usize);\n" -" dbg_bits!(Some(&0i32), usize);\n" -" }\n" -"}\n" -"```" - -#: src/enums/sizes.md:106 -msgid "More complex example if you want to discuss what happens when we chain more than 256 `Option`s together." -msgstr "좀더 복잡한 예제입니다. `Option`을 256개 이상으로 중첩한 경우에 어떻게 되는지 볼 수 있습니다." - -#: src/enums/sizes.md:108 -msgid "" -"```rust,editable\n" -"#![recursion_limit = \"1000\"]" -msgstr "" -"```rust,editable\n" -"#![recursion_limit = \"1000\"]" - -#: src/enums/sizes.md:111 -msgid "use std::mem::transmute;" -msgstr "use std::mem::transmute;" - -#: src/enums/sizes.md:119 -msgid "" -"// Macro to wrap a value in 2^n Some() where n is the number of \"@\" signs.\n" -"// Increasing the recursion limit is required to evaluate this macro.\n" -"macro_rules! many_options {\n" -" ($value:expr) => { Some($value) };\n" -" ($value:expr, @) => {\n" -" Some(Some($value))\n" -" };\n" -" ($value:expr, @ $($more:tt)+) => {\n" -" many_options!(many_options!($value, $($more)+), $($more)+)\n" -" };\n" -"}" -msgstr "" -"// Macro to wrap a value in 2^n Some() where n is the number of \"@\" signs.\n" -"// Increasing the recursion limit is required to evaluate this macro.\n" -"macro_rules! many_options {\n" -" ($value:expr) => { Some($value) };\n" -" ($value:expr, @) => {\n" -" Some(Some($value))\n" -" };\n" -" ($value:expr, @ $($more:tt)+) => {\n" -" many_options!(many_options!($value, $($more)+), $($more)+)\n" -" };\n" -"}" - -#: src/enums/sizes.md:131 -msgid "" -"fn main() {\n" -" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" -" // representation of types.\n" -" unsafe {\n" -" assert_eq!(many_options!(false), Some(false));\n" -" assert_eq!(many_options!(false, @), Some(Some(false)));\n" -" assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));" -msgstr "" -"fn main() {\n" -" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" -" // representation of types.\n" -" unsafe {\n" -" assert_eq!(many_options!(false), Some(false));\n" -" assert_eq!(many_options!(false, @), Some(Some(false)));\n" -" assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));" - -#: src/enums/sizes.md:139 -msgid "" -" println!(\"Bitwise representation of a chain of 128 Option's.\");\n" -" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" -" dbg_bits!(many_options!(true, @@@@@@@), u8);" -msgstr "" -" println!(\"Bitwise representation of a chain of 128 Option's.\");\n" -" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" -" dbg_bits!(many_options!(true, @@@@@@@), u8);" - -#: src/enums/sizes.md:143 -msgid "" -" println!(\"Bitwise representation of a chain of 256 Option's.\");\n" -" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(true, @@@@@@@@), u16);" -msgstr "" -" println!(\"Bitwise representation of a chain of 256 Option's.\");\n" -" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(true, @@@@@@@@), u16);" - -#: src/enums/sizes.md:147 -msgid "" -" println!(\"Bitwise representation of a chain of 257 Option's.\");\n" -" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" -" }\n" -"}\n" -"```" -msgstr "" -" println!(\"Bitwise representation of a chain of 257 Option's.\");\n" -" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" -" }\n" -"}\n" -"```" +" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (널포인터 최적화, 아래 설명 참조)\n" +"\n" +"* 니치 최적화: 러스트는 열거형 식별자를 사용되지 않은 비트 패턴과 병합합니다." #: src/methods.md:3 msgid "" @@ -5444,17 +5220,21 @@ msgid "" "`impl` block:" msgstr "러스트에서 선언된 타입에 대해 `impl`블록에 함수를 선언하여 메서드를 연결 할 수 있습니다:" -#: src/methods.md:13 +#: src/methods.md:6 msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" "impl Person {\n" " fn say_hello(&self) {\n" " println!(\"Hello, my name is {}\", self.name);\n" " }\n" -"}" -msgstr "" - -#: src/methods.md:19 -msgid "" +"}\n" +"\n" "fn main() {\n" " let peter = Person {\n" " name: String::from(\"Peter\"),\n" @@ -5465,9 +5245,8 @@ msgid "" "```" msgstr "" -#: src/methods.md:30 +#: src/methods.md:31 msgid "" -"Key Points:\n" "* It can be helpful to introduce methods by comparing them to functions.\n" " * Methods are called on an instance of a type (such as a struct or enum), the first parameter represents the instance as `self`.\n" " * Developers may choose to use methods to take advantage of method receiver syntax and to help keep them more organized. By using methods we can keep all the implementation code in one predictable place.\n" @@ -5477,10 +5256,8 @@ msgid "" " * Note how `self` is used like other structs and dot notation can be used to refer to individual fields.\n" " * This might be a good time to demonstrate how the `&self` differs from `self` by modifying the code and trying to run say_hello twice. \n" "* We describe the distinction between method receivers next.\n" -" \n" -"" +" " msgstr "" -"키 포인트: \n" "* 메서드를 함수와 비교하여 소개하는 것도 도움이 될 수 있습니다.\n" " * 메서드는 구조체나 열거형과 같은 타입의 인스턴스에서 호출 되며, 첫번째 매개변수(파라메터)는 인스턴스를 `self`로 표기합니다.\n" " * 메서드를 이용하면 receiver 문법을 사용할 수 있고 코드를 좀더 체계적으로 정리할 수 있습니다. 메서드들이 예측 가능한 위치에 모여 있으니 찾기 쉽습니다.\n" @@ -5490,7 +5267,7 @@ msgstr "" " * 구조체의 필드를 접근할 때 점 표기를 사용하듯이 `self`에 점 표기를 사용하여 개별 필드들을 접근할 수 있습니다.\n" " * `say_hello` 함수가 두 번 호출되도록 코드를 수정하여 `&self`와 `self`가 어떻게 다른지 보여주는 것도 좋습니다.\n" "* 다음 슬라이드에서 receiver의 구분을 설명합니다.\n" -"" +" " #: src/methods/receiver.md:1 msgid "# Method Receiver" @@ -5530,20 +5307,12 @@ msgid "" "allowed to be receiver types, such as `Box`." msgstr "`self`를 사용하는 이같은 변형들 외에도 `Box`와 같이 리시버 타입으로 허용되는 [특별한 래퍼 타입](https://doc.rust-lang.org/reference/special-types-and-traits.html)이 있습니다." -#: src/methods/receiver.md:23 +#: src/methods/receiver.md:25 msgid "" -"
\n" -" \n" "Consider emphasizing \"shared and immutable\" and \"unique and mutable\". These constraints always come\n" "together in Rust due to borrow checker rules, and `self` is no exception. It isn't possible to\n" -"reference a struct from multiple locations and call a mutating (`&mut self`) method on it.\n" -" \n" -"
" -msgstr "" -"
\n" -" \n" -" \"공유가능한 불변\"과 \"유일한 가변\" 부분은 강조할 만합니다. 이러한 제약은 러스트의 빌림 검사기(borrow checker) 규칙으로 늘 붙어다닙니다. `self`도 예외는 아닙니다. 여러 위치에서 구조체를 참조하면서 객체를 수정하는(`&mut self`를 리시버로 하는) 메서드를 호출하는 것은 불가능합니다.\n" -"
" +"reference a struct from multiple locations and call a mutating (`&mut self`) method on it." +msgstr "\"공유가능한 불변\"과 \"유일한 가변\" 부분은 강조할 만합니다. 이러한 제약은 러스트의 빌림 검사기(borrow checker) 규칙으로 늘 붙어다닙니다. `self`도 예외는 아닙니다. 여러 위치에서 구조체를 참조하면서 객체를 수정하는(`&mut self`를 리시버로 하는) 메서드를 호출하는 것은 불가능합니다." #: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 msgid "# Example" @@ -5556,63 +5325,30 @@ msgid "" "struct Race {\n" " name: String,\n" " laps: Vec,\n" -"}" -msgstr "" - -#: src/methods/example.md:10 -msgid "" +"}\n" +"\n" "impl Race {\n" " fn new(name: &str) -> Race { // No receiver, a static method\n" " Race { name: String::from(name), laps: Vec::new() }\n" -" }" -msgstr "" -"impl Race {\n" -" fn new(name: &str) -> Race { // 리시버 없음. 정적 메서드\n" -" Race { name: String::from(name), laps: Vec::new() }\n" -" }" - -#: src/methods/example.md:15 -msgid "" +" }\n" +"\n" " fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write access to self\n" " self.laps.push(lap);\n" -" }" -msgstr "" -" fn add_lap(&mut self, lap: i32) { // self에 대한 배타적인 빌림. 읽고 쓰기 가능\n" -" self.laps.push(lap);\n" -" }" - -#: src/methods/example.md:19 -msgid "" +" }\n" +"\n" " fn print_laps(&self) { // Shared and read-only borrowed access to self\n" " println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" " for (idx, lap) in self.laps.iter().enumerate() {\n" " println!(\"Lap {idx}: {lap} sec\");\n" " }\n" -" }" -msgstr "" -" fn print_laps(&self) { // self에 대한 읽기 전용 빌림. 공유 가능\n" -" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" -" for (idx, lap) in self.laps.iter().enumerate() {\n" -" println!(\"Lap {idx}: {lap} sec\");\n" -" }\n" -" }" - -#: src/methods/example.md:26 -msgid "" -" fn finish(self) { // Exclusive ownership of self\n" -" let total = self.laps.iter().sum::();\n" -" println!(\"Race {} is finished, total lap time: {}\", self.name, total);\n" " }\n" -"}" -msgstr "" -" fn finish(self) { // 배타적 self 소유권\n" +"\n" +" fn finish(self) { // Exclusive ownership of self\n" " let total = self.laps.iter().sum::();\n" " println!(\"Race {} is finished, total lap time: {}\", self.name, total);\n" " }\n" -"}" - -#: src/methods/example.md:32 -msgid "" +"}\n" +"\n" "fn main() {\n" " let mut race = Race::new(\"Monaco Grand Prix\");\n" " race.add_lap(70);\n" @@ -5626,20 +5362,14 @@ msgid "" "```" msgstr "" -#: src/methods/example.md:44 +#: src/methods/example.md:47 msgid "" -"
\n" -" \n" -"Key Points:\n" "* All four methods here use a different method receiver.\n" " * You can point out how that changes what the function can do with the variable values and if/how it can be used again in `main`.\n" " * You can showcase the error that appears when trying to call `finish` twice.\n" "* Note that although the method receivers are different, the non-static functions are called the same way in the main body. Rust enables automatic referencing and dereferencing when calling methods. Rust automatically adds in the `&`, `*`, `muts` so that that object matches the method signature.\n" "* You might point out that `print_laps` is using a vector that is iterated over. We describe vectors in more detail in the afternoon. " msgstr "" -"
\n" -" \n" -"키 포인트:\n" "* 4가지 유형의 메서드 receiver에 대해 설명합니다.\n" " * receiver 유형에 따라 함수가 할 수 있는 일이 달라지고, 또 메소드를 호출한 뒤 `main`에서 해당 객체를 사용할 수 있는지 여부도 달라진다는 점을 강조하세요.\n" " * `finish`를 두번 호출하여 오류가 발생하는 것을 보일 수 있습니다.\n" @@ -5664,11 +5394,8 @@ msgstr "C/C++의 `switch`와 비슷하게 값을 패턴으로 사용할 수도 msgid "" "```rust,editable\n" "fn main() {\n" -" let input = 'x';" -msgstr "" - -#: src/pattern-matching.md:12 -msgid "" +" let input = 'x';\n" +"\n" " match input {\n" " 'q' => println!(\"Quitting\"),\n" " 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" @@ -5678,16 +5405,25 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let input = 'x';\n" +"\n" +" match input {\n" +" 'q' => println!(\"Quitting\"),\n" +" 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" +" '0'..='9' => println!(\"Number input\"),\n" +" _ => println!(\"Something else\"),\n" +" }\n" +"}\n" +"```" #: src/pattern-matching.md:21 msgid "The `_` pattern is a wildcard pattern which matches any value." msgstr "`_`패턴은 어떤 값과도 매칭되는 와일드카드입니다." -#: src/pattern-matching.md:23 +#: src/pattern-matching.md:26 msgid "" -"
\n" -" \n" -"Key Points:\n" "* You might point out how some specific characters are being used when in a pattern\n" " * `|` as an `or`\n" " * `..` can expand as much as it needs to be\n" @@ -5696,12 +5432,8 @@ msgid "" "* It can be useful to show how binding works, by for instance replacing a wildcard character with a variable, or removing the quotes around `q`.\n" "* You can demonstrate matching on a reference.\n" "* This might be a good time to bring up the concept of irrefutable patterns, as the term can show up in error messages.\n" -" \n" -"
" +" " msgstr "" -"
\n" -" \n" -"키 포인트:\n" "* 패턴에서 사용되는 특수 문자들을 알려주세요.\n" " * `|`: or 기호입니다.\n" " * `..`: 필요한 만큼 확장합니다.\n" @@ -5710,8 +5442,7 @@ msgstr "" "* 와일드카드 문자를 변수로 바꾸거나 `q`의 따옴표를 제거하는 식으로 수정하면서 바인딩이 어떻게 작동하는지 보여주는 것도 유용할 수 있습니다.\n" "* 참조를 매칭하는 것도 시연할 수 있습니다.\n" "* 에러 메시지에 \"반박 불가능 패턴(irrefutable pattern)\"이란 용어가 등장하기도 합니다. 지금 그 의미를 소개하는 것도 좋을 것 같습니다.\n" -"\n" -"
" +" " #: src/pattern-matching/destructuring-enums.md:1 msgid "# Destructuring Enums" @@ -5729,34 +5460,16 @@ msgid "" "enum Result {\n" " Ok(i32),\n" " Err(String),\n" -"}" -msgstr "" -"```rust,editable\n" -"enum Result {\n" -" Ok(i32),\n" -" Err(String),\n" -"}" - -#: src/pattern-matching/destructuring-enums.md:12 -msgid "" -"fn divide_in_two(n: i32) -> Result {\n" -" if n % 2 == 0 {\n" -" Result::Ok(n / 2)\n" -" } else {\n" -" Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" -" }\n" -"}" -msgstr "" +"}\n" +"\n" "fn divide_in_two(n: i32) -> Result {\n" " if n % 2 == 0 {\n" " Result::Ok(n / 2)\n" " } else {\n" " Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" " }\n" -"}" - -#: src/pattern-matching/destructuring-enums.md:20 -msgid "" +"}\n" +"\n" "fn main() {\n" " let n = 100;\n" " match divide_in_two(n) {\n" @@ -5766,6 +5479,20 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"enum Result {\n" +" Ok(i32),\n" +" Err(String),\n" +"}\n" +"\n" +"fn divide_in_two(n: i32) -> Result {\n" +" if n % 2 == 0 {\n" +" Result::Ok(n / 2)\n" +" } else {\n" +" Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" +" }\n" +"}\n" +"\n" "fn main() {\n" " let n = 100;\n" " match divide_in_two(n) {\n" @@ -5782,13 +5509,11 @@ msgid "" "`msg` is bound to the error message." msgstr "`match`구문에서 `divide_in_two`함수에서 반환되는 `Result` 값을 두 개의 팔(혹은 가지)로 _분해(destructure)_ 하였습니다. 첫번째 팔에서 `half`는 `Ok` variant에 담긴 값으로 바인딩됩니다. 두번째 팔에서 `msg`는 오류 메시지 문자열에 바인딩됩니다." -#: src/pattern-matching/destructuring-enums.md:35 +#: src/pattern-matching/destructuring-enums.md:36 msgid "" -"Key points:\n" "* The `if`/`else` expression is returning an enum that is later unpacked with a `match`.\n" "* You can try adding a third variant to the enum definition and displaying the errors when running the code. Point out the places where your code is now inexhaustive and how the compiler tries to give you hints." msgstr "" -"키 포인트:\n" "* `if`/`else` 표현식은 열거형을 반환하고, 이 값은 나중에 `match`로 분해됩니다.\n" "* 열거형에 세번째 variant를 추가하고 코드를 실행하여 오류를 표시해보세요. 코드 어느 부분에 누락이 있는지, 그리고 컴파일러가 어떤 식으로 힌트를 주는지 같이 살펴보세요." @@ -5806,16 +5531,8 @@ msgid "" "struct Foo {\n" " x: (u32, u32),\n" " y: u32,\n" -"}" -msgstr "" -"```rust,editable\n" -"struct Foo {\n" -" x: (u32, u32),\n" -" y: u32,\n" -"}" - -#: src/pattern-matching/destructuring-structs.md:11 -msgid "" +"}\n" +"\n" "#[rustfmt::skip]\n" "fn main() {\n" " let foo = Foo { x: (1, 2), y: 3 };\n" @@ -5825,9 +5542,14 @@ msgid "" " Foo { y, .. } => println!(\"y = {y}, other fields were ignored\"),\n" " }\n" "}\n" -"```\n" -"
" +"```" msgstr "" +"```rust,editable\n" +"struct Foo {\n" +" x: (u32, u32),\n" +" y: u32,\n" +"}\n" +"\n" "#[rustfmt::skip]\n" "fn main() {\n" " let foo = Foo { x: (1, 2), y: 3 };\n" @@ -5837,18 +5559,15 @@ msgstr "" " Foo { y, .. } => println!(\"y = {y}, other fields were ignored\"),\n" " }\n" "}\n" -"```\n" -"
" +"```" #: 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.\n" -"
" +"* Add a new field to `Foo` and make changes to the pattern as needed." msgstr "" "* `foo` 인스턴스 생성에 사용된 리터럴 값을 변경해서 다른 패턴에 매치되도록 해보세요.\n" -"* `Foo` 구조체에 새 필드를 추가하고 패턴도 바꿔보세요.\n" -"
" +"* `Foo` 구조체에 새 필드를 추가하고 패턴도 바꿔보세요." #: src/pattern-matching/destructuring-arrays.md:1 msgid "# Destructuring Arrays" @@ -5887,56 +5606,56 @@ msgstr "" "```" #: src/pattern-matching/destructuring-arrays.md:21 -msgid "* Destructuring of slices of unknown length also works with patterns of fixed length." -msgstr "* 길이를 알 수 없는 슬라이스에 대해서도 고정 길이 패턴으로 분해할 수 있습니다." - -#: src/pattern-matching/destructuring-arrays.md:24 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" inspect(&[0, -2, 3]);\n" -" inspect(&[0, -2, 3, 4]);\n" -"}" -msgstr "" -"```rust,editable\n" -"fn main() {\n" -" inspect(&[0, -2, 3]);\n" -" inspect(&[0, -2, 3, 4]);\n" -"}" - -#: src/pattern-matching/destructuring-arrays.md:30 msgid "" -"#[rustfmt::skip]\n" -"fn inspect(slice: &[i32]) {\n" -" println!(\"Tell me about {slice:?}\");\n" -" match slice {\n" -" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" -" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" -" _ => println!(\"All elements were ignored\"),\n" -" }\n" -"}\n" -"```\n" +"* Destructuring of slices of unknown length also works with patterns of fixed length.\n" +"\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" inspect(&[0, -2, 3]);\n" +" inspect(&[0, -2, 3, 4]);\n" +" }\n" +"\n" +" #[rustfmt::skip]\n" +" fn inspect(slice: &[i32]) {\n" +" println!(\"Tell me about {slice:?}\");\n" +" match slice {\n" +" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +" }\n" +" ```\n" " \n" "* Create a new pattern using `_` to represent an element. \n" "* Add more values to the array.\n" "* Point out that how `..` will expand to account for different number of elements.\n" "* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`" msgstr "" -"#[rustfmt::skip]\n" -"fn inspect(slice: &[i32]) {\n" -" println!(\"Tell me about {slice:?}\");\n" -" match slice {\n" -" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" -" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" -" _ => println!(\"All elements were ignored\"),\n" -" }\n" -"}\n" -"```\n" -"* 엘리먼트를 매칭할 때 `_`를 사용하는 패턴을 추가해 보세요.\n" -"* 배열에 값을 더 추가해 보세요.\n" -"* `..`가 서로 다른 개수의 엘리먼트들에 대해 어떻게 확장되는지 설명하세요.\n" -"* `[.., b]`나 `[a@.., b]`와 같은 패턴으로 꼬리 부분을 매칭하는 것을 보여주세요.\n" -"
" +"* 길이를 알 수 없는 슬라이스에 대해서도 고정 길이 패턴으로 분해할 수 있습니다.\n" +"\n" +"\n" +" ```rust,editable\n" +" fn main() {\n" +" inspect(&[0, -2, 3]);\n" +" inspect(&[0, -2, 3, 4]);\n" +" }\n" +"\n" +" #[rustfmt::skip]\n" +" fn inspect(slice: &[i32]) {\n" +" println!(\"Tell me about {slice:?}\");\n" +" match slice {\n" +" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" +" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" +" _ => println!(\"All elements were ignored\"),\n" +" }\n" +" }\n" +" ```\n" +" \n" +"* `_`를 사용하여 요소를 매칭하는 패턴을 추가해보세요.\n" +"* 배열에 값을 더 추가해보세요.\n" +"* `..`가 요소 개수에 상관없이 매치될 수 있음을 알려주세요.\n" +"* `[.., b]`나 `[a@.., b]`와 같은 패턴으로 꼬리 부분을 매칭하는 것을 보여주세요." #: src/pattern-matching/match-guards.md:1 msgid "# Match Guards" @@ -5978,23 +5697,18 @@ msgstr "" "}\n" "```" -#: src/pattern-matching/match-guards.md:22 +#: src/pattern-matching/match-guards.md:23 msgid "" -"Key Points:\n" "* Match guards as a separate syntax feature are important and necessary when we wish to concisely express more complex ideas than patterns alone would allow.\n" "* They are not the same as separate `if` expression inside of the match arm. An `if` expression inside of the branch block (after `=>`) happens after the match arm is selected. Failing the `if` condition inside of that block won't result in other arms\n" "of the original `match` expression being considered. \n" "* You can use the variables defined in the pattern in your if expression.\n" -"* The condition defined in the guard applies to every expression in a pattern with an `|`.\n" -"
" +"* The condition defined in the guard applies to every expression in a pattern with an `|`." msgstr "" -"키 포인트:\n" "* 매치 가드는 별도의 문법 요소로서 패턴 자체만으로 표현하기 어려운 복잡한 경우를 간결하게 표현하고자 할 때 유용합니다.\n" -"* 매치의 각 팔(혹은 가지) 안에 따로 `if`를 사용한 것과 다릅니다. 매치 가지의 `=>` 뒤에 사용된 `if` 표현식은 해당\n" -" 가지가 선택된 다음에 실행됩니다. 따라서 여기서 `if` 조건이 실패하더라도 원래 `match`의 다른 가지는 고려되지 않습니다.\n" +"* 매치의 각 팔(혹은 가지) 안에 따로 `if`를 사용한 것과 다릅니다. 매치 가지의 `=>` 뒤에 사용된 `if` 표현식은 해당 가지가 선택된 다음에 실행됩니다. 따라서 여기서 `if` 조건이 실패하더라도 원래 `match`의 다른 가지는 고려되지 않습니다.\n" "* 패턴에 정의된 변수를 가드의 표현식에서 사용할 수 있습니다.\n" -"* 가드에 정의된 조건은 `|` 를 포함하는 패턴의 모든 표현식에 적용됩니다.\n" -"" +"* 가드에 정의된 조건은 `|` 를 포함하는 패턴의 모든 표현식에 적용됩니다." #: src/exercises/day-2/morning.md:1 msgid "# Day 2: Morning Exercises" @@ -6005,12 +5719,14 @@ msgid "We will look at implementing methods in two contexts:" msgstr "이번 연습문제들은 두가지 맥락에서 메서드 구현방법을 다룹니다:" #: src/exercises/day-2/morning.md:5 -msgid "* Simple struct which tracks health statistics." -msgstr "* 건강 상태 통계를 추적하는 프로그램의 간단한 구조체." - -#: src/exercises/day-2/morning.md:7 -msgid "* Multiple structs and enums for a drawing library." -msgstr "* 드로잉 라이브러리를 위한 구조체 및 열거헝." +msgid "" +"* Simple struct which tracks health statistics.\n" +"\n" +"* Multiple structs and enums for a drawing library." +msgstr "" +"* 건강 상태 통계를 추적하는 프로그램의 간단한 구조체.\n" +"\n" +"* 드로잉 라이브러리를 위한 구조체 및 열거헝." #: src/exercises/day-2/health-statistics.md:1 msgid "# Health Statistics" @@ -6035,78 +5751,55 @@ msgid "" "methods:" msgstr "아래 코드를 에 복사해서 빠진 메서드를 구현하면 됩니다:" -#: src/exercises/day-2/health-statistics.md:17 +#: src/exercises/day-2/health-statistics.md:13 msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" "struct User {\n" " name: String,\n" " age: u32,\n" " weight: f32,\n" -"}" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:23 -msgid "" +"}\n" +"\n" "impl User {\n" " pub fn new(name: String, age: u32, weight: f32) -> Self {\n" " unimplemented!()\n" -" }" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:28 -msgid "" +" }\n" +"\n" " pub fn name(&self) -> &str {\n" " unimplemented!()\n" -" }" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:32 -msgid "" +" }\n" +"\n" " pub fn age(&self) -> u32 {\n" " unimplemented!()\n" -" }" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:36 -msgid "" +" }\n" +"\n" " pub fn weight(&self) -> f32 {\n" " unimplemented!()\n" -" }" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:40 -msgid "" +" }\n" +"\n" " pub fn set_age(&mut self, new_age: u32) {\n" " unimplemented!()\n" -" }" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:44 -msgid "" +" }\n" +"\n" " pub fn set_weight(&mut self, new_weight: f32) {\n" " unimplemented!()\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:49 -msgid "" +"}\n" +"\n" "fn main() {\n" " let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" " println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" -"}" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:54 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_weight() {\n" " let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" " assert_eq!(bob.weight(), 155.2);\n" -"}" -msgstr "" - -#: src/exercises/day-2/health-statistics.md:60 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_set_age() {\n" " let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" @@ -6128,157 +5821,93 @@ msgid "" "tests pass:" msgstr "우리는 몇개의 꼭지점을 가진 다각형을 표현하는 `Polygon` 구조체를 만들 것입니다. 아래 코드를 에 복사해서 테스트가 통과하도록 빠진 메서드를 구현하시면 됩니다:" -#: src/exercises/day-2/points-polygons.md:7 src/exercises/day-2/luhn.md:23 -#: src/exercises/day-2/strings-iterators.md:12 +#: src/exercises/day-2/points-polygons.md:7 msgid "" "```rust\n" "// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:11 -msgid "" +"#![allow(unused_variables, dead_code)]\n" +"\n" "pub struct Point {\n" " // add fields\n" -"}" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:15 -msgid "" +"}\n" +"\n" "impl Point {\n" " // add methods\n" -"}" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:19 -msgid "" +"}\n" +"\n" "pub struct Polygon {\n" " // add fields\n" -"}" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:23 -msgid "" +"}\n" +"\n" "impl Polygon {\n" " // add methods\n" -"}" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:27 -msgid "" +"}\n" +"\n" "pub struct Circle {\n" " // add fields\n" -"}" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:31 -msgid "" +"}\n" +"\n" "impl Circle {\n" " // add methods\n" -"}" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:35 -msgid "" +"}\n" +"\n" "pub enum Shape {\n" " Polygon(Polygon),\n" " Circle(Circle),\n" -"}" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:40 src/testing/test-modules.md:15 -msgid "" +"}\n" +"\n" "#[cfg(test)]\n" "mod tests {\n" -" use super::*;" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:44 -#: src/exercises/day-2/solutions-morning.md:165 -msgid "" +" use super::*;\n" +"\n" " fn round_two_digits(x: f64) -> f64 {\n" " (x * 100.0).round() / 100.0\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:48 -#: src/exercises/day-2/solutions-morning.md:169 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_point_magnitude() {\n" " let p1 = Point::new(12, 13);\n" " assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:54 -#: src/exercises/day-2/solutions-morning.md:175 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_point_dist() {\n" " let p1 = Point::new(10, 10);\n" " let p2 = Point::new(14, 13);\n" " assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:61 -#: src/exercises/day-2/solutions-morning.md:182 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_point_add() {\n" " let p1 = Point::new(16, 16);\n" " let p2 = p1 + Point::new(-4, 3);\n" " assert_eq!(p2, Point::new(12, 19));\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:68 -#: src/exercises/day-2/solutions-morning.md:189 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_polygon_left_most_point() {\n" " let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:73 -#: src/exercises/day-2/solutions-morning.md:194 -msgid "" +" let p2 = Point::new(16, 16);\n" +"\n" " let mut poly = Polygon::new();\n" " poly.add_point(p1);\n" " poly.add_point(p2);\n" " assert_eq!(poly.left_most_point(), Some(p1));\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:79 -#: src/exercises/day-2/solutions-morning.md:200 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_polygon_iter() {\n" " let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:84 -#: src/exercises/day-2/solutions-morning.md:205 -msgid "" +" let p2 = Point::new(16, 16);\n" +"\n" " let mut poly = Polygon::new();\n" " poly.add_point(p1);\n" -" poly.add_point(p2);" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:88 -#: src/exercises/day-2/solutions-morning.md:209 -msgid "" +" poly.add_point(p2);\n" +"\n" " let points = poly.iter().cloned().collect::>();\n" " assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" -" }" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:92 -msgid "" +" }\n" +"\n" " #[test]\n" " fn test_shape_perimeters() {\n" " let mut poly = Polygon::new();\n" @@ -6296,11 +5925,8 @@ msgid "" " .collect::>();\n" " assert_eq!(perimeters, vec![15.48, 31.42]);\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:111 src/exercises/day-2/luhn.md:68 -msgid "" +"}\n" +"\n" "#[allow(dead_code)]\n" "fn main() {}\n" "```" @@ -6313,14 +5939,14 @@ msgid "" msgstr "누락된 메서드 시그니처를 올바르게 정의하는 것이 문제의 핵심 부분입니다. 테스트는 수정하면 안됩니다." #: src/exercises/day-2/points-polygons.md:120 +msgid "Other interesting parts of the exercise:" +msgstr "연습문제의 다른 흥미로운 부분:" + +#: src/exercises/day-2/points-polygons.md:122 msgid "" -"Other interesting parts of the exercise:\n" -" \n" "* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their arguments.\n" "* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". Note that we do not discuss generics until Day 3." msgstr "" -"연습문제의 다른 흥미로운 부분:\n" -" \n" "* 테스트 코드를 보면 어떤 메서드들은 인자를 borrow하는 대신 `Copy` 트레잇을 사용하기도 합니다. 구조체가 `Copy` 트레잇을 상속(derive)하도록 하면 됩니다.\n" "* \"+\"를 사용하여 두 객체를 서로 더하려면 `Add` 트레잇을 구현해야 합니다. 이는 3일차에 다룰 내용입니다." @@ -6379,34 +6005,36 @@ msgid "" "```rust,editable\n" "fn double(x: i32) -> i32 {\n" " x + x\n" -"}" -msgstr "" - -#: src/control-flow/blocks.md:33 -msgid "" +"}\n" +"\n" "fn main() {\n" " println!(\"doubled: {}\", double(7));\n" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn double(x: i32) -> i32 {\n" +" x + x\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"doubled: {}\", double(7));\n" +"}\n" +"```" #: src/control-flow/blocks.md:38 msgid "However if the last expression ends with `;`, then the resulting value and type is `()`." msgstr "위의 `main` 함수는 마지막 표현식이 `;`로 끝나기 때문에 반환되는 값과 타입이 `()`입니다." -#: src/control-flow/blocks.md:42 +#: src/control-flow/blocks.md:43 msgid "" -"Key Points:\n" "* The point of this slide is to show that blocks have a type and value in Rust. \n" "* You can show how the value of the block changes by changing the last line in the block. For instance, adding/removing a semicolon or using a `return`.\n" -" \n" -"" +" " msgstr "" -"키 포인트:\n" "* 러스트에서는 블록이 타입과 값을 가진다는 점이 이 슬라이드의 핵심입니다.\n" -"* 블록 마지막 줄을 수정하면서 블록의 값이 어떻게 바뀌는지 보여주세요. 예를 들어, 세미콜론을\n" -" 넣거나 뺀다든지, 아니면 `return`을 사용해 보세요.\n" -"" +"* 블록 마지막 줄을 수정하면서 블록의 값이 어떻게 바뀌는지 보여주세요. 예를 들어, 세미콜론을 넣거나 뺀다든지, 아니면 `return`을 사용해 보세요.\n" +" " #: src/control-flow/if-expressions.md:1 msgid "# `if` expressions" @@ -6449,13 +6077,8 @@ msgid "" msgstr "" #: src/control-flow/if-expressions.md:31 -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.\n" -" \n" -"" -msgstr "" -"`if`는 표현식이고 타입을 가져야 하므로 분기 블록은 모두 같은 타입을 가져야 합니다. 두번째 예시의 `x / 2` 뒤에 `;`를 추가하여 어떻게 되는지 확인해 보시기 바랍니다.\n" -"" +msgid "Because `if` is an expression and must have a particular type, both of its branch blocks must have the same type. Consider showing what happens if you add `;` after `x / 2` in the second example." +msgstr "`if`는 표현식이고 타입을 가져야 하므로 분기 블록은 모두 같은 타입을 가져야 합니다. 두번째 예시의 `x / 2` 뒤에 `;`를 추가하여 어떻게 되는지 확인해 보시기 바랍니다." #: src/control-flow/if-let-expressions.md:1 msgid "# `if let` expressions" @@ -6539,17 +6162,24 @@ msgid "" "```rust,editable\n" "fn main() {\n" " let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();" -msgstr "" - -#: src/control-flow/while-let-expressions.md:11 -msgid "" +" let mut iter = v.into_iter();\n" +"\n" " while let Some(x) = iter.next() {\n" " println!(\"x: {x}\");\n" " }\n" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +"\n" +" while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" }\n" +"}\n" +"```" #: src/control-flow/while-let-expressions.md:17 msgid "" @@ -6562,13 +6192,11 @@ msgstr "`v.into_iter()`가 반환한 반복자는 `next()`가 호출될 때마 msgid "" "* Point out that the `while let` loop will keep going as long as the value matches the pattern.\n" "* You could rewrite the `while let` loop as an infinite loop with an if statement that breaks when there is no value to unwrap for `iter.next()`. The `while let` provides syntactic sugar for the above scenario.\n" -" \n" -"" +" " msgstr "" "* `while let`은 값이 패턴에 매치되는 동안 계속됩니다.\n" "* `while let` 루프 대신 무한 루프를 사용하고 `iter.next()`가 빈 값을 반환할 때 루프를 빠져나오도록 작성할수도 있습니다. `while let`은 그러한 경우를 위한 문법적 편의를 제공합니다.\n" -" \n" -"" +" " #: src/control-flow/for-expressions.md:1 msgid "# `for` expressions" @@ -6584,11 +6212,8 @@ msgstr "`for`표현식은 `while let` 표현식과 매우 유사합니다. `for` msgid "" "```rust,editable\n" "fn main() {\n" -" let v = vec![10, 20, 30];" -msgstr "" - -#: src/control-flow/for-expressions.md:10 -msgid "" +" let v = vec![10, 20, 30];\n" +"\n" " for x in v {\n" " println!(\"x: {x}\");\n" " }\n" @@ -6599,22 +6224,31 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +"\n" +" for x in v {\n" +" println!(\"x: {x}\");\n" +" }\n" +" \n" +" for i in (0..10).step_by(2) {\n" +" println!(\"i: {i}\");\n" +" }\n" +"}\n" +"```" #: src/control-flow/for-expressions.md:20 msgid "You can use `break` and `continue` here as usual." msgstr "다른 언어와 마찬가지로 `break` 와 `continue`를 사용할 수 있습니다." -#: src/control-flow/for-expressions.md:22 +#: src/control-flow/for-expressions.md:24 msgid "" -"
\n" -" \n" "* Index iteration is not a special syntax in Rust for just that case.\n" "* `(0..10)` is a range that implements an `Iterator` trait. \n" "* `step_by` is a method that returns another `Iterator` that skips every other element. \n" "* Modify the elements in the vector and explain the compiler errors. Change vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." msgstr "" -"
\n" -" \n" "* 러스트는 인덱스 반복을 위해 별도의 문법을 사용하지 않습니다. \n" "* `(0..10)`은 `Iterator` 트레잇을 구현하는 범위(range) 값입니다. \n" "* `step_by`는 반복자의 요소들을 건너뛰는 또다른 `Iterator`를 반환하는 메서드입니다.\n" @@ -6650,15 +6284,9 @@ msgid "" "```" msgstr "" -#: src/control-flow/loop-expressions.md:23 -msgid "" -"
\n" -" \n" -"* Break the `loop` with a value (e.g. `break 8`) and print it out." -msgstr "" -"
\n" -" \n" -"* `loop` 블록을 빠져나올 때 `break 8`처럼 값을 지정하고 그걸 출력해보세요." +#: src/control-flow/loop-expressions.md:25 +msgid "* Break the `loop` with a value (e.g. `break 8`) and print it out." +msgstr "* `loop` 블록을 빠져나올 때 `break 8`처럼 값을 지정하고 그걸 출력해보세요." #: src/control-flow/match-expressions.md:1 msgid "# `match` expressions" @@ -6710,15 +6338,13 @@ msgid "" "* Remove `.as_deref()` and explain the error.\n" " * `std::env::args().next()` returns an `Option`, but we cannot match against `String`.\n" " * `as_deref()` transforms an `Option` to `Option<&T::Target>`. In our case, this turns `Option` into `Option<&str>`.\n" -" * We can now use pattern matching to match against the `&str` inside `Option`.\n" -"
" +" * We can now use pattern matching to match against the `&str` inside `Option`." msgstr "" "* `match` 표현식을 변수에 할당하고 그 값을 출력해보세요.\n" "* `.as_deref()`를 지워보고, 이 때 나오는 에러를 설명해주세요.\n" " * `std::env::args().next()`는 `Option` 값을 반환하는데, `String`은 직접 매치할 수 없습니다.\n" " * `as_deref()`는 `Option`를 `Option<&T::Target>`으로 바꿔줍니다. 이 경우는 `Option`에서 `Option<&str>`로 바뀝니다.\n" -" * 이제는 패턴 매칭으로 `Option` 안의 `&str`을 매치할 수 있습니다.\n" -"
" +" * 이제는 패턴 매칭으로 `Option` 안의 `&str`을 매치할 수 있습니다." #: src/control-flow/break-continue.md:1 msgid "# `break` and `continue`" @@ -6791,43 +6417,39 @@ msgstr "일반적인 타입은 아래와 같습니다:" #: src/std.md:9 msgid "" "* [`Option` and `Result`](std/option-result.md) types: used for optional values\n" -" and [error handling](error-handling.md)." -msgstr "* [`Option`과 `Result`](std/option-result.md) : 어떤 값이 있거나 없거나 하는 경우, 그리고 [오류 처리](error-handling.md)에 사용합니다." - -#: src/std.md:12 -msgid "* [`String`](std/string.md): the default string type used for owned data." -msgstr "* [`String`](std/string.md): 기본적인 문자열 타입으로, 문자열 데이터를 소유하는 경우에 사용합니다." - -#: src/std.md:14 -msgid "* [`Vec`](std/vec.md): a standard extensible vector." -msgstr "* [`Vec`](std/vec.md): 가변 크기의 표준 벡터 타입입니다." - -#: src/std.md:16 -msgid "" +" and [error handling](error-handling.md).\n" +"\n" +"* [`String`](std/string.md): the default string type used for owned data.\n" +"\n" +"* [`Vec`](std/vec.md): a standard extensible vector.\n" +"\n" "* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" -" algorithm." -msgstr "* [`HashMap`](std/hashmap.md): 해시 알고리즘을 따로 지정할 수도 있는 해시맵 타입입니다." - -#: src/std.md:19 -msgid "* [`Box`](std/box.md): an owned pointer for heap-allocated data." -msgstr "* [`Box`](std/box.md): 힙 데이터에 대한 소유 포인터입니다." - -#: src/std.md:21 -msgid "* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated data." -msgstr "* [`Rc`](std/rc.md): 힙에 할당된 데이터에 대한 참조 카운팅 공유 포인터입니다." +" algorithm.\n" +"\n" +"* [`Box`](std/box.md): an owned pointer for heap-allocated data.\n" +"\n" +"* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated data." +msgstr "" +"* [`Option`과 `Result`](std/option-result.md) : 어떤 값이 있거나 없거나 하는 경우, 그리고 [오류 처리](error-handling.md)에 사용합니다.\n" +"\n" +"* [`String`](std/string.md): 기본적인 문자열 타입으로, 문자열 데이터를 소유하는 경우에 사용합니다.\n" +"\n" +"* [`Vec`](std/vec.md): 가변 크기의 표준 벡터 타입입니다.\n" +"\n" +"* [`HashMap`](std/hashmap.md): 해시 알고리즘을 따로 지정할 수도 있는 해시맵 타입입니다.\n" +"\n" +"* [`Box`](std/box.md): 힙 데이터에 대한 소유 포인터입니다.\n" +"\n" +"* [`Rc`](std/rc.md): 힙에 할당된 데이터에 대한 참조 카운팅 공유 포인터입니다." -#: src/std.md:23 +#: src/std.md:25 msgid "" -"
\n" -" \n" " * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. \n" " * `core` includes the most basic types and functions that don't depend on `libc`, allocator or\n" " even the presence of an operating system. \n" " * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`.\n" " * Embedded Rust applications often only use `core`, and sometimes `alloc`." msgstr "" -"
\n" -" \n" " * 사실, 러스트의 표준 라이브러리는 `core`, `alloc`, `std`와 같이 계층(layer)으로 나눠집니다.\n" " * `core`는 `libc`나 할당자(allocator), 심지어 OS에도 의존하지 않는 가장 기본적인 함수와 타입을 포함합니다.\n" " * `alloc`은 `Vec`, `Box`, `Arc`와 같이 전역 힙 할당이 필요한 타입을 포함합니다.\n" @@ -6847,11 +6469,8 @@ msgid "" "fn main() {\n" " let numbers = vec![10, 20, 30];\n" " let first: Option<&i8> = numbers.first();\n" -" println!(\"first: {first:?}\");" -msgstr "" - -#: src/std/option-result.md:11 -msgid "" +" println!(\"first: {first:?}\");\n" +"\n" " let idx: Result = numbers.binary_search(&10);\n" " println!(\"idx: {idx:?}\");\n" "}\n" @@ -6888,19 +6507,13 @@ msgid "" "fn main() {\n" " let mut s1 = String::new();\n" " s1.push_str(\"Hello\");\n" -" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());" -msgstr "" - -#: src/std/string.md:11 -msgid "" +" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());\n" +"\n" " let mut s2 = String::with_capacity(s1.len() + 1);\n" " s2.push_str(&s1);\n" " s2.push('!');\n" -" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());" -msgstr "" - -#: src/std/string.md:16 -msgid "" +" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());\n" +"\n" " let s3 = String::from(\"🇨🇭\");\n" " println!(\"s3: len = {}, number of chars = {}\", s3.len(),\n" " s3.chars().count());\n" @@ -6914,15 +6527,9 @@ msgid "" "`str` methods on a `String`." msgstr "`String`은 [`Deref`][2]을 구현합니다. 이는 , `String` 값에 대해서도 `str`의 모든 메서드를 호출 할 수 있다는 의미 입니다." -#: src/std/string.md:25 -msgid "" -"[1]: https://doc.rust-lang.org/std/string/struct.String.html\n" -"[2]: https://doc.rust-lang.org/std/string/struct.String.html#deref-methods-str" -msgstr "" - #: src/std/string.md:30 msgid "" -"* `String::new` returns a new empty string, use `String::with capacity` when you know how much data you want to push to the string.\n" +"* `String::new` returns a new empty string, use `String::with_capacity` when you know how much data you want to push to the string.\n" "* `String::len` returns the size of the `String` in bytes (which can be different from its length in characters).\n" "* `String::chars` returns an iterator over the actual characters. Note that a `char` can be different from what a human will consider a \"character\" due to [grapheme clusters](https://docs.rs/unicode-segmentation/latest/unicode_segmentation/struct.Graphemes.html).\n" "* When people refer to strings they could either be talking about `&str` or `String`. \n" @@ -6956,32 +6563,20 @@ msgid "" "fn main() {\n" " let mut v1 = Vec::new();\n" " v1.push(42);\n" -" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());" -msgstr "" - -#: src/std/vec.md:11 -msgid "" +" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());\n" +"\n" " let mut v2 = Vec::with_capacity(v1.len() + 1);\n" " v2.extend(v1.iter());\n" " v2.push(9999);\n" -" println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());" -msgstr "" - -#: src/std/vec.md:16 -msgid "" +" println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());\n" +"\n" " // Canonical macro to initialize a vector with elements.\n" -" let mut v3 = vec![0, 0, 1, 2, 3, 4];" -msgstr "" - -#: src/std/vec.md:19 -msgid "" +" let mut v3 = vec![0, 0, 1, 2, 3, 4];\n" +"\n" " // Retain only the even elements.\n" " v3.retain(|x| x % 2 == 0);\n" -" println!(\"{v3:?}\");" -msgstr "" - -#: src/std/vec.md:23 -msgid "" +" println!(\"{v3:?}\");\n" +"\n" " // Remove consecutive duplicates.\n" " v3.dedup();\n" " println!(\"{v3:?}\");\n" @@ -6995,12 +6590,6 @@ msgid "" "methods on a `Vec`." msgstr "`Vec`은 [`Deref`][2]를 구현합니다. 이는 `Vec`에서 슬라이스 메서드를 호출 할 수 있다는 의미입니다." -#: src/std/vec.md:32 -msgid "" -"[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html\n" -"[2]: https://doc.rust-lang.org/std/vec/struct.Vec.html#deref-methods-[T]" -msgstr "" - #: src/std/vec.md:37 msgid "" "* `Vec` is a type of collection, along with `String` and `HashMap`. The data it contains is stored\n" @@ -7032,140 +6621,90 @@ msgstr "HashDoS 공격으로부터 보호되는 표준 해시 맵입니다:" #: src/std/hashmap.md:5 msgid "" "```rust,editable\n" -"use std::collections::HashMap;" -msgstr "" -"```rust,editable\n" -"use std::collections::HashMap;" - -#: src/std/hashmap.md:8 -msgid "" -"fn main() {\n" -" let mut page_counts = HashMap::new();\n" -" page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), 207);\n" -" page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" -" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);" -msgstr "" +"use std::collections::HashMap;\n" +"\n" "fn main() {\n" " let mut page_counts = HashMap::new();\n" " page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), 207);\n" " page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" -" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);" - -#: src/std/hashmap.md:14 -msgid "" -" if !page_counts.contains_key(\"Les Misérables\") {\n" -" println!(\"We know about {} books, but not Les Misérables.\",\n" -" page_counts.len());\n" -" }" -msgstr "" +" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);\n" +"\n" " if !page_counts.contains_key(\"Les Misérables\") {\n" " println!(\"We know about {} books, but not Les Misérables.\",\n" " page_counts.len());\n" -" }" - -#: src/std/hashmap.md:19 -msgid "" -" for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" -" match page_counts.get(book) {\n" -" Some(count) => println!(\"{book}: {count} pages\"),\n" -" None => println!(\"{book} is unknown.\")\n" -" }\n" -" }" -msgstr "" +" }\n" +"\n" " for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" " match page_counts.get(book) {\n" " Some(count) => println!(\"{book}: {count} pages\"),\n" " None => println!(\"{book} is unknown.\")\n" " }\n" -" }" - -#: src/std/hashmap.md:26 -msgid "" -" // Use the .entry() method to insert a value if nothing is found.\n" -" for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" -" let page_count: &mut i32 = page_counts.entry(book.to_string()).or_insert(0);\n" -" *page_count += 1;\n" -" }" -msgstr "" +" }\n" +"\n" " // Use the .entry() method to insert a value if nothing is found.\n" " for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" " let page_count: &mut i32 = page_counts.entry(book.to_string()).or_insert(0);\n" " *page_count += 1;\n" -" }" - -#: src/std/hashmap.md:32 -msgid "" +" }\n" +"\n" " println!(\"{page_counts:#?}\");\n" "}\n" "```" msgstr "" -" println!(\"{page_counts:#?}\");\n" -"}\n" -"```" #: src/std/hashmap.md:38 msgid "" "* `HashMap` is not defined in the prelude and needs to be brought into scope.\n" -"* Try the following lines of code. The first line will see if a book is in the hashmap and if not return an alternative value. The second line will insert the alternative value in the hashmap if the book is not found." -msgstr "" -"* `HashMap`은 prelude에 정의되어 있지 않기 때문에 명시적으로 추가해줘야 합니다.\n" -"* 아래 코드를 테스트해보세요. 첫 문장에서는 해시맵에 책이 있는지 검사하여, 없으면 디폴트 값을 반환합니다. 두번 째 문장에서는 해시맵에 해당 책이 없는 경우, 지정한 값을 해시맵에 추가한 뒤 그 값을 반환합니다." - -#: src/std/hashmap.md:41 -msgid "" -" ```rust,ignore\n" -" let pc1 = page_counts\n" -" .get(\"Harry Potter and the Sorcerer's Stone \")\n" -" .unwrap_or(&336);\n" -" let pc2 = page_counts\n" -" .entry(\"The Hunger Games\".to_string())\n" -" .or_insert(374);\n" -" ```\n" +"* Try the following lines of code. The first line will see if a book is in the hashmap and if not return an alternative value. The second line will insert the alternative value in the hashmap if the book is not found.\n" +"\n" +" ```rust,ignore\n" +" let pc1 = page_counts\n" +" .get(\"Harry Potter and the Sorcerer's Stone \")\n" +" .unwrap_or(&336);\n" +" let pc2 = page_counts\n" +" .entry(\"The Hunger Games\".to_string())\n" +" .or_insert(374);\n" +" ```\n" "* Unlike `vec!`, there is unfortunately no standard `hashmap!` macro.\n" -" * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], which allows us to easily initialize a hash map from a literal array:" -msgstr "" -" ```rust,ignore\n" -" let pc1 = page_counts\n" -" .get(\"Harry Potter and the Sorcerer's Stone \")\n" -" .unwrap_or(&336);\n" -" let pc2 = page_counts\n" -" .entry(\"The Hunger Games\".to_string())\n" -" .or_insert(374);\n" -" ```\n" -"* 안타깝지만 `hashmap!`같은 매크로가 없습니다.\n" -" * 러스트 1.56부터는 `HashMap`이 [`From<[(K, V); N]>`][1]을 구현하기 때문에 배열 리터럴을 이용하여 쉽게 해시맵을 초기화할 수 있습니다:" - -#: src/std/hashmap.md:52 -msgid "" -" ```rust,ignore\n" -" let page_counts = HashMap::from([\n" -" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" -" (\"The Hunger Games\".to_string(), 374),\n" -" ]);\n" -" ```" -msgstr "" -" ```rust,ignore\n" -" let page_counts = HashMap::from([\n" -" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" -" (\"The Hunger Games\".to_string(), 374),\n" -" ]);\n" -" ```" - -#: src/std/hashmap.md:59 -msgid "" +" * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], which allows us to easily initialize a hash map from a literal array:\n" +"\n" +" ```rust,ignore\n" +" let page_counts = HashMap::from([\n" +" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" +" (\"The Hunger Games\".to_string(), 374),\n" +" ]);\n" +" ```\n" +"\n" " * Alternatively HashMap can be built from any `Iterator` which yields key-value tuples.\n" "* We are showing `HashMap`, and avoid using `&str` as key to make examples easier. Using references in collections can, of course, be done,\n" " but it can lead into complications with the borrow checker.\n" " * Try removing `to_string()` from the example above and see if it still compiles. Where do you think we might run into issues?" msgstr "" +"* `HashMap`은 prelude에 정의되어 있지 않기 때문에 명시적으로 추가해줘야 합니다.\n" +"* 아래 코드를 테스트해보세요. 첫 문장에서는 해시맵에 책이 있는지 검사하여, 없으면 디폴트 값을 반환합니다. 두번 째 문장에서는 해시맵에 해당 책이 없는 경우, 지정한 값을 해시맵에 추가한 뒤 그 값을 반환합니다.\n" +"\n" +" ```rust,ignore\n" +" let pc1 = page_counts\n" +" .get(\"Harry Potter and the Sorcerer's Stone \")\n" +" .unwrap_or(&336);\n" +" let pc2 = page_counts\n" +" .entry(\"The Hunger Games\".to_string())\n" +" .or_insert(374);\n" +" ```\n" +"* 안타깝지만 `hashmap!`같은 매크로가 없습니다.\n" +" * 러스트 1.56부터는 `HashMap`이 [`From<[(K, V); N]>`][1]을 구현하기 때문에 배열 리터럴을 이용하여 쉽게 해시맵을 초기화할 수 있습니다:\n" +"\n" +" ```rust,ignore\n" +" let page_counts = HashMap::from([\n" +" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" +" (\"The Hunger Games\".to_string(), 374),\n" +" ]);\n" +" ```\n" +"\n" " * 키-값 쌍에 대한 `Iterator`로 해시맵을 만들 수도 있습니다.\n" "* 예제 코드에서는 편의상 해시맵의 키로 `&str`를 사용하지 않았습니다. 물론 컬렉션에 참조를 사용할 수도 있습니다. 다만 참조를 사용하게 되면 빌림 검사기 때문에 복잡해 질 수 있습니다.\n" " * 예제 코드에서 `to_string()`을 없애도 컴파일에 문제가 없는지 확인해보세요. 어떤 문제에 부딪힐까요?" -#: src/std/hashmap.md:64 -msgid "[1]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#impl-From%3C%5B(K%2C%20V)%3B%20N%5D%3E-for-HashMap%3CK%2C%20V%2C%20RandomState%3E" -msgstr "[1]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#impl-From%3C%5B(K%2C%20V)%3B%20N%5D%3E-for-HashMap%3CK%2C%20V%2C%20RandomState%3E" - #: src/std/box.md:1 msgid "# `Box`" msgstr "# `Box`" @@ -7224,29 +6763,19 @@ msgid "" "from `T` directly on a `Box`][2]." msgstr "`Box`은 [`Deref`][2]를 구현합니다. 이는 [`Box`에서 `T` 메서드를 직접 호출][2] 할 수 있다는 의미입니다." -#: src/std/box.md:29 -msgid "" -"[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" -"[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion" -msgstr "" -"[1]: https://doc.rust-lang.org/std/boxed/struct.Box.html\n" -"[2]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion" - #: src/std/box.md:34 msgid "" "* `Box` is like `std::unique_ptr` in C++, except that it's guaranteed to be not null. \n" "* In the above example, you can even leave out the `*` in the `println!` statement thanks to `Deref`. \n" "* A `Box` can be useful when you:\n" " * have a type whose size that can't be known at compile time, but the Rust compiler wants to know an exact size.\n" -" * want to transfer ownership of a large amount of data. To avoid copying large amounts of data on the stack, instead store the data on the heap in a `Box` so only the pointer is moved.\n" -"
" +" * want to transfer ownership of a large amount of data. To avoid copying large amounts of data on the stack, instead store the data on the heap in a `Box` so only the pointer is moved." msgstr "" "* `Box`는 C++의 `std::unique_ptr`과 비슷합니다. 차이라면 `Box`는 널이 아님을 보장한다는 점입니다.\n" "* `Deref` 덕분에 위 예제의 `println!`문에 사용된 `*`를 빼도 문제가 없습니다.\n" "* `Box`는 아래의 경우에 유용합니다:\n" " * 타입 크기를 컴파일 시점에 알 수 없는 경우.\n" -" * 아주 큰 데이터의 소유권을 전달하고 싶은 경우. 스택에 있는 큰 데이터를 복사하는 대신 `Box`를 이용하여 데이터는 힙에 저장하고 포인터만 이동하면 됩니다.\n" -"
" +" * 아주 큰 데이터의 소유권을 전달하고 싶은 경우. 스택에 있는 큰 데이터를 복사하는 대신 `Box`를 이용하여 데이터는 힙에 저장하고 포인터만 이동하면 됩니다." #: src/std/box-recursive.md:1 msgid "# Box with Recursive Data Structures" @@ -7263,11 +6792,8 @@ msgid "" "enum List {\n" " Cons(T, Box>),\n" " Nil,\n" -"}" -msgstr "" - -#: src/std/box-recursive.md:12 src/std/box-niche.md:10 -msgid "" +"}\n" +"\n" "fn main() {\n" " let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));\n" " println!(\"{list:?}\");\n" @@ -7306,24 +6832,19 @@ msgstr "" #: src/std/box-recursive.md:33 msgid "" "* If the `Box` was not used here and we attempted to embed a `List` directly into the `List`,\n" -"the compiler would not compute a fixed size of the struct in memory, it would look infinite." -msgstr "* 만일 `Box`를 사용하지 않고 `List`에 직접 `List`를 포함하려고 시도한다면, 컴파일러는 구조체의 고정 크기를 계산할 수 없습니다. 컴파일러가 보기에 무한대의 크기로 보일 것입니다." - -#: src/std/box-recursive.md:36 -msgid "" +"the compiler would not compute a fixed size of the struct in memory, it would look infinite.\n" +"\n" "* `Box` solves this problem as it has the same size as a regular pointer and just points at the next\n" -"element of the `List` in the heap." -msgstr "* `Box`는 일반 포인터와 크기가 같기 때문에 크기를 계산하는 데 문제가 없습니다. 다만 힙에 위치한 `List`의 다음 요소를 가리킬 뿐입니다." - -#: src/std/box-recursive.md:39 -msgid "" +"element of the `List` in the heap.\n" +"\n" "* Remove the `Box` in the List definition and show the compiler error. \"Recursive with indirection\" is a hint you might want to use a Box or reference of some kind, instead of storing a value directly. \n" -" \n" -"
" +" " msgstr "" -"* `List` 정의에서 `Box`를 제거하면 어떤 컴파일러 에러가 나오는지 같이 살펴보세요. “Recursive with indirection”라는 메시지를 보면, 값을 직접 저장하는 대신 `Box`나 비슷한 다른 종류의 참조 타입이 필요하다는 힌트를 얻을 수 있습니다.\n" -" \n" -"
" +"* 만일 `Box`를 사용하지 않고 `List`에 직접 `List`를 포함하려고 시도한다면, 컴파일러는 구조체의 고정 크기를 계산할 수 없습니다. 컴파일러가 보기에 무한대의 크기로 보일 것입니다.\n" +"\n" +"* `Box`는 일반 포인터와 크기가 같기 때문에 크기를 계산하는 데 문제가 없습니다. 다만 힙에 위치한 `List`의 다음 요소를 가리킬 뿐입니다.\n" +"\n" +"* `List` 정의에서 `Box`를 제거하면 어떤 컴파일러 에러가 나오는지 같이 살펴보세요. “Recursive with indirection”라는 메시지를 보면, 값을 직접 저장하는 대신 `Box`나 비슷한 다른 종류의 참조 타입이 필요하다는 힌트를 얻을 수 있습니다." #: src/std/box-niche.md:1 msgid "# Niche Optimization" @@ -7376,15 +6897,28 @@ msgstr "[`Rc`][1]는 참조 카운팅 공유 포인터입니다. 여러 위치 #: src/std/rc.md:6 msgid "" "```rust,editable\n" -"use std::rc::Rc;" -msgstr "" - -#: src/std/rc.md:9 -msgid "" +"use std::rc::Rc;\n" +"\n" "fn main() {\n" " let mut a = Rc::new(10);\n" -" let mut b = a.clone();" +" let mut b = a.clone();\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" msgstr "" +"```rust,editable\n" +"use std::rc::Rc;\n" +"\n" +"fn main() {\n" +" let mut a = Rc::new(10);\n" +" let mut b = a.clone();\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" #: src/std/rc.md:18 msgid "" @@ -7398,18 +6932,6 @@ msgstr "" "* 멀티스레드인 경우 [`Arc`][3]를 참조하시기 바랍니다.\n" "* drop 가능한 순환 구조를 만들기 위해 공유 포인터를 [`Weak`][4] 포인터로 **다운그레이드**할 수도 있습니다." -#: src/std/rc.md:24 -msgid "" -"[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" -"[2]: https://doc.rust-lang.org/std/cell/index.html\n" -"[3]: ../concurrency/shared_state/arc.md\n" -"[4]: https://doc.rust-lang.org/std/rc/struct.Weak.html" -msgstr "" -"[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" -"[2]: https://doc.rust-lang.org/std/cell/index.html\n" -"[3]: ../concurrency/shared_state/arc.md\n" -"[4]: https://doc.rust-lang.org/std/rc/struct.Weak.html" - #: src/std/rc.md:31 msgid "" "* `Rc`'s Count ensures that its contained value is valid for as long as there are references.\n" @@ -7434,24 +6956,15 @@ msgstr "" msgid "" "```rust,editable\n" "use std::rc::{Rc, Weak};\n" -"use std::cell::RefCell;" -msgstr "" -"```rust,editable\n" -"use std::rc::{Rc, Weak};\n" -"use std::cell::RefCell;" - -#: src/std/rc.md:45 -msgid "" +"use std::cell::RefCell;\n" +"\n" "#[derive(Debug)]\n" "struct Node {\n" " value: i64,\n" " parent: Option>>,\n" " children: Vec>>,\n" -"}" -msgstr "" - -#: src/std/rc.md:52 -msgid "" +"}\n" +"\n" "fn main() {\n" " let mut root = Rc::new(RefCell::new(Node {\n" " value: 42,\n" @@ -7463,11 +6976,8 @@ msgid "" " children: vec![],\n" " parent: Some(Rc::downgrade(&root))\n" " }));\n" -" root.borrow_mut().children.push(child);" -msgstr "" - -#: src/std/rc.md:65 -msgid "" +" root.borrow_mut().children.push(child);\n" +"\n" " println!(\"graph: {root:#?}\");\n" "}\n" "```" @@ -7492,20 +7002,14 @@ msgid "" " pub fn do_something() {\n" " println!(\"In the foo module\");\n" " }\n" -"}" -msgstr "" - -#: src/modules.md:14 -msgid "" +"}\n" +"\n" "mod bar {\n" " pub fn do_something() {\n" " println!(\"In the bar module\");\n" " }\n" -"}" -msgstr "" - -#: src/modules.md:20 -msgid "" +"}\n" +"\n" "fn main() {\n" " foo::do_something();\n" " bar::do_something();\n" @@ -7529,7 +7033,7 @@ msgstr "# 가시성" #: src/modules/visibility.md:3 msgid "Modules are a privacy boundary:" -msgstr "모듈의 타입이나 함수는 기본적으로 비깥에 노출되지 않습니다:" +msgstr "모듈의 타입이나 함수는 기본적으로 바깥에 노출되지 않습니다:" #: src/modules/visibility.md:5 msgid "" @@ -7548,63 +7052,29 @@ msgid "" "mod outer {\n" " fn private() {\n" " println!(\"outer::private\");\n" -" }" -msgstr "" -"```rust,editable\n" -"mod outer {\n" -" fn private() {\n" -" println!(\"outer::private\");\n" -" }" - -#: src/modules/visibility.md:16 -msgid "" -" pub fn public() {\n" -" println!(\"outer::public\");\n" -" }" -msgstr "" +" }\n" +"\n" " pub fn public() {\n" " println!(\"outer::public\");\n" -" }" - -#: src/modules/visibility.md:20 -msgid "" -" mod inner {\n" -" fn private() {\n" -" println!(\"outer::inner::private\");\n" -" }" -msgstr "" +" }\n" +"\n" " mod inner {\n" " fn private() {\n" " println!(\"outer::inner::private\");\n" -" }" - -#: src/modules/visibility.md:25 -msgid "" -" pub fn public() {\n" -" println!(\"outer::inner::public\");\n" -" super::private();\n" " }\n" -" }\n" -"}" -msgstr "" +"\n" " pub fn public() {\n" " println!(\"outer::inner::public\");\n" " super::private();\n" " }\n" " }\n" -"}" - -#: src/modules/visibility.md:32 -msgid "" -"fn main() {\n" -" outer::public();\n" "}\n" -"```" -msgstr "" +"\n" "fn main() {\n" " outer::public();\n" "}\n" "```" +msgstr "" #: src/modules/visibility.md:39 msgid "* Use the `pub` keyword to make modules public." @@ -7638,18 +7108,16 @@ msgstr "경로는 아래와 같이 구분합니다:" msgid "" "1. As a relative path:\n" " * `foo` or `self::foo` refers to `foo` in the current module,\n" -" * `super::foo` refers to `foo` in the parent module." -msgstr "" -"1. 상대 경로\n" -" * `foo` 또는 `self::foo`는 현재 모듈 내부의 `foo`를 가리킵니다.\n" -" * `super::foo`는 부모 모듈의 `foo`를 가리킵니다." - -#: src/modules/paths.md:9 -msgid "" +" * `super::foo` refers to `foo` in the parent module.\n" +"\n" "2. As an absolute path:\n" " * `crate::foo` refers to `foo` in the root of the current crate,\n" " * `bar::foo` refers to `foo` in the `bar` crate." msgstr "" +"1. 상대 경로\n" +" * `foo` 또는 `self::foo`는 현재 모듈 내부의 `foo`를 가리킵니다.\n" +" * `super::foo`는 부모 모듈의 `foo`를 가리킵니다.\n" +"\n" "2. 절대 경로\n" " * `crate::foo`는 현재 크레이트 루트의 `foo`를 가리킵니다.\n" " * `bar::foo`는 `bar`크레이트의 `foo`를 가리킵니다." @@ -7704,60 +7172,54 @@ msgstr "" #: src/modules/filesystem.md:26 msgid "" "* The change from `module/mod.rs` to `module.rs` doesn't preclude the use of submodules in Rust 2018.\n" -" (It was mandatory in Rust 2015.)" -msgstr "* `module/mod.rs`를 `module.rs`로 바꾼다 하더라도 Rust 2018에서는 하위 모듈을 사용할 수 있습니다. (Rust 2015에서는 하위 모듈이 있는 모듈은 `module/mod.rs` 형태여야 했습니다.)" - -#: src/modules/filesystem.md:29 -msgid " The following is valid:" -msgstr " 아래처럼 구성하는데 아무런 문제가 없습니다:" - -#: src/modules/filesystem.md:31 -msgid "" +" (It was mandatory in Rust 2015.)\n" +"\n" +" The following is valid:\n" +"\n" " ```ignore\n" " src/\n" " ├── main.rs\n" " ├── top_module.rs\n" " └── top_module/\n" " └── sub_module.rs\n" -" ```" +" ```\n" +"\n" +"* The main reason for the change is to prevent many files named `mod.rs`, which can be hard\n" +" to distinguish in IDEs.\n" +"\n" +"* Rust will look for modules in `modulename/mod.rs` and `modulename.rs`, but this can be changed\n" +" with a compiler directive:\n" +"\n" +" ```rust,ignore\n" +" #[path = \"some/path.rs\"]\n" +" mod some_module { }\n" +" ```\n" +"\n" +" This is useful, for example, if you would like to place tests for a module in a file named\n" +" `some_module_test.rs`, similar to the convention in Go." msgstr "" +"* `module/mod.rs`를 `module.rs`로 바꾼다 하더라도 Rust 2018에서는 하위 모듈을 사용할 수 있습니다. (Rust 2015에서는 하위 모듈이 있는 모듈은 `module/mod.rs` 형태여야 했습니다.)\n" +"\n" +" 아래처럼 구성하는데 아무런 문제가 없습니다:\n" +"\n" " ```ignore\n" " src/\n" " ├── main.rs\n" " ├── top_module.rs\n" " └── top_module/\n" " └── sub_module.rs\n" -" ```" - -#: src/modules/filesystem.md:39 -msgid "" -"* The main reason for the change is to prevent many files named `mod.rs`, which can be hard\n" -" to distinguish in IDEs." -msgstr "* 이렇게 변경된 주된 이유는 모두 똑같은 이름의 `mod.rs` 파일이 잔뜩 생기는 것을 방지하기 위해서 입니다. IDE에서는 이들을 구분하기가 까다로웠습니다." - -#: src/modules/filesystem.md:42 -msgid "" -"* Rust will look for modules in `modulename/mod.rs` and `modulename.rs`, but this can be changed\n" -" with a compiler directive:" -msgstr "* 러스트는 모듈을 찾을 때 `modulename/mod.rs`와 `modulename.rs` 파일을 검사하는데, 컴파일러 디렉티브로 이를 변경할 수 있습니다." - -#: src/modules/filesystem.md:45 -msgid "" -" ```rust,ignore\n" -" #[path = \"some/path.rs\"]\n" -" mod some_module { }\n" -" ```" -msgstr "" +" ```\n" +"\n" +"* 이렇게 변경된 주된 이유는 모두 똑같은 이름의 `mod.rs` 파일이 잔뜩 생기는 것을 방지하기 위해서 입니다. IDE에서는 이들을 구분하기가 까다로웠습니다.\n" +"\n" +"* 러스트는 모듈을 찾을 때 `modulename/mod.rs`와 `modulename.rs` 파일을 검사하는데, 컴파일러 디렉티브로 이를 변경할 수 있습니다.\n" +"\n" " ```rust,ignore\n" " #[path = \"some/path.rs\"]\n" " mod some_module { }\n" -" ```" - -#: src/modules/filesystem.md:50 -msgid "" -" This is useful, for example, if you would like to place tests for a module in a file named\n" -" `some_module_test.rs`, similar to the convention in Go." -msgstr " Go언어 에서처럼 어떤 모듈의 테스트를 `some_module_test.rs` 같은 파일에 두고 싶은 경우에 유용합니다." +" ```\n" +"\n" +" Go언어 에서처럼 어떤 모듈의 테스트를 `some_module_test.rs` 같은 파일에 두고 싶은 경우에 유용합니다." #: src/exercises/day-2/afternoon.md:1 msgid "# Day 2: Afternoon Exercises" @@ -7779,28 +7241,28 @@ msgid "" msgstr "[룬(Luhn) 알고리즘](https://ko.wikipedia.org/wiki/%EB%A3%AC_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98)은 신용카드 번호 검증에 사용되는 알고리즘 입니다. 이 알고리즘은 신용카드 번호를 `문자열`로 입력받고, 아래의 순서에 따라 신용카드 번호의 유효성을 확인합니다:" #: src/exercises/day-2/luhn.md:7 -msgid "* Ignore all spaces. Reject number with less than two digits." -msgstr "* 모든 공백을 무시합니다. 2자리 미만 숫자는 무시합니다." - -#: src/exercises/day-2/luhn.md:9 msgid "" +"* Ignore all spaces. Reject number with less than two digits.\n" +"\n" "* Moving from right to left, double every second digit: for the number `1234`,\n" -" we double `3` and `1`." -msgstr "* 오른쪽에서 왼쪽으로 이동하며 2번째 자리마다 숫자를 2배 증가시킵니다. 예를 들어 `1234`에서 `3`과 `1`에 각각 2를 곱합니다." - -#: src/exercises/day-2/luhn.md:12 -msgid "" +" we double `3` and `1`.\n" +"\n" "* After doubling a digit, sum the digits. So doubling `7` becomes `14` which\n" -" becomes `5`." -msgstr "* 두배로 만든 숫자가 2자리라면 각 자리 숫자를 더합니다. 예를 들어, `7`은 두배로 만들면 `14`이므로 `5`가 됩니다." - -#: src/exercises/day-2/luhn.md:15 -msgid "* Sum all the undoubled and doubled digits." -msgstr "* 모든 자리의 숫자를 더합니다." - -#: src/exercises/day-2/luhn.md:17 -msgid "* The credit card number is valid if the sum ends with `0`." -msgstr "* 합계의 끝자리가 `0`인 경우 유효한 신용카드 번호입니다." +" becomes `5`.\n" +"\n" +"* Sum all the undoubled and doubled digits.\n" +"\n" +"* The credit card number is valid if the sum ends with `0`." +msgstr "" +"* 모든 공백을 무시합니다. 2자리 미만 숫자는 무시합니다.\n" +"\n" +"* 오른쪽에서 왼쪽으로 이동하며 2번째 자리마다 숫자를 2배 증가시킵니다. 예를 들어 `1234`에서 `3`과 `1`에 각각 2를 곱합니다.\n" +"\n" +"* 두배로 만든 숫자가 2자리라면 각 자리 숫자를 더합니다. 예를 들어, `7`은 두배로 만들면 `14`이므로 `5`가 됩니다.\n" +"\n" +"* 모든 자리의 숫자를 더합니다.\n" +"\n" +"* 합계의 끝자리가 `0`인 경우 유효한 신용카드 번호입니다." #: src/exercises/day-2/luhn.md:19 msgid "" @@ -7808,66 +7270,56 @@ msgid "" "function:" msgstr "아래 코드를 에 복사하고 함수를 구현해 보시기 바랍니다:" -#: src/exercises/day-2/luhn.md:27 +#: src/exercises/day-2/luhn.md:23 msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" "pub fn luhn(cc_number: &str) -> bool {\n" " unimplemented!()\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:31 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_non_digit_cc_number() {\n" " assert!(!luhn(\"foo\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:36 src/exercises/day-2/solutions-afternoon.md:64 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_empty_cc_number() {\n" " assert!(!luhn(\"\"));\n" " assert!(!luhn(\" \"));\n" " assert!(!luhn(\" \"));\n" " assert!(!luhn(\" \"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:44 src/exercises/day-2/solutions-afternoon.md:72 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_single_digit_cc_number() {\n" " assert!(!luhn(\"0\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:49 src/exercises/day-2/solutions-afternoon.md:77 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_two_digit_cc_number() {\n" " assert!(luhn(\" 0 0 \"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:54 src/exercises/day-2/solutions-afternoon.md:82 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_valid_cc_number() {\n" " assert!(luhn(\"4263 9826 4026 9299\"));\n" " assert!(luhn(\"4539 3195 0343 6467\"));\n" " assert!(luhn(\"7992 7398 713\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/luhn.md:61 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_invalid_cc_number() {\n" " assert!(!luhn(\"4223 9826 4026 9299\"));\n" " assert!(!luhn(\"4539 3195 0343 6476\"));\n" " assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" msgstr "" #: src/exercises/day-2/strings-iterators.md:1 @@ -7888,34 +7340,27 @@ msgid "" "pass. Try avoiding allocating a `Vec` for your intermediate results:" msgstr "아래 코드를 에 복사하고 테스트를 통과해 보시기 바랍니다. 중간 결과값을 `Vec`에 할당하지 않도록 주의 하시기 바랍니다:" -#: src/exercises/day-2/strings-iterators.md:16 +#: src/exercises/day-2/strings-iterators.md:12 msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" "pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" " unimplemented!()\n" -"}" -msgstr "" - -#: src/exercises/day-2/strings-iterators.md:20 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_matches_without_wildcard() {\n" " assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" " assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" -msgstr "" - -#: src/exercises/day-2/strings-iterators.md:26 -#: src/exercises/day-2/solutions-afternoon.md:146 -msgid "" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));\n" +"\n" " assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" " assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" " assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/strings-iterators.md:31 -#: src/exercises/day-2/solutions-afternoon.md:151 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_matches_with_wildcard() {\n" " assert!(prefix_matches(\n" @@ -7929,11 +7374,8 @@ msgid "" " assert!(prefix_matches(\n" " \"/v1/publishers/*/books\",\n" " \"/v1/publishers/foo/books/book1\"\n" -" ));" -msgstr "" - -#: src/exercises/day-2/strings-iterators.md:46 -msgid "" +" ));\n" +"\n" " assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" " assert!(!prefix_matches(\n" " \"/v1/publishers/*/books\",\n" @@ -7954,28 +7396,27 @@ msgstr "오늘은 몇 가지 고급 주제를 다룹니다:" #: src/welcome-day-3.md:5 msgid "" "* Traits: deriving traits, default methods, and important standard library\n" -" traits." -msgstr "* 트레잇: 트레잇 상속(derive), 디폴트 메서드, 표준 라이브러에 있는 중요한 트레잇들." - -#: src/welcome-day-3.md:8 -msgid "" +" traits.\n" +"\n" "* Generics: generic data types, generic methods, monomorphization, and trait\n" -" objects." -msgstr "* 제네릭: 제네릭 데이터 타입, 제네릭 메서드, 단형화(monomorphization), 트레잇 객체." - -#: src/welcome-day-3.md:11 -msgid "* Error handling: panics, `Result`, and the try operator `?`." -msgstr "* 오류처리(에러 핸들링): 패닉, `Result`, `?` 연산자." - -#: src/welcome-day-3.md:13 -msgid "* Testing: unit tests, documentation tests, and integration tests." -msgstr "* 테스트: 단위 테스트, 문서 테스트 및 통합 테스트." - -#: src/welcome-day-3.md:15 -msgid "" +" objects.\n" +"\n" +"* Error handling: panics, `Result`, and the try operator `?`.\n" +"\n" +"* Testing: unit tests, documentation tests, and integration tests.\n" +"\n" "* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" " functions." -msgstr "* 안전하지 않은 러스트: 원시(raw) 포인터, 정적 변수, 안전하지 않은 함수, 외부 함수." +msgstr "" +"* 트레잇: 트레잇 상속(derive), 디폴트 메서드, 표준 라이브러에 있는 중요한 트레잇들.\n" +"\n" +"* 제네릭: 제네릭 데이터 타입, 제네릭 메서드, 단형화(monomorphization), 트레잇 객체.\n" +"\n" +"* 오류처리(에러 핸들링): 패닉, `Result`, `?` 연산자.\n" +"\n" +"* 테스트: 단위 테스트, 문서 테스트 및 통합 테스트.\n" +"\n" +"* 안전하지 않은 러스트: 원시(raw) 포인터, 정적 변수, 안전하지 않은 함수, 외부 함수." #: src/traits.md:1 msgid "# Traits" @@ -7990,40 +7431,26 @@ msgid "" "```rust,editable\n" "trait Greet {\n" " fn say_hello(&self);\n" -"}" -msgstr "" - -#: src/traits.md:10 -msgid "" +"}\n" +"\n" "struct Dog {\n" " name: String,\n" -"}" -msgstr "" - -#: src/traits.md:14 -msgid "struct Cat; // No name, cats won't respond to it anyway." -msgstr "struct Cat; // 이름이 없습니다. 이름이 있더라도 고양이는 어차피 불러도 반응 없을 겁니다." - -#: src/traits.md:16 -msgid "" +"}\n" +"\n" +"struct Cat; // No name, cats won't respond to it anyway.\n" +"\n" "impl Greet for Dog {\n" " fn say_hello(&self) {\n" " println!(\"Wuf, my name is {}!\", self.name);\n" " }\n" -"}" -msgstr "" - -#: src/traits.md:22 -msgid "" +"}\n" +"\n" "impl Greet for Cat {\n" " fn say_hello(&self) {\n" " println!(\"Miau!\");\n" " }\n" -"}" -msgstr "" - -#: src/traits.md:28 -msgid "" +"}\n" +"\n" "fn main() {\n" " let pets: Vec> = vec![\n" " Box::new(Dog { name: String::from(\"Fido\") }),\n" @@ -8041,29 +7468,26 @@ msgid "" "* Traits may specify pre-implemented (default) methods and methods that users are required to implement themselves. Methods with default implementations can rely on required methods.\n" "* Types that implement a given trait may be of different sizes. This makes it impossible to have things like `Vec` in the example above.\n" "* `dyn Greet` is a way to tell the compiler about a dynamically sized type that implements `Greet`.\n" -"* In the example, `pets` holds Fat Pointers to objects that implement `Greet`. The Fat Pointer consists of two components, a pointer to the actual object and a pointer to the virtual method table for the `Greet` implementation of that particular object." +"* In the example, `pets` holds Fat Pointers to objects that implement `Greet`. The Fat Pointer consists of two components, a pointer to the actual object and a pointer to the virtual method table for the `Greet` implementation of that particular object.\n" +"* Compare these outputs in the above example:\n" +" ```rust,ignore\n" +" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::());\n" +" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n" +" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n" +" println!(\"{}\", std::mem::size_of::>());\n" +" ```" msgstr "" "* 트레잇은 사용자가 직접 구현해야 하는 메서드와 사전 구현된(디폴트) 메서드를 지정할 수 있습니다. 기본 구현된 메서드는 (다른)필수 메서드를 의존할 수 있습니다.\n" "* 여러 타입이 같은 트레잇을 구현하더라도 그 크기는 서로 다를 수 있습니다. 그래서 `Vec`같은 것은 불가능합니다. 왜냐하면 `Greet`트레잇을 구현하는 타입들 중 어떤 크기의 타입이 실제로 사용될 지, 컴파일 시에 알 방법이 없는 반면, `Vec<>`는 타입의 크기를 컴파일 시에 알고자 하기 때문입니다.\n" -"* `dyn Greet`는 `Greet`을 구현하는, 가변 크기의 타입을 의미합니다." - -#: src/traits.md:46 -msgid "" -"Compare these outputs in the above example:\n" -"```rust,ignore\n" -" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::());\n" -" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n" -" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n" -" println!(\"{}\", std::mem::size_of::>());\n" -"```" -msgstr "" -"위의 예제에 아래를 추가하여 출력을 비교해 보시기 바랍니다:\n" -"```rust,ignore\n" -" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::());\n" -" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n" -" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n" -" println!(\"{}\", std::mem::size_of::>());\n" -"```" +"* `dyn Greet`는 `Greet`을 구현하는, 가변 크기의 타입을 의미합니다.\n" +"* 예제에서 `pets`는 `Greet`을 구현하는 객체들의 Fat pointer를 담고 있습니다. Fat pointer는 실제 객체에 대한 포인터와 그 객체가 `Greet`을 구현하고 있는 가상 함수 테이블에 대한 포인터를 가집니다.\n" +"* 아래 코드의 결과와 비교해보세요:\n" +" ```rust,ignore\n" +" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::());\n" +" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n" +" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n" +" println!(\"{}\", std::mem::size_of::>());\n" +" ```" #: src/traits/deriving-traits.md:1 msgid "# Deriving Traits" @@ -8081,11 +7505,8 @@ msgid "" " name: String,\n" " strength: u8,\n" " hit_points: u8,\n" -"}" -msgstr "" - -#: src/traits/deriving-traits.md:13 -msgid "" +"}\n" +"\n" "fn main() {\n" " let p1 = Player::default();\n" " let p2 = p1.clone();\n" @@ -8111,26 +7532,17 @@ msgid "" " fn not_equal(&self, other: &Self) -> bool {\n" " !self.equal(other)\n" " }\n" -"}" -msgstr "" - -#: src/traits/default-methods.md:13 -msgid "" +"}\n" +"\n" "#[derive(Debug)]\n" -"struct Centimeter(i16);" -msgstr "" - -#: src/traits/default-methods.md:16 -msgid "" +"struct Centimeter(i16);\n" +"\n" "impl Equals for Centimeter {\n" " fn equal(&self, other: &Centimeter) -> bool {\n" " self.0 == other.0\n" " }\n" -"}" -msgstr "" - -#: src/traits/default-methods.md:22 -msgid "" +"}\n" +"\n" "fn main() {\n" " let a = Centimeter(10);\n" " let b = Centimeter(20);\n" @@ -8164,20 +7576,6 @@ msgstr "" "* [`Drop`][9] 트레잇은 소멸자 정의에 사용됩니다.\n" "* [`Default`][10] 트레잇은 어떤 타입의 기본값 인스턴스를 만들때 사용됩니다." -#: src/traits/important-traits.md:12 -msgid "" -"[1]: https://doc.rust-lang.org/std/iter/trait.Iterator.html\n" -"[2]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html\n" -"[3]: https://doc.rust-lang.org/std/convert/trait.From.html\n" -"[4]: https://doc.rust-lang.org/std/convert/trait.Into.html\n" -"[5]: https://doc.rust-lang.org/std/io/trait.Read.html\n" -"[6]: https://doc.rust-lang.org/std/io/trait.Write.html\n" -"[7]: https://doc.rust-lang.org/std/ops/trait.Add.html\n" -"[8]: https://doc.rust-lang.org/std/ops/trait.Mul.html\n" -"[9]: https://doc.rust-lang.org/std/ops/trait.Drop.html\n" -"[10]: https://doc.rust-lang.org/std/default/trait.Default.html" -msgstr "" - #: src/traits/iterator.md:1 msgid "# Iterators" msgstr "# Iterators" @@ -8192,28 +7590,19 @@ msgid "" "struct Fibonacci {\n" " curr: u32,\n" " next: u32,\n" -"}" -msgstr "" - -#: src/traits/iterator.md:11 -msgid "" +"}\n" +"\n" "impl Iterator for Fibonacci {\n" -" type Item = u32;" -msgstr "" - -#: src/traits/iterator.md:14 -msgid "" +" type Item = u32;\n" +"\n" " fn next(&mut self) -> Option {\n" " let new_next = self.curr + self.next;\n" " self.curr = self.next;\n" " self.next = new_next;\n" " Some(self.curr)\n" " }\n" -"}" -msgstr "" - -#: src/traits/iterator.md:22 -msgid "" +"}\n" +"\n" "fn main() {\n" " let fib = Fibonacci { curr: 0, next: 1 };\n" " for (i, n) in fib.enumerate().take(5) {\n" @@ -8231,17 +7620,11 @@ msgid "" " (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can find all the documentation\n" " about them. In Rust these functions should produce the code as efficient as equivalent imperative\n" " implementations.\n" -" \n" -"" +" " msgstr "" "* `IntoIterator`는 루프가 작동하도록 만드는 트레잇입니다. `Vec`와 같은 컬렉션 타입과 그에 대한 참조 타입(`&Vec`, `&[T]`)들 모두 이 트레잇을 구현합니다. Range 역시 이를 구현합니다.\n" "* `Iterator` 트레잇은 컬렉션에 대해 다양한 함수형 프로그래밍 연산 (`map`, `filter`, `reduce` 등)을 구현합니다. 이 연산들에 대한 자세한 설명은 `Iterator` 트레잇의 API 레퍼런스에서 찾을 수 있습니다. 러스트에서 이러한 함수형 연산들은 절차형으로 구현된 코드와 동일한 성능을 보여줍니다.\n" -" \n" -"" - -#: src/traits/iterator.md:41 -msgid "[1]: https://doc.rust-lang.org/std/iter/trait.Iterator.html" -msgstr "" +" " #: src/traits/from-iterator.md:1 msgid "# FromIterator" @@ -8272,27 +7655,17 @@ msgid "" " B: FromIterator,\n" " Self: Sized`" msgstr "" -"`Iterator`는 아래와 같이 구현됩니다.\n" -"```\n" -"fn collect(self) -> B\n" +"`Iterator`에는 다음 함수가 정의되어 있습니다:\n" +"`fn collect(self) -> B\n" "where\n" " B: FromIterator,\n" -" Self: Sized\n" -"```" +" Self: Sized`" #: src/traits/from-iterator.md:23 msgid "" "There are also implementations which let you do cool things like convert an\n" "`Iterator>` into a `Result, E>`." -msgstr "이는 또한 `Iterator>`을 `Result, E>`로 변경하는 멋진 작업도 구현합니다." - -#: src/traits/from-iterator.md:28 -msgid "" -"[1]: https://doc.rust-lang.org/std/iter/trait.FromIterator.html\n" -"[2]: https://doc.rust-lang.org/std/iter/trait.Iterator.html" -msgstr "" -"[1]: https://doc.rust-lang.org/std/iter/trait.FromIterator.html\n" -"[2]: https://doc.rust-lang.org/std/iter/trait.Iterator.html" +msgstr "`Iterator>`을 `Result, E>`로 변환할 수 있는 멋진 기능들도 구현되어 있습니다." #: src/traits/from-into.md:1 msgid "# `From` and `Into`" @@ -8332,30 +7705,16 @@ msgid "" "```" msgstr "" -#: src/traits/from-into.md:27 +#: src/traits/from-into.md:29 msgid "" -"
\n" -" \n" "* That's why it is common to only implement `From`, as your type will get `Into` implementation too.\n" "* When declaring a function argument input type like \"anything that can be converted into a `String`\", the rule is opposite, you should use `Into`.\n" " Your function will accept types that implement `From` and those that _only_ implement `Into`.\n" -" \n" -"
" +" " msgstr "" -"
\n" -" \n" "* 그렇기 때문에 사용자 정의 타입의 경우에도 `From` 만 구현하는 것이 일반적입니다.\n" "* \"`String`으로 변환할 수 있는 모든 것\"과 같은 함수의 인수 타입을 선언할 때에는 `Into`를 사용해야 함을 조심하세요. 그래야만, 함수는 `From`을 구현한 타입과 `Into` _만_ 구현한 타입 모두를 인자로 받을 수 있습니다.\n" -" \n" -"
" - -#: src/traits/from-into.md:35 -msgid "" -"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" -"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html" -msgstr "" -"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n" -"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html" +" " #: src/traits/read-write.md:1 msgid "# `Read` and `Write`" @@ -8368,26 +7727,17 @@ msgstr "[`Read`][1]와 [`BufRead`][2]를 사용하면 `u8` 타입의 데이터 #: src/traits/read-write.md:5 msgid "" "```rust,editable\n" -"use std::io::{BufRead, BufReader, Read, Result};" -msgstr "" - -#: src/traits/read-write.md:8 -msgid "" +"use std::io::{BufRead, BufReader, Read, Result};\n" +"\n" "fn count_lines(reader: R) -> usize {\n" " let buf_reader = BufReader::new(reader);\n" " buf_reader.lines().count()\n" -"}" -msgstr "" - -#: src/traits/read-write.md:13 -msgid "" +"}\n" +"\n" "fn main() -> Result<()> {\n" " let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" -" println!(\"lines in slice: {}\", count_lines(slice));" -msgstr "" - -#: src/traits/read-write.md:17 -msgid "" +" println!(\"lines in slice: {}\", count_lines(slice));\n" +"\n" " let file = std::fs::File::open(std::env::current_exe()?)?;\n" " println!(\"lines in file: {}\", count_lines(file));\n" " Ok(())\n" @@ -8402,19 +7752,13 @@ msgstr "이와 비슷하게, `Write`를 사옹하면 `u8` 타입의 데이터를 #: src/traits/read-write.md:25 msgid "" "```rust,editable\n" -"use std::io::{Result, Write};" -msgstr "" - -#: src/traits/read-write.md:28 -msgid "" +"use std::io::{Result, Write};\n" +"\n" "fn log(writer: &mut W, msg: &str) -> Result<()> {\n" " writer.write_all(msg.as_bytes())?;\n" " writer.write_all(\"\\n\".as_bytes())\n" -"}" -msgstr "" - -#: src/traits/read-write.md:33 -msgid "" +"}\n" +"\n" "fn main() -> Result<()> {\n" " let mut buffer = Vec::new();\n" " log(&mut buffer, \"Hello\")?;\n" @@ -8425,16 +7769,6 @@ msgid "" "```" msgstr "" -#: src/traits/read-write.md:42 -msgid "" -"[1]: https://doc.rust-lang.org/std/io/trait.Read.html\n" -"[2]: https://doc.rust-lang.org/std/io/trait.BufRead.html\n" -"[3]: https://doc.rust-lang.org/std/io/trait.Write.html" -msgstr "" -"[1]: https://doc.rust-lang.org/std/io/trait.Read.html\n" -"[2]: https://doc.rust-lang.org/std/io/trait.BufRead.html\n" -"[3]: https://doc.rust-lang.org/std/io/trait.Write.html" - #: src/traits/operators.md:1 msgid "# `Add`, `Mul`, ..." msgstr "# `Add`, `Mul`, ..." @@ -8447,25 +7781,16 @@ msgstr "연산자 오버로드는 `std::ops`에 있는 다양한 트레잇들을 msgid "" "```rust,editable\n" "#[derive(Debug, Copy, Clone)]\n" -"struct Point { x: i32, y: i32 }" -msgstr "" - -#: src/traits/operators.md:9 src/exercises/day-2/solutions-morning.md:46 -msgid "" +"struct Point { x: i32, y: i32 }\n" +"\n" "impl std::ops::Add for Point {\n" -" type Output = Self;" -msgstr "" - -#: src/traits/operators.md:12 -msgid "" +" type Output = Self;\n" +"\n" " fn add(self, other: Self) -> Self {\n" " Self {x: self.x + other.x, y: self.y + other.y}\n" " }\n" -"}" -msgstr "" - -#: src/traits/operators.md:17 -msgid "" +"}\n" +"\n" "fn main() {\n" " let p1 = Point { x: 10, y: 20 };\n" " let p2 = Point { x: 100, y: 200 };\n" @@ -8495,10 +7820,6 @@ msgstr "" "* 왜 `Output`이 연관된 타입인가요? 타입 파라메터로 만들 수 있을까요?\n" " * 답: 타입 파라메터를 호출하는 쪽에서 결정합니다. 반면 연관된 타입(`Output`같은) 은 트레잇을 구현하는 쪽에서 제어 가능합니다." -#: src/traits/operators.md:40 -msgid "[1]: https://doc.rust-lang.org/std/ops/index.html" -msgstr "" - #: src/traits/drop.md:1 msgid "# The `Drop` Trait" msgstr "# `Drop` 트레잇" @@ -8512,20 +7833,14 @@ msgid "" "```rust,editable\n" "struct Droppable {\n" " name: &'static str,\n" -"}" -msgstr "" - -#: src/traits/drop.md:10 -msgid "" +"}\n" +"\n" "impl Drop for Droppable {\n" " fn drop(&mut self) {\n" " println!(\"Dropping {}\", self.name);\n" " }\n" -"}" -msgstr "" - -#: src/traits/drop.md:16 -msgid "" +"}\n" +"\n" "fn main() {\n" " let a = Droppable { name: \"a\" };\n" " {\n" @@ -8555,10 +7870,6 @@ msgstr "" " * 짧은 대답: 만약 그렇게 된다면 `std::mem::drop`이 블록의 끝에서 호출되고, 다시 `Drop::drop`을 호출하게되 스택 오버플로가 발생합니다.\n" "* `drop(a)`를 `a.drop()`로 변경해 보시기 바랍니다." -#: src/traits/drop.md:44 -msgid "[1]: https://doc.rust-lang.org/std/ops/trait.Drop.html" -msgstr "" - #: src/traits/default.md:1 msgid "# The `Default` Trait" msgstr "# `Default` 트레잇" @@ -8575,71 +7886,33 @@ msgid "" " x: u32,\n" " y: String,\n" " z: Implemented,\n" -"}" -msgstr "" -"```rust,editable\n" -"#[derive(Debug, Default)]\n" -"struct Derived {\n" -" x: u32,\n" -" y: String,\n" -" z: Implemented,\n" -"}" - -#: src/traits/default.md:13 -msgid "" -"#[derive(Debug)]\n" -"struct Implemented(String);" -msgstr "" +"}\n" +"\n" "#[derive(Debug)]\n" -"struct Implemented(String);" - -#: src/traits/default.md:16 -msgid "" -"impl Default for Implemented {\n" -" fn default() -> Self {\n" -" Self(\"John Smith\".into())\n" -" }\n" -"}" -msgstr "" +"struct Implemented(String);\n" +"\n" "impl Default for Implemented {\n" " fn default() -> Self {\n" " Self(\"John Smith\".into())\n" " }\n" -"}" - -#: src/traits/default.md:22 -msgid "" -"fn main() {\n" -" let default_struct: Derived = Default::default();\n" -" println!(\"{default_struct:#?}\");" -msgstr "" +"}\n" +"\n" "fn main() {\n" " let default_struct: Derived = Default::default();\n" -" println!(\"{default_struct:#?}\");" - -#: src/traits/default.md:26 -msgid "" -" let almost_default_struct = Derived {\n" -" y: \"Y is set!\".into(),\n" -" ..Default::default()\n" -" };\n" -" println!(\"{almost_default_struct:#?}\");" -msgstr "" +" println!(\"{default_struct:#?}\");\n" +"\n" " let almost_default_struct = Derived {\n" " y: \"Y is set!\".into(),\n" " ..Default::default()\n" " };\n" -" println!(\"{almost_default_struct:#?}\");" - -#: src/traits/default.md:32 -msgid "" +" println!(\"{almost_default_struct:#?}\");\n" +"\n" " let nothing: Option = None;\n" " println!(\"{:#?}\", nothing.unwrap_or_default());\n" -"}" +"}\n" +"\n" +"```" msgstr "" -" let nothing: Option = None;\n" -" println!(\"{:#?}\", nothing.unwrap_or_default());\n" -"}" #: src/traits/default.md:40 msgid "" @@ -8657,10 +7930,6 @@ msgstr "" " * 구조체 부분 복사를 할때 `default`를 편리하게 사용할 수 있습니다.\n" " * 러스트 표준 라이브러리는 `Default` 트레잇을 구현한 타입을 위한 편의 메서드를 제공하기도 합니다." -#: src/traits/default.md:49 -msgid "[1]: https://doc.rust-lang.org/std/default/trait.Default.html" -msgstr "[1]: https://doc.rust-lang.org/std/default/trait.Default.html" - #: src/generics.md:1 msgid "# Generics" msgstr "# 제네릭" @@ -8686,11 +7955,8 @@ msgid "" "struct Point {\n" " x: T,\n" " y: T,\n" -"}" -msgstr "" - -#: src/generics/data-types.md:12 -msgid "" +"}\n" +"\n" "fn main() {\n" " let integer = Point { x: 5, y: 10 };\n" " let float = Point { x: 1.0, y: 4.0 };\n" @@ -8711,25 +7977,16 @@ msgstr "`impl` 블록에서도 제네릭 타입을 선언할 수 있습니다:" msgid "" "```rust,editable\n" "#[derive(Debug)]\n" -"struct Point(T, T);" -msgstr "" - -#: src/generics/methods.md:9 -msgid "" +"struct Point(T, T);\n" +"\n" "impl Point {\n" " fn x(&self) -> &T {\n" " &self.0 // + 10\n" -" }" -msgstr "" - -#: src/generics/methods.md:14 -msgid "" +" }\n" +"\n" " // fn set_x(&mut self, x: T)\n" -"}" -msgstr "" - -#: src/generics/methods.md:17 -msgid "" +"}\n" +"\n" "fn main() {\n" " let p = Point(5, 10);\n" " println!(\"p.x = {}\", p.x());\n" @@ -8770,32 +8027,21 @@ msgid "" "```rust,editable\n" "fn duplicate(a: T) -> (T, T) {\n" " (a.clone(), a.clone())\n" -"}" -msgstr "" - -#: src/generics/trait-bounds.md:13 -msgid "" +"}\n" +"\n" "// Syntactic sugar for:\n" "// fn add_42_millions>(x: T) -> i32 {\n" "fn add_42_millions(x: impl Into) -> i32 {\n" " x.into() + 42_000_000\n" -"}" -msgstr "" - -#: src/generics/trait-bounds.md:19 -msgid "// struct NotClonable;" -msgstr "" - -#: src/generics/trait-bounds.md:21 -msgid "" +"}\n" +"\n" +"// struct NotClonable;\n" +"\n" "fn main() {\n" " let foo = String::from(\"foo\");\n" " let pair = duplicate(foo);\n" -" println!(\"{pair:?}\");" -msgstr "" - -#: src/generics/trait-bounds.md:26 -msgid "" +" println!(\"{pair:?}\");\n" +"\n" " let many = add_42_millions(42_i8);\n" " println!(\"{many}\");\n" " let many_more = add_42_millions(10_000_000);\n" @@ -8805,9 +8051,11 @@ msgid "" msgstr "" #: src/generics/trait-bounds.md:35 +msgid "Show a `where` clause, students will encounter it when reading code." +msgstr "`where` 문법을 사용할 수도 있습니다. 수강생들도 코드를 읽다가 그 문법을 마주할 수 있습니다." + +#: src/generics/trait-bounds.md:37 msgid "" -"Show a `where` clause, students will encounter it when reading code.\n" -" \n" "```rust,ignore\n" "fn duplicate(a: T) -> (T, T)\n" "where\n" @@ -8817,7 +8065,6 @@ msgid "" "}\n" "```" msgstr "" -"`where` 문법을 사용할 수도 있습니다. 수강생들도 코드를 읽다가 그 문법을 마주할 수 있습니다.\n" "```rust,ignore\n" "fn duplicate(a: T) -> (T, T)\n" "where\n" @@ -8832,14 +8079,12 @@ msgid "" "* It declutters the function signature if you have many parameters.\n" "* It has additional features making it more powerful.\n" " * If someone asks, the extra feature is that the type on the left of \":\" can be arbitrary, like `Option`.\n" -" \n" -"" +" " msgstr "" "* 이를 이용하면 타입 파라메터가 많은 경우 함수 시그니처를 간결하게 정리하는 데 도움이 됩니다.\n" "* 좀 더 강력한 추가 기능도 제공합니다.\n" " * `:` 왼쪽에 임의의 타입(예를 들어 `Option`)을 사용할 수 있습니다.\n" -" \n" -"" +" " #: src/generics/impl-trait.md:1 msgid "# `impl Trait`" @@ -8851,22 +8096,15 @@ msgid "" "arguments and return values:" msgstr "트레잇 바운드와 유사하게 `impl Trait` 문법은 함수의 인자와 반환값에도 적용 가능합니다:" -#: src/generics/impl-trait.md:6 src/generics/trait-objects.md:5 -#: src/generics/trait-objects.md:28 +#: src/generics/impl-trait.md:6 msgid "" "```rust,editable\n" -"use std::fmt::Display;" -msgstr "" - -#: src/generics/impl-trait.md:9 -msgid "" +"use std::fmt::Display;\n" +"\n" "fn get_x(name: impl Display) -> impl Display {\n" " format!(\"Hello {name}\")\n" -"}" -msgstr "" - -#: src/generics/impl-trait.md:13 -msgid "" +"}\n" +"\n" "fn main() {\n" " let x = get_x(\"foo\");\n" " println!(\"{x}\");\n" @@ -8903,13 +8141,8 @@ msgid "" "`T: Display`, it would enforce the constraint that input `T` and return `T` type are the same type.\n" "It would not work for this particular function, as the type we expect as input is likely not\n" "what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two\n" -"independent generic parameters.\n" -" \n" -"" -msgstr "" -"이 예시는 `impl Display`가 두번 사용 되었다는 점에서 훌륭합니다. 여기서 중요한 것은 이 두 `impl Display`가 실제로 같은 타입일 필요가 없다는 것입니다. 만약 `T: Display`로 트레잇 경계를 정하고 입력 파라메터와 리턴 값의 타입을 모두 `T`로 했다면, 이는 입력과 리턴값이 같은 타입임을 강제합니다. 이렇게 했다면 위의 예제는 동작하지 않았을 것입니다. 왜냐하면, 입력 값의 타입이 `format!`이 리턴하는 타입과 같지 않을 가능성이 높기 때문입니다. 만약 `: Display` 문법을 사용하고 싶다면 독립적인 제네릭 매개변수가 두 개가 필요합니다.\n" -" \n" -"" +"independent generic parameters." +msgstr "이 예시는 `impl Display`가 두번 사용 되었다는 점에서 훌륭합니다. 여기서 중요한 것은 이 두 `impl Display`가 실제로 같은 타입일 필요가 없다는 것입니다. 만약 `T: Display`로 트레잇 경계를 정하고 입력 파라메터와 리턴 값의 타입을 모두 `T`로 했다면, 이는 입력과 리턴값이 같은 타입임을 강제합니다. 이렇게 했다면 위의 예제는 동작하지 않았을 것입니다. 왜냐하면, 입력 값의 타입이 `format!`이 리턴하는 타입과 같지 않을 가능성이 높기 때문입니다. 만약 `: Display` 문법을 사용하고 싶다면 독립적인 제네릭 매개변수가 두 개가 필요합니다." #: src/generics/closures.md:1 msgid "# Closures" @@ -8929,18 +8162,12 @@ msgid "" "fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" " println!(\"Calling function on {input}\");\n" " func(input)\n" -"}" -msgstr "" - -#: src/generics/closures.md:14 -msgid "" +"}\n" +"\n" "fn main() {\n" " let add_3 = |x| x + 3;\n" -" let mul_5 = |x| x * 5;" -msgstr "" - -#: src/generics/closures.md:18 -msgid "" +" let mul_5 = |x| x * 5;\n" +"\n" " println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" " println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" "}\n" @@ -9000,19 +8227,13 @@ msgid "" "enum Option_i32 {\n" " Some(i32),\n" " None,\n" -"}" -msgstr "" - -#: src/generics/monomorphization.md:20 -msgid "" +"}\n" +"\n" "enum Option_f64 {\n" " Some(f64),\n" " None,\n" -"}" -msgstr "" - -#: src/generics/monomorphization.md:25 -msgid "" +"}\n" +"\n" "fn main() {\n" " let integer = Option_i32::Some(5);\n" " let float = Option_f64::Some(5.0);\n" @@ -9034,15 +8255,15 @@ msgstr "# 트레잇 객체" msgid "We've seen how a function can take arguments which implement a trait:" msgstr "함수가 특정 트레잇을 구현하는 인자를 입력으로 받도록 하는 방법에 대해 설명했었습니다:" -#: src/generics/trait-objects.md:8 +#: src/generics/trait-objects.md:5 msgid "" +"```rust,editable\n" +"use std::fmt::Display;\n" +"\n" "fn print(x: T) {\n" " println!(\"Your value: {x}\");\n" -"}" -msgstr "" - -#: src/generics/trait-objects.md:12 -msgid "" +"}\n" +"\n" "fn main() {\n" " print(123);\n" " print(\"Hello\");\n" @@ -9067,8 +8288,11 @@ msgstr "" msgid "For this, we need _trait objects_:" msgstr "이를 위해서는 \"트레잇 객체\"가 필요합니다:" -#: src/generics/trait-objects.md:31 +#: src/generics/trait-objects.md:28 msgid "" +"```rust,editable\n" +"use std::fmt::Display;\n" +"\n" "fn main() {\n" " let xs: Vec> = vec![Box::new(123), Box::new(\"Hello\")];\n" " for x in xs {\n" @@ -9155,15 +8379,14 @@ msgid "" " } else {\n" " Box::new((n..0).rev())\n" " }\n" -"}" -msgstr "" - -#: src/generics/trait-objects.md:81 -msgid "" +"}\n" +"\n" "fn main() {\n" " println!(\"{:?}\", numbers(-5).collect::>());\n" " println!(\"{:?}\", numbers(5).collect::>());\n" -"}" +"}\n" +"\n" +"```" msgstr "" #: src/exercises/day-3/morning.md:1 @@ -9210,71 +8433,43 @@ msgid "" msgstr "아래 코드를 에 복사하고 누락된 `draw_into`메서드를 채워 넣어 `Widget` 트레잇을 완성해봅시다:" #: src/exercises/day-3/simple-gui.md:18 -#: src/exercises/day-3/safe-ffi-wrapper.md:25 msgid "" "```rust,should_panic\n" "// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_imports, unused_variables, dead_code)]" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:22 -msgid "" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" "pub trait Widget {\n" " /// Natural width of `self`.\n" -" fn width(&self) -> usize;" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:26 -#: src/exercises/day-3/solutions-morning.md:27 -msgid "" +" fn width(&self) -> usize;\n" +"\n" " /// Draw the widget into a buffer.\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:29 -#: src/exercises/day-3/solutions-morning.md:30 -msgid "" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" " /// Draw the widget on standard output.\n" " fn draw(&self) {\n" " let mut buffer = String::new();\n" " self.draw_into(&mut buffer);\n" " println!(\"{buffer}\");\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:37 -#: src/exercises/day-3/solutions-morning.md:38 -msgid "" +"}\n" +"\n" "pub struct Label {\n" " label: String,\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:41 -#: src/exercises/day-3/solutions-morning.md:42 -msgid "" +"}\n" +"\n" "impl Label {\n" " fn new(label: &str) -> Label {\n" " Label {\n" " label: label.to_owned(),\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:49 -#: src/exercises/day-3/solutions-morning.md:50 -msgid "" +"}\n" +"\n" "pub struct Button {\n" " label: Label,\n" " callback: Box,\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:54 -#: src/exercises/day-3/solutions-morning.md:55 -msgid "" +"}\n" +"\n" "impl Button {\n" " fn new(label: &str, callback: Box) -> Button {\n" " Button {\n" @@ -9282,74 +8477,57 @@ msgid "" " callback,\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:63 -#: src/exercises/day-3/solutions-morning.md:64 -msgid "" +"}\n" +"\n" "pub struct Window {\n" " title: String,\n" " widgets: Vec>,\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:68 -#: src/exercises/day-3/solutions-morning.md:69 -msgid "" +"}\n" +"\n" "impl Window {\n" " fn new(title: &str) -> Window {\n" " Window {\n" " title: title.to_owned(),\n" " widgets: Vec::new(),\n" " }\n" -" }" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:76 -#: src/exercises/day-3/solutions-morning.md:77 -msgid "" +" }\n" +"\n" " fn add_widget(&mut self, widget: Box) {\n" " self.widgets.push(widget);\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:82 -msgid "" +"}\n" +"\n" +"\n" "impl Widget for Label {\n" " fn width(&self) -> usize {\n" " unimplemented!()\n" -" }" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:87 src/exercises/day-3/simple-gui.md:97 -#: src/exercises/day-3/simple-gui.md:107 -msgid "" +" }\n" +"\n" " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" " unimplemented!()\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:92 -msgid "" -"impl Widget for Button {\n" +"}\n" +"\n" +"impl Widget for Button {\n" " fn width(&self) -> usize {\n" " unimplemented!()\n" -" }" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:102 -msgid "" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" "impl Widget for Window {\n" " fn width(&self) -> usize {\n" " unimplemented!()\n" -" }" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:112 -msgid "" +" }\n" +"\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" +" unimplemented!()\n" +" }\n" +"}\n" +"\n" "fn main() {\n" " let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" " window.add_widget(Box::new(Label::new(\"This is a small text GUI demo.\")));\n" @@ -9371,15 +8549,10 @@ msgid "" "```text\n" "========\n" "Rust GUI Demo 1.23\n" -"========" -msgstr "" - -#: src/exercises/day-3/simple-gui.md:130 -msgid "This is a small text GUI demo." -msgstr "" - -#: src/exercises/day-3/simple-gui.md:132 -msgid "" +"========\n" +"\n" +"This is a small text GUI demo.\n" +"\n" "| Click me! |\n" "```" msgstr "" @@ -9477,19 +8650,13 @@ msgstr "기본적으로, 패닉이 발생하면 스택 되감기를 합니다. #: src/error-handling/panic-unwind.md:5 msgid "" "```rust\n" -"use std::panic;" -msgstr "" - -#: src/error-handling/panic-unwind.md:8 -msgid "" +"use std::panic;\n" +"\n" "let result = panic::catch_unwind(|| {\n" " println!(\"hello!\");\n" "});\n" -"assert!(result.is_ok());" -msgstr "" - -#: src/error-handling/panic-unwind.md:13 -msgid "" +"assert!(result.is_ok());\n" +"\n" "let result = panic::catch_unwind(|| {\n" " panic!(\"oh no!\");\n" "});\n" @@ -9520,11 +8687,8 @@ msgstr "여러분은 이미 `Result` 열거형을 몇 번 봤습니다. 이 타 msgid "" "```rust\n" "use std::fs::File;\n" -"use std::io::Read;" -msgstr "" - -#: src/error-handling/result.md:10 -msgid "" +"use std::io::Read;\n" +"\n" "fn main() {\n" " let file = File::open(\"diary.txt\");\n" " match file {\n" @@ -9548,13 +8712,11 @@ msgid "" " `unwrap()` or `expect()` can be called, and this is a signal of the developer intent too. \n" " * `Result` documentation is a recommended read. Not during the course, but it is worth mentioning. \n" " It contains a lot of convenience methods and functions that help functional-style programming. \n" -" \n" -"" +" " msgstr "" " * `Option`와 마찬가지로, 성공한 경우의 값은 `Result` 내부에 있습니다. 그래서, 개발자는 명시적으로 이를 추출하여야 합니다. 이렇게 함으로써 값을 읽기 전에 오류 발생 여부를 반드시 체크하도록 유도하고 있습니다. 만일 오류가 절대 발생하지 않는 경우라면 `unwrap()`이나 `expect()`를 사용할 수 있으며, 이는 개발자의 의도(_역주_: 오류가 발생할 수 없음)을 명시적으로 나타내는 방법이기도 합니다.\n" " * 수업중엔 아니지만 `Result`의 API 레퍼런스를 읽는 것을 권장합니다. 함수형 프로그래밍 스타일에 도움이 되는 편리한 메서드와 함수를 많이 배울 수 있습니다.\n" -" \n" -"" +" " #: src/error-handling/try-operator.md:1 msgid "# Propagating Errors with `?`" @@ -9595,38 +8757,24 @@ msgstr "이제 우리 예제에 적용해 보겠습니다:" msgid "" "```rust,editable\n" "use std::fs;\n" -"use std::io::{self, Read};" -msgstr "" - -#: src/error-handling/try-operator.md:25 -msgid "" +"use std::io::{self, Read};\n" +"\n" "fn read_username(path: &str) -> Result {\n" -" let username_file_result = fs::File::open(path);" -msgstr "" - -#: src/error-handling/try-operator.md:28 -msgid "" +" 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" -" };" -msgstr "" - -#: src/error-handling/try-operator.md:33 -msgid " let mut username = String::new();" -msgstr "" - -#: src/error-handling/try-operator.md:35 -msgid "" +" };\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" " }\n" -"}" -msgstr "" - -#: src/error-handling/try-operator.md:41 -msgid "" +"}\n" +"\n" "fn main() {\n" " //fs::write(\"config.dat\", \"alice\").unwrap();\n" " let username = read_username(\"config.dat\");\n" @@ -9686,24 +8834,16 @@ msgid "" "use std::error::Error;\n" "use std::fmt::{self, Display, Formatter};\n" "use std::fs::{self, File};\n" -"use std::io::{self, Read};" -msgstr "" - -#: src/error-handling/converting-error-types-example.md:9 -msgid "" +"use std::io::{self, Read};\n" +"\n" "#[derive(Debug)]\n" "enum ReadUsernameError {\n" " IoError(io::Error),\n" " EmptyUsername(String),\n" -"}" -msgstr "" - -#: src/error-handling/converting-error-types-example.md:15 -msgid "impl Error for ReadUsernameError {}" -msgstr "" - -#: src/error-handling/converting-error-types-example.md:17 -msgid "" +"}\n" +"\n" +"impl Error for ReadUsernameError {}\n" +"\n" "impl Display for ReadUsernameError {\n" " fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" " match self {\n" @@ -9711,20 +8851,14 @@ msgid "" " Self::EmptyUsername(filename) => write!(f, \"Found no username in {}\", filename),\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/error-handling/converting-error-types-example.md:26 -msgid "" +"}\n" +"\n" "impl From for ReadUsernameError {\n" " fn from(err: io::Error) -> ReadUsernameError {\n" " ReadUsernameError::IoError(err)\n" " }\n" -"}" -msgstr "" - -#: src/error-handling/converting-error-types-example.md:32 -msgid "" +"}\n" +"\n" "fn read_username(path: &str) -> Result {\n" " let mut username = String::with_capacity(100);\n" " File::open(path)?.read_to_string(&mut username)?;\n" @@ -9732,11 +8866,8 @@ msgid "" " return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" " }\n" " Ok(username)\n" -"}" -msgstr "" - -#: src/error-handling/converting-error-types-example.md:41 -msgid "" +"}\n" +"\n" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" " let username = read_username(\"config.dat\");\n" @@ -9768,22 +8899,16 @@ msgid "" "```rust,editable,compile_fail\n" "use std::{fs, io};\n" "use std::io::Read;\n" -"use thiserror::Error;" -msgstr "" - -#: src/error-handling/deriving-error-enums.md:11 -msgid "" +"use thiserror::Error;\n" +"\n" "#[derive(Debug, Error)]\n" "enum ReadUsernameError {\n" " #[error(\"Could not read: {0}\")]\n" " IoError(#[from] io::Error),\n" " #[error(\"Found no username in {0}\")]\n" " EmptyUsername(String),\n" -"}" -msgstr "" - -#: src/error-handling/deriving-error-enums.md:19 -msgid "" +"}\n" +"\n" "fn read_username(path: &str) -> Result {\n" " let mut username = String::with_capacity(100);\n" " fs::File::open(path)?.read_to_string(&mut username)?;\n" @@ -9791,12 +8916,8 @@ msgid "" " return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" " }\n" " Ok(username)\n" -"}" -msgstr "" - -#: src/error-handling/deriving-error-enums.md:28 -#: src/error-handling/dynamic-errors.md:25 -msgid "" +"}\n" +"\n" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" " match read_username(\"config.dat\") {\n" @@ -9834,18 +8955,12 @@ msgid "" "use std::fs::{self, File};\n" "use std::io::Read;\n" "use thiserror::Error;\n" -"use std::error::Error;" -msgstr "" - -#: src/error-handling/dynamic-errors.md:12 -msgid "" +"use std::error::Error;\n" +"\n" "#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" "#[error(\"Found no username in {0}\")]\n" -"struct EmptyUsernameError(String);" -msgstr "" - -#: src/error-handling/dynamic-errors.md:16 -msgid "" +"struct EmptyUsernameError(String);\n" +"\n" "fn read_username(path: &str) -> Result> {\n" " let mut username = String::with_capacity(100);\n" " File::open(path)?.read_to_string(&mut username)?;\n" @@ -9853,7 +8968,16 @@ msgid "" " return Err(EmptyUsernameError(String::from(path)).into());\n" " }\n" " Ok(username)\n" -"}" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" msgstr "" #: src/error-handling/dynamic-errors.md:36 @@ -9880,50 +9004,46 @@ msgid "" "```rust,editable,compile_fail\n" "use std::{fs, io};\n" "use std::io::Read;\n" -"use anyhow::{Context, Result, bail};" -msgstr "" -"```rust,editable,compile_fail\n" -"use std::{fs, io};\n" -"use std::io::Read;\n" -"use anyhow::{Context, Result, bail};" - -#: src/error-handling/error-contexts.md:12 -msgid "" +"use anyhow::{Context, Result, bail};\n" +"\n" "fn read_username(path: &str) -> Result {\n" " let mut username = String::with_capacity(100);\n" " fs::File::open(path)\n" -" .context(format!(\"Failed to open {path}\"))?\n" +" .with_context(|| format!(\"Failed to open {path}\"))?\n" " .read_to_string(&mut username)\n" " .context(\"Failed to read\")?;\n" " if username.is_empty() {\n" " bail!(\"Found no username in {path}\");\n" " }\n" " Ok(username)\n" -"}" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err:?}\"),\n" +" }\n" +"}\n" +"```" msgstr "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use anyhow::{Context, Result, bail};\n" +"\n" "fn read_username(path: &str) -> Result {\n" " let mut username = String::with_capacity(100);\n" " fs::File::open(path)\n" -" .context(format!(\"Failed to open {path}\"))?\n" +" .with_context(|| format!(\"Failed to open {path}\"))?\n" " .read_to_string(&mut username)\n" " .context(\"Failed to read\")?;\n" " if username.is_empty() {\n" " bail!(\"Found no username in {path}\");\n" " }\n" " Ok(username)\n" -"}" - -#: src/error-handling/error-contexts.md:24 -msgid "" -"fn main() {\n" -" //fs::write(\"config.dat\", \"\").unwrap();\n" -" match read_username(\"config.dat\") {\n" -" Ok(username) => println!(\"Username: {username}\"),\n" -" Err(err) => println!(\"Error: {err:?}\"),\n" -" }\n" "}\n" -"```" -msgstr "" +"\n" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" " match read_username(\"config.dat\") {\n" @@ -9956,12 +9076,14 @@ msgid "Rust and Cargo come with a simple unit test framework:" msgstr "러스트와 카고(cargo)는 간단한 단위 테스트 프레임워크와 함께 제공됩니다:" #: src/testing.md:5 -msgid "* Unit tests are supported throughout your code." -msgstr "* 단위 테스트는 코드 전반에서 지원됩니다." - -#: src/testing.md:7 -msgid "* Integration tests are supported via the `tests/` directory." -msgstr "* 통합 테스트는 `tests/` 디렉터리를 통해 지원됩니다." +msgid "" +"* Unit tests are supported throughout your code.\n" +"\n" +"* Integration tests are supported via the `tests/` directory." +msgstr "" +"* 단위 테스트는 코드 전반에서 지원됩니다.\n" +"\n" +"* 통합 테스트는 `tests/` 디렉터리를 통해 지원됩니다." #: src/testing/unit-tests.md:1 msgid "# Unit Tests" @@ -9973,59 +9095,30 @@ msgstr "단위 테스트는 `#[test]` 로 표시합니다:" #: src/testing/unit-tests.md:5 msgid "" -"```rust,editable\n" -"fn first_word(text: &str) -> &str {\n" -" match text.find(' ') {\n" -" Some(idx) => &text[..idx],\n" -" None => &text,\n" -" }\n" -"}" -msgstr "" -"```rust,editable\n" +"```rust,ignore\n" "fn first_word(text: &str) -> &str {\n" " match text.find(' ') {\n" " Some(idx) => &text[..idx],\n" " None => &text,\n" " }\n" -"}" - -#: src/testing/unit-tests.md:13 -msgid "" -"#[test]\n" -"fn test_empty() {\n" -" assert_eq!(first_word(\"\"), \"\");\n" -"}" -msgstr "" +"}\n" +"\n" "#[test]\n" "fn test_empty() {\n" " assert_eq!(first_word(\"\"), \"\");\n" -"}" - -#: src/testing/unit-tests.md:18 -msgid "" -"#[test]\n" -"fn test_single_word() {\n" -" assert_eq!(first_word(\"Hello\"), \"Hello\");\n" -"}" -msgstr "" +"}\n" +"\n" "#[test]\n" "fn test_single_word() {\n" " assert_eq!(first_word(\"Hello\"), \"Hello\");\n" -"}" - -#: src/testing/unit-tests.md:23 -msgid "" -"#[test]\n" -"fn test_multiple_words() {\n" -" assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" "}\n" -"```" -msgstr "" +"\n" "#[test]\n" "fn test_multiple_words() {\n" " assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" "}\n" "```" +msgstr "" #: src/testing/unit-tests.md:29 msgid "Use `cargo test` to find and run the unit tests." @@ -10046,38 +9139,23 @@ msgid "" "```rust,editable\n" "fn helper(a: &str, b: &str) -> String {\n" " format!(\"{a} {b}\")\n" -"}" -msgstr "" -"```rust,editable\n" -"fn helper(a: &str, b: &str) -> String {\n" -" format!(\"{a} {b}\")\n" -"}" - -#: src/testing/test-modules.md:11 -msgid "" -"pub fn main() {\n" -" println!(\"{}\", helper(\"Hello\", \"World\"));\n" -"}" -msgstr "" +"}\n" +"\n" "pub fn main() {\n" " println!(\"{}\", helper(\"Hello\", \"World\"));\n" -"}" - -#: src/testing/test-modules.md:19 -msgid "" -" #[test]\n" -" fn test_helper() {\n" -" assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" -" }\n" "}\n" -"```" -msgstr "" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" " #[test]\n" " fn test_helper() {\n" " assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" " }\n" "}\n" "```" +msgstr "" #: src/testing/test-modules.md:26 msgid "" @@ -10148,19 +9226,17 @@ msgstr "`test/`디렉터리 아래에 `.rs`파일을 하나 만드세요:" #: src/testing/integration-tests.md:7 msgid "" "```rust,ignore\n" -"use my_library::init;" -msgstr "" -"```rust,ignore\n" -"use my_library::init;" - -#: src/testing/integration-tests.md:10 -msgid "" +"use my_library::init;\n" +"\n" "#[test]\n" "fn test_init() {\n" " assert!(init().is_ok());\n" "}\n" "```" msgstr "" +"```rust,ignore\n" +"use my_library::init;\n" +"\n" "#[test]\n" "fn test_init() {\n" " assert!(init().is_ok());\n" @@ -10243,22 +9319,11 @@ msgstr "포인터를 만드는 것은 안전합니다. 하지만 역참조(따 msgid "" "```rust,editable\n" "fn main() {\n" -" let mut num = 5;" -msgstr "" -"```rust,editable\n" -"fn main() {\n" -" let mut num = 5;" - -#: src/unsafe/raw-pointers.md:9 -msgid "" -" let r1 = &mut num as *mut i32;\n" -" let r2 = &num as *const i32;" -msgstr "" +" let mut num = 5;\n" +"\n" " let r1 = &mut num as *mut i32;\n" -" let r2 = &num as *const i32;" - -#: src/unsafe/raw-pointers.md:12 -msgid "" +" 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" @@ -10271,6 +9336,13 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let mut num = 5;\n" +"\n" +" let r1 = &mut num as *mut i32;\n" +" let r2 = r1 as *const i32;\n" +"\n" " // 아래 코드는 안전합니다. r1과 r2는 참조로 부터 만들어 졌기 때문에 null이 아니며\n" " // align이 맞다는 것이 보장됩니다. 참조가 가리키는 객체들은 unsafe 블럭이 수행되는\n" " // 동안 메모리에 살아있습니다. 그리고 이 객체들은 r1과 r2가 아닌 다른 어떤 참조나\n" @@ -10326,18 +9398,16 @@ msgstr "불변 정적변수를 읽는 것은 안전합니다:" #: src/unsafe/mutable-static-variables.md:5 msgid "" "```rust,editable\n" -"static HELLO_WORLD: &str = \"Hello, world!\";" -msgstr "" -"```rust,editable\n" -"static HELLO_WORLD: &str = \"Hello, world!\";" - -#: src/unsafe/mutable-static-variables.md:8 -msgid "" +"static HELLO_WORLD: &str = \"Hello, world!\";\n" +"\n" "fn main() {\n" " println!(\"HELLO_WORLD: {HELLO_WORLD}\");\n" "}\n" "```" msgstr "" +"```rust,editable\n" +"static HELLO_WORLD: &str = \"Hello, world!\";\n" +"\n" "fn main() {\n" " println!(\"HELLO_WORLD: {HELLO_WORLD}\");\n" "}\n" @@ -10352,38 +9422,19 @@ msgstr "하지만, 데이터 레이스가 발생할 수 있으므로 정적 가 #: src/unsafe/mutable-static-variables.md:16 msgid "" "```rust,editable\n" -"static mut COUNTER: u32 = 0;" -msgstr "" -"```rust,editable\n" -"static mut COUNTER: u32 = 0;" - -#: src/unsafe/mutable-static-variables.md:19 -msgid "" -"fn add_to_counter(inc: u32) {\n" -" unsafe { COUNTER += inc; } // Potential data race!\n" -"}" -msgstr "" +"static mut COUNTER: u32 = 0;\n" +"\n" "fn add_to_counter(inc: u32) {\n" " unsafe { COUNTER += inc; } // Potential data race!\n" -"}" - -#: src/unsafe/mutable-static-variables.md:23 -msgid "" -"fn main() {\n" -" add_to_counter(42);" -msgstr "" +"}\n" +"\n" "fn main() {\n" -" add_to_counter(42);" - -#: src/unsafe/mutable-static-variables.md:26 -msgid "" +" add_to_counter(42);\n" +"\n" " unsafe { println!(\"COUNTER: {COUNTER}\"); } // Potential data race!\n" "}\n" "```" msgstr "" -" unsafe { println!(\"COUNTER: {COUNTER}\"); } // Potential data race!\n" -"}\n" -"```" #: src/unsafe/mutable-static-variables.md:32 msgid "" @@ -10406,17 +9457,8 @@ msgid "" "union MyUnion {\n" " i: u8,\n" " b: bool,\n" -"}" -msgstr "" -"```rust,editable\n" -"#[repr(C)]\n" -"union MyUnion {\n" -" i: u8,\n" -" b: bool,\n" -"}" - -#: src/unsafe/unions.md:12 -msgid "" +"}\n" +"\n" "fn main() {\n" " let u = MyUnion { i: 42 };\n" " println!(\"int: {}\", unsafe { u.i });\n" @@ -10424,6 +9466,13 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"#[repr(C)]\n" +"union MyUnion {\n" +" i: u8,\n" +" b: bool,\n" +"}\n" +"\n" "fn main() {\n" " let u = MyUnion { i: 42 };\n" " println!(\"int: {}\", unsafe { u.i });\n" @@ -10458,41 +9507,23 @@ msgstr "함수나 메서드가 정의되지 않은 동작으로 빠지지 않게 msgid "" "```rust,editable\n" "fn main() {\n" -" let emojis = \"🗻∈🌏\";" -msgstr "" - -#: src/unsafe/calling-unsafe-functions.md:10 -msgid "" +" let emojis = \"🗻∈🌏\";\n" +"\n" " // Safe because the indices are in the correct order, within the bounds of\n" " // the string slice, and lie on UTF-8 sequence boundaries.\n" " unsafe {\n" " println!(\"emoji: {}\", emojis.get_unchecked(0..4));\n" " println!(\"emoji: {}\", emojis.get_unchecked(4..7));\n" " println!(\"emoji: {}\", emojis.get_unchecked(7..11));\n" -" }" -msgstr "" -" // 인덱스들이 올바른 순서로 있으며, 문자열 슬라이스의 범위 안에 있고, UTF-8 시퀀스의 범위 안에\n" -" // 있기 때문에 안전합니다.\n" -" unsafe {\n" -" println!(\"emoji: {}\", emojis.get_unchecked(0..4));\n" -" println!(\"emoji: {}\", emojis.get_unchecked(4..7));\n" -" println!(\"emoji: {}\", emojis.get_unchecked(7..11));\n" -" }" - -#: src/unsafe/calling-unsafe-functions.md:18 -msgid " println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..7) }));" -msgstr "" - -#: src/unsafe/calling-unsafe-functions.md:20 -msgid "" +" }\n" +"\n" +" println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..7) }));\n" +"\n" " // Not upholding the UTF-8 encoding requirement breaks memory safety!\n" " // println!(\"emoji: {}\", unsafe { emojis.get_unchecked(0..3) });\n" " // println!(\"char count: {}\", count_chars(unsafe { emojis.get_unchecked(0..3) }));\n" -"}" -msgstr "" - -#: src/unsafe/calling-unsafe-functions.md:25 -msgid "" +"}\n" +"\n" "fn count_chars(s: &str) -> usize {\n" " s.chars().map(|_| 1).sum()\n" "}\n" @@ -10521,7 +9552,20 @@ msgid "" " let temp = *a;\n" " *a = *b;\n" " *b = temp;\n" -"}" +"}\n" +"\n" +"fn main() {\n" +" let mut a = 42;\n" +" let mut b = 66;\n" +"\n" +" // Safe because ...\n" +" unsafe {\n" +" swap(&mut a, &mut b);\n" +" }\n" +"\n" +" println!(\"a = {}, b = {}\", a, b);\n" +"}\n" +"```" msgstr "" "```rust,editable\n" "/// Swaps the values pointed to by the given pointers.\n" @@ -10533,36 +9577,17 @@ msgstr "" " let temp = *a;\n" " *a = *b;\n" " *b = temp;\n" -"}" - -#: src/unsafe/writing-unsafe-functions.md:18 -msgid "" -"fn main() {\n" -" let mut a = 42;\n" -" let mut b = 66;" -msgstr "" +"}\n" +"\n" "fn main() {\n" " let mut a = 42;\n" -" let mut b = 66;" - -#: src/unsafe/writing-unsafe-functions.md:22 -msgid "" -" // Safe because ...\n" -" unsafe {\n" -" swap(&mut a, &mut b);\n" -" }" -msgstr "" +" let mut b = 66;\n" +"\n" " // Safe because ...\n" " unsafe {\n" " swap(&mut a, &mut b);\n" -" }" - -#: src/unsafe/writing-unsafe-functions.md:27 -msgid "" -" println!(\"a = {}, b = {}\", a, b);\n" -"}\n" -"```" -msgstr "" +" }\n" +"\n" " println!(\"a = {}, b = {}\", a, b);\n" "}\n" "```" @@ -10592,15 +9617,8 @@ msgid "" "```rust,editable\n" "extern \"C\" {\n" " fn abs(input: i32) -> i32;\n" -"}" -msgstr "" -"```rust,editable\n" -"extern \"C\" {\n" -" fn abs(input: i32) -> i32;\n" -"}" - -#: src/unsafe/extern-functions.md:11 -msgid "" +"}\n" +"\n" "fn main() {\n" " unsafe {\n" " // Undefined behavior if abs misbehaves.\n" @@ -10609,6 +9627,11 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"extern \"C\" {\n" +" fn abs(input: i32) -> i32;\n" +"}\n" +"\n" "fn main() {\n" " unsafe {\n" " // Undefined behavior if abs misbehaves.\n" @@ -10650,14 +9673,8 @@ msgstr "예를 들어 `zerocopy` 크레이트에는 [안전하지 않은 트레 msgid "" "```rust,editable\n" "use std::mem::size_of_val;\n" -"use std::slice;" -msgstr "" -"```rust,editable\n" -"use std::mem::size_of_val;\n" -"use std::slice;" - -#: src/unsafe/unsafe-traits.md:13 -msgid "" +"use std::slice;\n" +"\n" "/// ...\n" "/// # Safety\n" "/// The type must have a defined representation and no padding.\n" @@ -10667,8 +9684,16 @@ msgid "" " slice::from_raw_parts(self as *const Self as *const u8, size_of_val(self))\n" " }\n" " }\n" -"}" +"}\n" +"\n" +"// Safe because u32 has a defined representation and no padding.\n" +"unsafe impl AsBytes for u32 {}\n" +"```" msgstr "" +"```rust,editable\n" +"use std::mem::size_of_val;\n" +"use std::slice;\n" +"\n" "/// ...\n" "/// # Safety\n" "/// The type must have a defined representation and no padding.\n" @@ -10678,14 +9703,8 @@ msgstr "" " slice::from_raw_parts(self as *const Self as *const u8, size_of_val(self))\n" " }\n" " }\n" -"}" - -#: src/unsafe/unsafe-traits.md:24 -msgid "" -"// Safe because u32 has a defined representation and no padding.\n" -"unsafe impl AsBytes for u32 {}\n" -"```" -msgstr "" +"}\n" +"\n" "// Safe because u32 has a defined representation and no padding.\n" "unsafe impl AsBytes for u32 {}\n" "```" @@ -10716,10 +9735,6 @@ msgstr "디렉터리의 내용을 읽는 안전한 래퍼 코드를 작성해 msgid "After looking at the exercise, you can look at the [solution] provided." msgstr "연습문제를 살펴 본 후, 제공된 [해답][solution]을 살펴볼 수 있습니다." -#: src/exercises/day-3/afternoon.md:9 -msgid "[solution]: solutions-afternoon.md" -msgstr "[solution]: solutions-afternoon.md" - #: src/exercises/day-3/safe-ffi-wrapper.md:1 msgid "# Safe FFI Wrapper" msgstr "# FFI래퍼" @@ -10752,44 +9767,28 @@ msgid "" "C. The [Nomicon] also has a very useful chapter about FFI." msgstr "[`std::ffi`] 모듈을 탐색하는게 필요할 지도 모르겠습니다. C에서 사용되는 NUL-terminated 문자열을 담기 위한 [`CStr`]과 [`CString`] 타입을 확인해 보세요. [Nomicon]문서 또한 FFI에 대한 유용한 내용을 담고 있습니다." -#: src/exercises/day-3/safe-ffi-wrapper.md:17 -msgid "" -"[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" -"[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" -"[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" -"[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" -msgstr "" -"[`std::ffi`]: https://doc.rust-lang.org/std/ffi/\n" -"[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html\n" -"[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html\n" -"[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html" - #: src/exercises/day-3/safe-ffi-wrapper.md:22 msgid "" "Copy the code below to and fill in the missing\n" "functions and methods:" msgstr "아래 코드를 에 복사하고 빠진 함수와 메서드를 채워봅니다:" -#: src/exercises/day-3/safe-ffi-wrapper.md:29 +#: src/exercises/day-3/safe-ffi-wrapper.md:25 msgid "" +"```rust,should_panic\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_imports, unused_variables, dead_code)]\n" +"\n" "mod ffi {\n" -" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:32 -#: src/exercises/day-3/solutions-afternoon.md:26 -msgid "" +" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};\n" +"\n" " // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" " #[repr(C)]\n" " pub struct DIR {\n" " _data: [u8; 0],\n" " _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" -" }" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:39 -#: src/exercises/day-3/solutions-afternoon.md:33 -msgid "" +" }\n" +"\n" " // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" " #[repr(C)]\n" " pub struct dirent {\n" @@ -10798,70 +9797,47 @@ msgid "" " pub d_reclen: c_ushort,\n" " pub d_type: c_char,\n" " pub d_name: [c_char; 256],\n" -" }" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:49 -#: src/exercises/day-3/solutions-afternoon.md:43 -msgid "" +" }\n" +"\n" " extern \"C\" {\n" " pub fn opendir(s: *const c_char) -> *mut DIR;\n" " pub fn readdir(s: *mut DIR) -> *const dirent;\n" " pub fn closedir(s: *mut DIR) -> c_int;\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:56 -#: src/exercises/day-3/solutions-afternoon.md:50 -msgid "" +"}\n" +"\n" "use std::ffi::{CStr, CString, OsStr, OsString};\n" -"use std::os::unix::ffi::OsStrExt;" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:59 -msgid "" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" "#[derive(Debug)]\n" "struct DirectoryIterator {\n" " path: CString,\n" " dir: *mut ffi::DIR,\n" -"}" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:65 -msgid "" +"}\n" +"\n" "impl DirectoryIterator {\n" " fn new(path: &str) -> Result {\n" " // Call opendir and return a Ok value if that worked,\n" " // otherwise return Err with a message.\n" " unimplemented!()\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:73 -msgid "" +"}\n" +"\n" "impl Iterator for DirectoryIterator {\n" " type Item = OsString;\n" " fn next(&mut self) -> Option {\n" " // Keep calling readdir until we get a NULL pointer back.\n" " unimplemented!()\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:81 -msgid "" +"}\n" +"\n" "impl Drop for DirectoryIterator {\n" " fn drop(&mut self) {\n" " // Call closedir as needed.\n" " unimplemented!()\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/safe-ffi-wrapper.md:88 -msgid "" +"}\n" +"\n" "fn main() -> Result<(), String> {\n" " let iter = DirectoryIterator::new(\".\")?;\n" " println!(\"files: {:#?}\", iter.collect::>());\n" @@ -10875,26 +9851,18 @@ msgid "# Welcome to Day 4" msgstr "# 4일차 개요" #: src/welcome-day-4.md:3 -msgid "Today we will look at two main topics:" -msgstr "오늘 강의는 두 가지 주제를 다룹니다:" - -#: src/welcome-day-4.md:5 -msgid "* Concurrency: threads, channels, shared state, `Send` and `Sync`." -msgstr "* 동시성: 쓰레드, 채널, 상태 공유, `Send`와 `Sync`." - -#: src/welcome-day-4.md:7 msgid "" -"* Android: building binaries and libraries, using AIDL, logging, and\n" -" interoperability with C, C++, and Java." -msgstr "* 안드로이드: 바이너리와 라이브러리 만드는 방법, AIDL 사용법, 로깅하는 방법, C/C++, 자바와의 상호 운용성." +"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 "" +"오전에는 동시성을 다룹니다: 쓰레드, 채널, 공유 상태, `Send`와 `Sync`.\n" +"오후에는 러스트가 실제 사용되는 사례를 살펴봅니다." -#: src/welcome-day-4.md:10 +#: src/welcome-day-4.md:8 msgid "" -"> We will attempt to call Rust from one of your own projects today. So try to\n" -"> find a little corner of your code base where we can move some lines of code to\n" -"> Rust. The fewer dependencies and \"exotic\" types the better. Something that\n" -"> parses some raw bytes would be ideal." -msgstr "> 우리는 오늘 여러분의 프로젝트에서 러스트 코드를 호출해볼 것입니다. 그 프로젝트에서 러스트로 옮길만 한 작은 부분을 정하세요. 의존성이 적고 \"특이한\" 타입이 적을 수록 좋습니다. 바이트 몇 개를 파싱하는 코드라면 완벽합니다." +"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 msgid "# Fearless Concurrency" @@ -10925,22 +9893,16 @@ msgstr "러스트의 스레드는 다른 언어의 스레드와 유사하게 동 msgid "" "```rust,editable\n" "use std::thread;\n" -"use std::time::Duration;" -msgstr "" - -#: src/concurrency/threads.md:9 -msgid "" +"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" -" });" -msgstr "" - -#: src/concurrency/threads.md:17 -msgid "" +" });\n" +"\n" " for i in 1..5 {\n" " println!(\"Main thread: {i}\");\n" " thread::sleep(Duration::from_millis(5));\n" @@ -10962,28 +9924,23 @@ msgstr "" #: src/concurrency/threads.md:32 msgid "" "* Notice that the thread is stopped before it reaches 10 — the main thread is\n" -" not waiting." -msgstr "* 메인 스레드가 자식 스레드를 기다리지 않기 때문에 자식 스레드의 for문은 10까지 가지 않습니다." - -#: src/concurrency/threads.md:35 -msgid "" +" not waiting.\n" +"\n" "* Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for\n" -" the thread to finish." -msgstr "* 만약 메인 스레드가 자식 스레드가 끝날 때 까지 기다리기를 원한다면 `let handle = thread::spawn(...)`으로 스레드를 선언한 후 `handle.join()`로 연결하여 사용합니다." - -#: src/concurrency/threads.md:38 -msgid "* Trigger a panic in the thread, notice how this doesn't affect `main`." -msgstr "* 자식 스레드에서 발생한 패닉이 메인 스레드에는 영향을 주지 않음을 확인하시기 바랍니다." - -#: src/concurrency/threads.md:40 -msgid "" +" 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 "* `handle.join()`사용시 `Result` 반환값을 통해 패닉의 추가정보에 접근할 수 있습니다. 이 시점에서 [`Any`]에 대해 이야기를 해 보면 좋습니다." - -#: src/concurrency/threads.md:43 -msgid "[`Any`]: https://doc.rust-lang.org/std/any/index.html" msgstr "" +"* 메인 스레드가 자식 스레드를 기다리지 않기 때문에 자식 스레드의 for문은 10까지 가지 않습니다.\n" +"\n" +"* 만약 메인 스레드가 자식 스레드가 끝날 때 까지 기다리기를 원한다면 `let handle = thread::spawn(...)`으로 스레드를 선언한 후 `handle.join()`로 연결하여 사용합니다.\n" +"\n" +"* 자식 스레드에서 발생한 패닉이 메인 스레드에는 영향을 주지 않음을 확인하시기 바랍니다.\n" +"\n" +"* `handle.join()`사용시 `Result` 반환값을 통해 패닉의 추가정보에 접근할 수 있습니다. 이 시점에서 [`Any`]에 대해 이야기를 해 보면 좋습니다." #: src/concurrency/scoped-threads.md:1 msgid "# Scoped Threads" @@ -10996,17 +9953,11 @@ msgstr "보통, 스레드는 스레드 밖에서 데이터를 빌릴 수 없습 #: src/concurrency/scoped-threads.md:5 msgid "" "```rust,editable,compile_fail\n" -"use std::thread;" -msgstr "" - -#: src/concurrency/scoped-threads.md:8 src/concurrency/scoped-threads.md:22 -msgid "" +"use std::thread;\n" +"\n" "fn main() {\n" -" let s = String::from(\"Hello\");" -msgstr "" - -#: src/concurrency/scoped-threads.md:11 -msgid "" +" let s = String::from(\"Hello\");\n" +"\n" " thread::spawn(|| {\n" " println!(\"Length: {}\", s.len());\n" " });\n" @@ -11021,11 +9972,11 @@ msgstr "하지만, [scoped thread][1]에서는 가능합니다:" #: src/concurrency/scoped-threads.md:19 msgid "" "```rust,editable\n" -"use std::thread;" -msgstr "" - -#: src/concurrency/scoped-threads.md:25 -msgid "" +"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" @@ -11035,25 +9986,15 @@ msgid "" "```" msgstr "" -#: src/concurrency/scoped-threads.md:33 -msgid "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html" -msgstr "" - -#: src/concurrency/scoped-threads.md:35 +#: src/concurrency/scoped-threads.md:37 msgid "" -"
\n" -" \n" "* 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" -" \n" -"
" +" " msgstr "" -"
\n" -" \n" "* `thread::scope` 함수가 완료되면 그 안에서 생성된 모든 스레드들이 종료했음이 보장되기 때문에, 그 때 빌렸던 데이터들을 다시 반환할 수 있기 때문입니다.\n" "* 일반적인 러스트의 빌림 규칙이 적용됩니다: 한 스레드에 의한 가변 빌림 또는 여러 스레드에 대한 불변 빌림중 하나만 가능합니다.\n" -" \n" -"
" +" " #: src/concurrency/channels.md:1 msgid "# Channels" @@ -11069,29 +10010,17 @@ msgstr "러스트의 채널은 `Sender` 와 `Receiver` 두 부분으로 msgid "" "```rust,editable\n" "use std::sync::mpsc;\n" -"use std::thread;" -msgstr "" - -#: src/concurrency/channels.md:10 src/concurrency/channels/unbounded.md:10 -msgid "" +"use std::thread;\n" +"\n" "fn main() {\n" -" let (tx, rx) = mpsc::channel();" -msgstr "" - -#: src/concurrency/channels.md:13 -msgid "" +" let (tx, rx) = mpsc::channel();\n" +"\n" " tx.send(10).unwrap();\n" -" tx.send(20).unwrap();" -msgstr "" - -#: src/concurrency/channels.md:16 -msgid "" +" tx.send(20).unwrap();\n" +"\n" " println!(\"Received: {:?}\", rx.recv());\n" -" println!(\"Received: {:?}\", rx.recv());" -msgstr "" - -#: src/concurrency/channels.md:19 -msgid "" +" println!(\"Received: {:?}\", rx.recv());\n" +"\n" " let tx2 = tx.clone();\n" " tx2.send(30).unwrap();\n" " println!(\"Received: {:?}\", rx.recv());\n" @@ -11118,17 +10047,15 @@ msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" msgstr "`mpsc::channel()` 함수는 경계가 없는 비동기 채널을 생성합니다:" #: src/concurrency/channels/unbounded.md:5 -#: src/concurrency/channels/bounded.md:5 msgid "" "```rust,editable\n" "use std::sync::mpsc;\n" "use std::thread;\n" -"use std::time::Duration;" -msgstr "" - -#: src/concurrency/channels/unbounded.md:13 -#: src/concurrency/channels/bounded.md:13 -msgid "" +"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" @@ -11137,11 +10064,8 @@ msgid "" " }\n" " println!(\"{thread_id:?}: done\");\n" " });\n" -" thread::sleep(Duration::from_millis(100));" -msgstr "" - -#: src/concurrency/channels/unbounded.md:23 -msgid "" +" thread::sleep(Duration::from_millis(100));\n" +"\n" " for msg in rx.iter() {\n" " println!(\"Main: got {}\", msg);\n" " }\n" @@ -11157,14 +10081,26 @@ msgstr "# 경계가 있는 채널(Bounded Channels)" msgid "Bounded and synchronous channels make `send` block the current thread:" msgstr "경계가 있는 동기 채널은 `send`가 현제 스레드를 블로킹 하도록 만듭니다:" -#: src/concurrency/channels/bounded.md:10 +#: 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);" -msgstr "" - -#: src/concurrency/channels/bounded.md:23 -msgid "" +" 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" @@ -11191,14 +10127,6 @@ msgstr "" "* [`Arc`][1], `T`에 대한 아토믹 참조 카운트: 이 참조는 다수의 스레드 사이에서 공유될 수 있고, 참조하던 마지막 스레드가 종료할 경우 `T`를 반환합니다.\n" "* [`Mutex`][2]: `T`값에 대한 상호 배제 엑세스를 보장합니다." -#: src/concurrency/shared_state.md:10 -msgid "" -"[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" -"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" -msgstr "" -"[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n" -"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html" - #: src/concurrency/shared_state/arc.md:1 msgid "# `Arc`" msgstr "# `Arc`" @@ -11211,11 +10139,8 @@ msgstr "[`Arc`][1]의 `clone` 메서드를 이용하면 여러 스레드가 msgid "" "```rust,editable\n" "use std::thread;\n" -"use std::sync::Arc;" -msgstr "" - -#: src/concurrency/shared_state/arc.md:9 -msgid "" +"use std::sync::Arc;\n" +"\n" "fn main() {\n" " let v = Arc::new(vec![10, 20, 30]);\n" " let mut handles = Vec::new();\n" @@ -11225,21 +10150,14 @@ msgid "" " let thread_id = thread::current().id();\n" " println!(\"{thread_id:?}: {v:?}\");\n" " }));\n" -" }" -msgstr "" - -#: src/concurrency/shared_state/arc.md:20 -msgid "" +" }\n" +"\n" " handles.into_iter().for_each(|h| h.join().unwrap());\n" " println!(\"v: {v:?}\");\n" "}\n" "```" msgstr "" -#: src/concurrency/shared_state/arc.md:25 -msgid "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" -msgstr "" - #: src/concurrency/shared_state/arc.md:29 msgid "" "* `Arc` stands for \"Atomic Reference Counted\", a thread safe version of `Rc` that uses atomic\n" @@ -11270,30 +10188,17 @@ msgstr "[`Mutex`][1]를 이용하면 불변 참조를 통해서도 `T`의 값 #: src/concurrency/shared_state/mutex.md:6 msgid "" "```rust,editable\n" -"use std::sync::Mutex;" -msgstr "" - -#: src/concurrency/shared_state/mutex.md:9 -msgid "" +"use std::sync::Mutex;\n" +"\n" "fn main() {\n" " let v = Mutex::new(vec![10, 20, 30]);\n" -" println!(\"v: {:?}\", v.lock().unwrap());" -msgstr "" - -#: src/concurrency/shared_state/mutex.md:13 -msgid "" -" {\n" -" let mut guard = v.lock().unwrap();\n" -" guard.push(40);\n" -" }" -msgstr "" +" println!(\"v: {:?}\", v.lock().unwrap());\n" +"\n" " {\n" " let mut guard = v.lock().unwrap();\n" " guard.push(40);\n" -" }" - -#: src/concurrency/shared_state/mutex.md:18 -msgid "" +" }\n" +"\n" " println!(\"v: {:?}\", v.lock().unwrap());\n" "}\n" "```" @@ -11305,17 +10210,8 @@ msgid "" "implementation." msgstr "모든 `Mutex`는 [`impl Sync for Mutex`][2]를 자동으로 구현함을 참조하세요." -#: src/concurrency/shared_state/mutex.md:25 -msgid "" -"[1]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n" -"[2]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Sync-for-Mutex%3CT%3E\n" -"[3]: https://doc.rust-lang.org/std/sync/struct.Arc.html" -msgstr "" - -#: src/concurrency/shared_state/mutex.md:29 +#: src/concurrency/shared_state/mutex.md:31 msgid "" -"
\n" -" \n" "* `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" @@ -11328,8 +10224,6 @@ msgid "" " fails with a [`PoisonError`]. You can call `into_inner()` on the error to recover the data\n" " regardless." msgstr "" -"
\n" -" \n" "* 러스트의 `Mutex`는 오직 하나의 데이터만 담을 수 있는 컬렉션처럼 볼 수도 있습니다. 다른 컬렉션과 다른 점은, 그 데이터가 동시성 문제로부터 자유롭다는 점입니다.\n" " * `Mutex`는 뮤텍스를 획득하지 않으면 보호된 데이터에 접근하는 것이 불가능 하도록 디자인 되어 있습니다.\n" "* `&Mutex`에 대해 lock을 획득하면 `&mut T`를 얻을 수 있습니다. `MutexGuard`는 `&mut T`가 획득한 lock보다 오래 살아남지 않음을 보장합니다.\n" @@ -11338,13 +10232,6 @@ msgstr "" "* 왜 `lock()`이 `Result`를 반환할까요?\n" " * `Mutex`를 획득한 스레드에서 패닉이 발생하면, 데이터가 올바르지 않은 상황이 될 수 있습니다. 이를 `Mutex`가 \"중독(poisoned)\" 되었다고 표현하며, 중독된 뮤텍스에서 `lock()`을 호출하면 실패하고 [`PoisonError`]가 발생합니다. 이러한 오류로부터 데이터를 복구하기 위해 `into_inner()`를 호출할 수 있습니다." -#: src/concurrency/shared_state/mutex.md:43 -msgid "" -"[`PoisonError`]: https://doc.rust-lang.org/std/sync/struct.PoisonError.html \n" -" \n" -"
" -msgstr "" - #: src/concurrency/shared_state/example.md:3 msgid "Let us see `Arc` and `Mutex` in action:" msgstr "`Arc`와 `Mutex`의 동작을 살펴봅시다:" @@ -11353,21 +10240,15 @@ msgstr "`Arc`와 `Mutex`의 동작을 살펴봅시다:" msgid "" "```rust,editable,compile_fail\n" "use std::thread;\n" -"// use std::sync::{Arc, Mutex};" -msgstr "" - -#: src/concurrency/shared_state/example.md:9 -msgid "" +"// 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);" -msgstr "" - -#: src/concurrency/shared_state/example.md:16 -msgid "" +" v.push(1000);\n" +"\n" " handle.join().unwrap();\n" " println!(\"v: {v:?}\");\n" "}\n" @@ -11375,79 +10256,51 @@ msgid "" msgstr "" #: src/concurrency/shared_state/example.md:23 -msgid "" -"Possible solution:\n" -" \n" -"```rust,editable\n" -"use std::sync::{Arc, Mutex};\n" -"use std::thread;" +msgid "Possible solution:" msgstr "" -"가능한 해결방법입니다.:\n" -" \n" -"```rust,editable\n" -"use std::sync::{Arc, Mutex};\n" -"use std::thread;" -#: src/concurrency/shared_state/example.md:29 +#: 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]));" -msgstr "" - -#: src/concurrency/shared_state/example.md:32 -msgid "" +" 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" -" });" -msgstr "" - -#: src/concurrency/shared_state/example.md:38 -msgid "" +" });\n" +"\n" " {\n" " let mut v = v.lock().unwrap();\n" " v.push(1000);\n" -" }" -msgstr "" - -#: src/concurrency/shared_state/example.md:43 -msgid " handle.join().unwrap();" -msgstr "" - -#: src/concurrency/shared_state/example.md:45 -msgid "" -" {\n" -" let v = v.lock().unwrap();\n" -" println!(\"v: {v:?}\");\n" " }\n" +"\n" +" handle.join().unwrap();\n" +"\n" +" println!(\"v: {v:?}\");\n" "}\n" -"```\n" -" \n" -"Notable parts:" +"```" msgstr "" -" {\n" -" let v = v.lock().unwrap();\n" -" println!(\"v: {v:?}\");\n" -" }\n" -"}\n" -"```\n" -" \n" -"참고 사항:" -#: src/concurrency/shared_state/example.md:54 +#: src/concurrency/shared_state/example.md:49 +msgid "Notable parts:" +msgstr "눈여겨 볼 부분:" + +#: src/concurrency/shared_state/example.md:51 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.\n" -"* We still need to acquire the `Mutex` to print our `Vec`." +"* Blocks are introduced to narrow the scope of the `LockGuard` as much as possible." msgstr "" "* `v`는 `Arc`와 `Mutex` 모두에 포함되어 있습니다. 이는 `Arc`와 `Mutex`가 서로 완전히 다른 문제를 위한 도구이기 때문입니다.\n" " * `Mutex`를 `Arc`로 래핑하는 것은 가변 상태를 스레드들 간에 공유할 때 흔히 사용하는 패턴입니다.\n" "* `v: Arc<_>`를 다른 스레드에서 사용하려면, 먼저 `v2`로 복사를 하고 이를 그 스레드로 이동 해야 합니다. 그래서 람다의 시그니처에 `move`가 있는 것입니다.\n" -"* 블록은 `LockGuard`의 범위를 최대한 좁히기 위해 사용되었습니다.\n" -"* `Vec`을 단순히 출력하기 위해서도 여전히 `Mutex`를 획득해야 합니다." +"* 블록은 `LockGuard`의 범위를 최대한 좁히기 위해 사용되었습니다." #: src/concurrency/send-sync.md:1 msgid "# `Send` and `Sync`" @@ -11474,27 +10327,15 @@ msgid "" "know it is valid." msgstr "`Send`와 `Sync` 트레잇은 [안전하지 않은 트레잇][3]입니다. 컴파일러는 타입의 요소들이 모두 `Send`와 `Sync` 타입이면 자동으로 이 트레잇들을 적용시켜 줍니다. 물론 여러분 스스로 맞다고 알고 있다면 직접 구현해도 됩니다." -#: src/concurrency/send-sync.md:14 -msgid "" -"[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" -"[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html\n" -"[3]: ../unsafe/unsafe-traits.md" -msgstr "" -"[1]: https://doc.rust-lang.org/std/marker/trait.Send.html\n" -"[2]: https://doc.rust-lang.org/std/marker/trait.Sync.html\n" -"[3]: ../unsafe/unsafe-traits.md" - #: src/concurrency/send-sync.md:20 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" -" \n" -"
" +" " msgstr "" "* `Sync`와 `Send`는 어떤 타입이 특정한 스레드-안전 속성을 가짐을 나타내는 마커로 생각할 수 있습니다.\n" -"* 이 두 트레잇은 제네릭에서 제약 조건을 나타내는 트레잇로 사용될 수도 있습니다.\n" -"\n" -"" +"* 이 두 트레이트는 제너릭에서 제약 조건을 나타내는 트레이트로 사용될 수도 있습니다.\n" +" " #: src/concurrency/send-sync/send.md:1 msgid "# `Send`" @@ -11511,10 +10352,6 @@ msgid "" "and deallocate it in another." msgstr "소유권을 다른 스레드로 이동하면 소멸자가 해당 스레드에서 실행됩니다. 여기서 의문은 \"언제 한 스레드에서 값을 할당하고 다른 스레드에서 값을 할당 해제할 수 있는가\" 입니다." -#: src/concurrency/send-sync/send.md:9 -msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" -msgstr "" - #: src/concurrency/send-sync/sync.md:1 msgid "# `Sync`" msgstr "# `Sync`" @@ -11533,10 +10370,6 @@ msgstr "좀 더 정확한 정의는 다음과 같습니다:" msgid "> `T` is `Sync` if and only if `&T` is `Send`" msgstr "`&T`가 `Send`인 경우에만 `T`의 타입이 `Sync`가 됩니다" -#: src/concurrency/send-sync/sync.md:10 -msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Sync.html" -msgstr "" - #: src/concurrency/send-sync/sync.md:14 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 "위 문장을 풀어서 이야기 하면, 어떤 타입이 스레드 간에 공유되어서 사용되기에 안전하다면 그 타입의 참조 타입은 스레드 간에 이동 가능하다는 것입니다." @@ -11629,7 +10462,7 @@ msgstr "" "* `Rc`: `Rc` 는 아토믹하지 않은 방식으로 참조 카운트를 조작하는 `RcBox`를 참조합니다.\n" "* `*const T`, `*mut T`: 러스트는 포인터가 스레드 안전하지 않다고 가정합니다." -#: src/exercises/day-4/morning.md:1 src/exercises/day-4/afternoon.md:1 +#: src/exercises/day-4/morning.md:1 src/exercises/day-4/android.md:1 msgid "# Exercises" msgstr "# 연습문제" @@ -11638,14 +10471,15 @@ msgid "Let us practice our new concurrency skills with" msgstr "동시성 기법들을 연습해 봅시다" #: src/exercises/day-4/morning.md:5 -msgid "* Dining philosophers: a classic problem in concurrency." -msgstr "* 식사하는 철학자 문제: 고적적인 동시성 문제입니다." - -#: src/exercises/day-4/morning.md:7 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 "* 멀티 스레드 링크 검사기: 병렬적으로 웹페이지의 링크들을 체크합니다. 카고를 통해 몇 가지 의존성들을 다운도르 받아야 하는 큰 프로젝트 입니다." +msgstr "" +"* 식사하는 철학자 문제: 고적적인 동시성 문제입니다.\n" +"\n" +"* 멀티 스레드 링크 검사기: 병렬적으로 웹페이지의 링크들을 체크합니다. 카고를 통해 몇 가지 의존성들을 다운도르 받아야 하는 큰 프로젝트 입니다." #: src/exercises/day-4/dining-philosophers.md:1 msgid "# Dining Philosophers" @@ -11687,67 +10521,41 @@ msgid "" "use std::sync::mpsc;\n" "use std::sync::{Arc, Mutex};\n" "use std::thread;\n" -"use std::time::Duration;" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:23 -#: src/exercises/day-4/solutions-morning.md:28 -msgid "struct Fork;" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:25 -msgid "" +"use std::time::Duration;\n" +"\n" +"struct Fork;\n" +"\n" "struct Philosopher {\n" " name: String,\n" " // left_fork: ...\n" " // right_fork: ...\n" " // thoughts: ...\n" -"}" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:32 -msgid "" +"}\n" +"\n" "impl Philosopher {\n" " fn think(&self) {\n" " self.thoughts\n" " .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" " .unwrap();\n" -" }" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:39 -msgid "" +" }\n" +"\n" " fn eat(&self) {\n" " // Pick up forks...\n" " println!(\"{} is eating...\", &self.name);\n" " thread::sleep(Duration::from_millis(10));\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:46 -#: src/exercises/day-4/solutions-morning.md:60 -msgid "" +"}\n" +"\n" "static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:49 -msgid "" +" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" +"\n" "fn main() {\n" -" // Create forks" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:52 -msgid " // Create philosophers" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:54 -msgid " // Make them think and eat" -msgstr "" - -#: src/exercises/day-4/dining-philosophers.md:56 -msgid "" +" // Create forks\n" +"\n" +" // Create philosophers\n" +"\n" +" // Make them think and eat\n" +"\n" " // Output their thoughts\n" "}\n" "```" @@ -11840,29 +10648,20 @@ msgid "" "use reqwest::blocking::{get, Response};\n" "use reqwest::Url;\n" "use scraper::{Html, Selector};\n" -"use thiserror::Error;" -msgstr "" - -#: src/exercises/day-4/link-checker.md:53 -msgid "" +"use thiserror::Error;\n" +"\n" "#[derive(Error, Debug)]\n" "enum Error {\n" " #[error(\"request error: {0}\")]\n" " ReqwestError(#[from] reqwest::Error),\n" -"}" -msgstr "" - -#: src/exercises/day-4/link-checker.md:59 -msgid "" +"}\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();" -msgstr "" - -#: src/exercises/day-4/link-checker.md:65 -msgid "" +" 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" @@ -11873,17 +10672,11 @@ msgid "" " }\n" " }\n" " }\n" -" }" -msgstr "" - -#: src/exercises/day-4/link-checker.md:77 -msgid "" +" }\n" +"\n" " Ok(valid_urls)\n" -"}" -msgstr "" - -#: src/exercises/day-4/link-checker.md:80 -msgid "" +"}\n" +"\n" "fn main() {\n" " let start_url = Url::parse(\"https://www.google.org\").unwrap();\n" " let response = get(start_url).unwrap();\n" @@ -11921,13 +10714,6 @@ msgstr "" "* 스레드를 사용하여 링크를 병렬로 확인합니다: URL을 채널로 보내서 몇 개의 스레드가 URL을 병렬로 체크하도록 합니다.\n" "* `www.google.org`도메인의 모든 페이지를 재귀적으로 확인하기 위해 코드를 확장해서 작성합니다: 차단당하지 않도록 100페이지 정도로 제한을 두시기 바랍니다." -#: src/exercises/day-4/link-checker.md:104 -msgid "" -"[1]: https://docs.rs/reqwest/\n" -"[2]: https://docs.rs/scraper/\n" -"[3]: https://docs.rs/thiserror/" -msgstr "" - #: src/android.md:1 msgid "# Android" msgstr "# 안드로이드" @@ -11939,6 +10725,14 @@ msgid "" "existing services." msgstr "러스트는 안드로이드 네이티브 플랫폼 개발을 지원합니다. 기존의 OS 서비스를 확장하거나, 새로운 서비스를 만드는데 러스트를 쓸 수 있습니다." +#: src/android.md:7 +msgid "" +"> We will attempt to call Rust from one of your own projects today. So try to\n" +"> find a little corner of your code base where we can move some lines of code to\n" +"> Rust. The fewer dependencies and \"exotic\" types the better. Something that\n" +"> parses some raw bytes would be ideal." +msgstr "> 우리는 오늘 여러분의 프로젝트에서 러스트 코드를 호출해볼 것입니다. 그 프로젝트에서 러스트로 옮길만 한 작은 부분을 정하세요. 의존성이 적고 \"특이한\" 타입이 적을 수록 좋습니다. 바이트 몇 개를 파싱하는 코드라면 완벽합니다." + #: src/android/setup.md:1 msgid "# Setup" msgstr "# 설치" @@ -12032,11 +10826,8 @@ msgstr "" #: src/android/build-rules/binary.md:18 msgid "" "```rust\n" -"//! Rust demo." -msgstr "" - -#: src/android/build-rules/binary.md:21 -msgid "" +"//! Rust demo.\n" +"\n" "/// Prints a greeting to standard output.\n" "fn main() {\n" " println!(\"Hello from Rust!\");\n" @@ -12079,10 +10870,6 @@ msgstr "" "* 아래에 정의한 `libgreeting`.\n" "* [`external/rust/crates/`][crates]에 존재하는 `libtextwrap`." -#: src/android/build-rules/library.md:11 -msgid "[crates]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/" -msgstr "" - #: src/android/build-rules/library.md:15 msgid "" "```javascript\n" @@ -12095,11 +10882,8 @@ msgid "" " \"libtextwrap\",\n" " ],\n" " prefer_rlib: true,\n" -"}" -msgstr "" - -#: src/android/build-rules/library.md:27 -msgid "" +"}\n" +"\n" "rust_library {\n" " name: \"libgreetings\",\n" " crate_name: \"greetings\",\n" @@ -12111,17 +10895,11 @@ msgstr "" #: src/android/build-rules/library.md:36 msgid "" "```rust,ignore\n" -"//! Rust demo." -msgstr "" - -#: src/android/build-rules/library.md:39 -msgid "" +"//! Rust demo.\n" +"\n" "use greetings::greeting;\n" -"use textwrap::fill;" -msgstr "" - -#: src/android/build-rules/library.md:42 -msgid "" +"use textwrap::fill;\n" +"\n" "/// Prints a greeting to standard output.\n" "fn main() {\n" " println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" @@ -12136,11 +10914,8 @@ msgstr "" #: src/android/build-rules/library.md:50 msgid "" "```rust,ignore\n" -"//! Greeting library." -msgstr "" - -#: src/android/build-rules/library.md:53 -msgid "" +"//! Greeting library.\n" +"\n" "/// Greet `name`.\n" "pub fn greeting(name: &str) -> String {\n" " format!(\"Hello {name}, it is very nice to meet you!\")\n" @@ -12193,14 +10968,11 @@ msgstr "AIDL 인터페이스를 이용해서 서비스의 API를 선언합니다 msgid "*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:" msgstr "" -#: src/android/aidl/interface.md:7 src/android/aidl/changing.md:6 +#: src/android/aidl/interface.md:7 msgid "" "```java\n" -"package com.example.birthdayservice;" -msgstr "" - -#: src/android/aidl/interface.md:10 -msgid "" +"package com.example.birthdayservice;\n" +"\n" "/** Birthday service interface. */\n" "interface IBirthdayService {\n" " /** Generate a Happy Birthday message. */\n" @@ -12252,21 +11024,13 @@ msgid "" "```rust,ignore\n" "//! Implementation of the `IBirthdayService` AIDL interface.\n" "use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;\n" -"use com_example_birthdayservice::binder;" -msgstr "" - -#: src/android/aidl/implementation.md:12 -msgid "" +"use com_example_birthdayservice::binder;\n" +"\n" "/// The `IBirthdayService` implementation.\n" -"pub struct BirthdayService;" -msgstr "" - -#: src/android/aidl/implementation.md:15 -msgid "impl binder::Interface for BirthdayService {}" -msgstr "" - -#: src/android/aidl/implementation.md:17 -msgid "" +"pub struct BirthdayService;\n" +"\n" +"impl binder::Interface for BirthdayService {}\n" +"\n" "impl IBirthdayService for BirthdayService {\n" " fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result {\n" " Ok(format!(\n" @@ -12315,15 +11079,10 @@ msgid "" "//! Birthday service.\n" "use birthdayservice::BirthdayService;\n" "use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::BnBirthdayService;\n" -"use com_example_birthdayservice::binder;" -msgstr "" - -#: src/android/aidl/server.md:13 src/android/aidl/client.md:12 -msgid "const SERVICE_IDENTIFIER: &str = \"birthdayservice\";" -msgstr "" - -#: src/android/aidl/server.md:15 -msgid "" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" "/// Entry point for birthday service.\n" "fn main() {\n" " let birthday_service = BirthdayService;\n" @@ -12421,19 +11180,15 @@ msgid "" "```rust,ignore\n" "//! Birthday service.\n" "use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;\n" -"use com_example_birthdayservice::binder;" -msgstr "" - -#: src/android/aidl/client.md:14 -msgid "" +"use com_example_birthdayservice::binder;\n" +"\n" +"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" +"\n" "/// Connect to the BirthdayService.\n" "pub fn connect() -> Result, binder::StatusCode> {\n" " binder::get_interface(SERVICE_IDENTIFIER)\n" -"}" -msgstr "" - -#: src/android/aidl/client.md:19 -msgid "" +"}\n" +"\n" "/// Call the birthday service.\n" "fn main() -> Result<(), binder::Status> {\n" " let name = std::env::args()\n" @@ -12442,11 +11197,8 @@ msgid "" " let years = std::env::args()\n" " .nth(2)\n" " .and_then(|arg| arg.parse::().ok())\n" -" .unwrap_or(42);" -msgstr "" - -#: src/android/aidl/client.md:29 -msgid "" +" .unwrap_or(42);\n" +"\n" " binder::ProcessState::start_thread_pool();\n" " let service = connect().expect(\"Failed to connect to BirthdayService\");\n" " let msg = service.wishHappyBirthday(&name, years)?;\n" @@ -12500,8 +11252,11 @@ msgid "" "list of lines for the birthday card:" msgstr "API를 확장하여 더 많은 기능을 제공해 봅시다. 클라이언트가 생일 카드에 담길 내용을 지정할 수 있도록 하겠습니다:" -#: src/android/aidl/changing.md:9 +#: src/android/aidl/changing.md:6 msgid "" +"```java\n" +"package com.example.birthdayservice;\n" +"\n" "/** Birthday service interface. */\n" "interface IBirthdayService {\n" " /** Generate a Happy Birthday message. */\n" @@ -12548,15 +11303,10 @@ msgstr "" #: src/android/logging.md:24 msgid "" "```rust,ignore\n" -"//! Rust logging demo." -msgstr "" - -#: src/android/logging.md:27 -msgid "use log::{debug, error, info};" -msgstr "" - -#: src/android/logging.md:29 -msgid "" +"//! Rust logging demo.\n" +"\n" +"use log::{debug, error, info};\n" +"\n" "/// Logs a greeting.\n" "fn main() {\n" " logger::init(\n" @@ -12642,11 +11392,8 @@ msgid "" "```rust\n" "extern \"C\" {\n" " fn abs(x: i32) -> i32;\n" -"}" -msgstr "" - -#: src/android/interoperability/with-c.md:13 -msgid "" +"}\n" +"\n" "fn main() {\n" " let x = -42;\n" " let abs_x = unsafe { abs(x) };\n" @@ -12695,11 +11442,8 @@ msgid "" "typedef struct card {\n" " const char* name;\n" " int years;\n" -"} card;" -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:16 -msgid "" +"} card;\n" +"\n" "void print_card(const card* card);\n" "```" msgstr "" @@ -12712,11 +11456,8 @@ msgstr "" msgid "" "```c\n" "#include \n" -"#include \"libbirthday.h\"" -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:25 -msgid "" +"#include \"libbirthday.h\"\n" +"\n" "void print_card(const card* card) {\n" " printf(\"+--------------\\n\");\n" " printf(\"| Happy Birthday %s!\\n\", card->name);\n" @@ -12803,15 +11544,10 @@ msgstr "" #: src/android/interoperability/with-c/bindgen.md:81 msgid "" "```rust,compile_fail\n" -"//! Bindgen demo." -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:84 -msgid "use birthday_bindgen::{card, print_card};" -msgstr "" - -#: src/android/interoperability/with-c/bindgen.md:86 -msgid "" +"//! Bindgen demo.\n" +"\n" +"use birthday_bindgen::{card, print_card};\n" +"\n" "fn main() {\n" " let name = std::ffi::CString::new(\"Peter\").unwrap();\n" " let card = card {\n" @@ -12876,15 +11612,10 @@ msgstr "" msgid "" "```rust,editable\n" "//! Rust FFI demo.\n" -"#![deny(improper_ctypes_definitions)]" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:11 -msgid "use std::os::raw::c_int;" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:13 -msgid "" +"#![deny(improper_ctypes_definitions)]\n" +"\n" +"use std::os::raw::c_int;\n" +"\n" "/// Analyze the numbers.\n" "#[no_mangle]\n" "pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" @@ -12905,18 +11636,12 @@ msgstr "" msgid "" "```c\n" "#ifndef ANALYSE_H\n" -"#define ANALYSE_H" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:30 -msgid "" +"#define ANALYSE_H\n" +"\n" "extern \"C\" {\n" "void analyze_numbers(int x, int y);\n" -"}" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:34 -msgid "" +"}\n" +"\n" "#endif\n" "```" msgstr "" @@ -12948,11 +11673,8 @@ msgstr "" #: src/android/interoperability/with-c/rust.md:52 msgid "" "```c\n" -"#include \"analyze.h\"" -msgstr "" - -#: src/android/interoperability/with-c/rust.md:55 -msgid "" +"#include \"analyze.h\"\n" +"\n" "int main() {\n" " analyze_numbers(10, 20);\n" " analyze_numbers(123, 123);\n" @@ -13013,12 +11735,6 @@ msgstr "" msgid "See the [CXX tutorial][2] for an full example of using this." msgstr "사용하는 방법에 대해서는[CXX 튜토리얼][2] 를 참조합니다." -#: src/android/interoperability/cpp.md:12 -msgid "" -"[1]: https://cxx.rs/\n" -"[2]: https://cxx.rs/tutorial.html" -msgstr "" - #: src/android/interoperability/java.md:1 msgid "# Interoperability with Java" msgstr "# Java와의 상호운용성" @@ -13041,18 +11757,12 @@ msgstr "" #: src/android/interoperability/java.md:11 msgid "" "```rust,compile_fail\n" -"//! Rust <-> Java FFI demo." -msgstr "" - -#: src/android/interoperability/java.md:14 -msgid "" +"//! Rust <-> Java FFI demo.\n" +"\n" "use jni::objects::{JClass, JString};\n" "use jni::sys::jstring;\n" -"use jni::JNIEnv;" -msgstr "" - -#: src/android/interoperability/java.md:18 -msgid "" +"use jni::JNIEnv;\n" +"\n" "/// HelloWorld::hello method implementation.\n" "#[no_mangle]\n" "pub extern \"system\" fn Java_HelloWorld_hello(\n" @@ -13097,18 +11807,12 @@ msgstr "" msgid "" "```java\n" "class HelloWorld {\n" -" private static native String hello(String name);" -msgstr "" - -#: src/android/interoperability/java.md:51 -msgid "" +" private static native String hello(String name);\n" +"\n" " static {\n" " System.loadLibrary(\"hello_jni\");\n" -" }" -msgstr "" - -#: src/android/interoperability/java.md:55 -msgid "" +" }\n" +"\n" " public static void main(String[] args) {\n" " String output = HelloWorld.hello(\"Alice\");\n" " System.out.println(output);\n" @@ -13142,21 +11846,23 @@ msgid "" "```" msgstr "" -#: src/exercises/day-4/afternoon.md:3 +#: src/exercises/day-4/android.md:3 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:" msgstr "마지막 연습문제는 여러분이 작업하고 있는 프로젝트 중 하나를 FFI로 러스트와 연계 해보는 것입니다. 몇 가지 예시입니다:" -#: src/exercises/day-4/afternoon.md:6 -msgid "* Call your AIDL service with a client written in Rust." -msgstr "* 당신의 AIDL서비스를 러스트 클라이언트에서 호출해봅니다." - -#: src/exercises/day-4/afternoon.md:8 -msgid "* Move a function from your project to Rust and call it." -msgstr "* 당신의 프로젝트의 함수를 러스트로 옮기고 호출해봅니다." +#: src/exercises/day-4/android.md:6 +msgid "" +"* Call your AIDL service with a client written in Rust.\n" +"\n" +"* Move a function from your project to Rust and call it." +msgstr "" +"* 당신의 AIDL서비스를 러스트 클라이언트에서 호출해봅니다.\n" +"\n" +"* 당신의 프로젝트의 함수를 러스트로 옮기고 호출해봅니다." -#: src/exercises/day-4/afternoon.md:12 +#: src/exercises/day-4/android.md:12 msgid "" "No solution is provided here since this is open-ended: it relies on someone in\n" "the class having a piece of code which you can turn in to Rust on the fly." @@ -13371,16 +12077,9 @@ msgstr "## 배열과 `for`반복문" #: src/exercises/day-1/solutions-morning.md:5 msgid "([back to exercise](for-loops.md))" -msgstr "([연습문제로 돌아가기](for-loops.md))" +msgstr "" #: src/exercises/day-1/solutions-morning.md:7 -#: src/exercises/day-1/solutions-afternoon.md:7 -#: src/exercises/day-2/solutions-morning.md:7 -#: src/exercises/day-2/solutions-afternoon.md:7 -#: src/exercises/day-2/solutions-afternoon.md:102 -#: src/exercises/day-3/solutions-morning.md:7 -#: src/exercises/day-3/solutions-afternoon.md:7 -#: src/exercises/day-4/solutions-morning.md:7 msgid "" "```rust\n" "// Copyright 2022 Google LLC\n" @@ -13395,11 +12094,8 @@ msgid "" "// 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." -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:22 -msgid "" +"// limitations under the License.\n" +"\n" "// ANCHOR: transpose\n" "fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" " // ANCHOR_END: transpose\n" @@ -13410,22 +12106,16 @@ msgid "" " }\n" " }\n" " return result;\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:34 -msgid "" +"}\n" +"\n" "// ANCHOR: pretty_print\n" "fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" " // ANCHOR_END: pretty_print\n" " for row in matrix {\n" " println!(\"{row:?}\");\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:42 -msgid "" +"}\n" +"\n" "// ANCHOR: tests\n" "#[test]\n" "fn test_transpose() {\n" @@ -13444,36 +12134,29 @@ msgid "" " ]\n" " );\n" "}\n" -"// ANCHOR_END: tests" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:62 -msgid "" +"// ANCHOR_END: tests\n" +"\n" "// ANCHOR: main\n" "fn main() {\n" " let matrix = [\n" " [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" " [201, 202, 203],\n" " [301, 302, 303],\n" -" ];" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:73 -msgid "" +" ];\n" +"\n" +" println!(\"matrix:\");\n" +" pretty_print(&matrix);\n" +"\n" " let transposed = transpose(matrix);\n" " println!(\"transposed:\");\n" " pretty_print(&transposed);\n" "}\n" -"```\n" -"### Bonus question" +"```" msgstr "" -" let transposed = transpose(matrix);\n" -" println!(\"transposed:\");\n" -" pretty_print(&transposed);\n" -"}\n" -"```\n" -"\n" -"### 보너스 문제" + +#: src/exercises/day-1/solutions-morning.md:78 +msgid "### Bonus question" +msgstr "### 보너스 문제" #: src/exercises/day-1/solutions-morning.md:80 msgid "It requires more advanced concepts. It might seem that we could use a slice-of-slices (`&[&[i32]]`) as the input type to transpose and thus make our function handle any size of matrix. However, this quickly breaks down: the return type cannot be `&[&[i32]]` since it needs to own the data you return." @@ -13491,11 +12174,8 @@ msgstr "트레잇나 제네릭을 다루고 나면 [`std::convert::AsRef`][1] msgid "" "```rust\n" "use std::convert::AsRef;\n" -"use std::fmt::Debug;" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:90 -msgid "" +"use std::fmt::Debug;\n" +"\n" "fn pretty_print(matrix: Matrix)\n" "where\n" " T: Debug,\n" @@ -13507,11 +12187,8 @@ msgid "" " for row in matrix.as_ref() {\n" " println!(\"{:?}\", row.as_ref());\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-morning.md:103 -msgid "" +"}\n" +"\n" "fn main() {\n" " // &[&[i32]]\n" " pretty_print(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" @@ -13527,10 +12204,6 @@ msgstr "" msgid "In addition, the type itself would not enforce that the child slices are of the same length, so such variable could contain an invalid matrix." msgstr "또한, 슬라이스 타입은 길이를 포함하지 않기 때문에 한 단계 아래의 슬라이스들이 같은 길이임을 보장할 수 없습니다. 때문에 슬라이스 타입의 변수에는 잘못된 행렬이 전달될 수 있습니다." -#: src/exercises/day-1/solutions-morning.md:115 -msgid "[1]: https://doc.rust-lang.org/std/convert/trait.AsRef.html" -msgstr "" - #: src/exercises/day-1/solutions-afternoon.md:1 msgid "# Day 1 Afternoon Exercises" msgstr "# 1일차 오후 연습문제" @@ -13543,37 +12216,58 @@ msgstr "## 도서관 설계" msgid "([back to exercise](book-library.md))" msgstr "" -#: src/exercises/day-1/solutions-afternoon.md:22 +#: src/exercises/day-1/solutions-afternoon.md:7 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: setup\n" "struct Library {\n" " books: Vec,\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:42 -msgid "" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" "// 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" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:50 -msgid "" +"// ANCHOR_END: setup\n" +"\n" "// ANCHOR: Library_new\n" "impl Library {\n" " fn new() -> Library {\n" " // ANCHOR_END: Library_new\n" " Library { books: Vec::new() }\n" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:57 -msgid "" +" }\n" +"\n" " // ANCHOR: Library_len\n" " //fn len(self) -> usize {\n" " // unimplemented!()\n" @@ -13581,11 +12275,8 @@ msgid "" " // ANCHOR_END: Library_len\n" " fn len(&self) -> usize {\n" " self.books.len()\n" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:66 -msgid "" +" }\n" +"\n" " // ANCHOR: Library_is_empty\n" " //fn is_empty(self) -> bool {\n" " // unimplemented!()\n" @@ -13593,11 +12284,8 @@ msgid "" " // ANCHOR_END: Library_is_empty\n" " fn is_empty(&self) -> bool {\n" " self.books.is_empty()\n" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:75 -msgid "" +" }\n" +"\n" " // ANCHOR: Library_add_book\n" " //fn add_book(self, book: Book) {\n" " // unimplemented!()\n" @@ -13605,11 +12293,8 @@ msgid "" " // ANCHOR_END: Library_add_book\n" " fn add_book(&mut self, book: Book) {\n" " self.books.push(book)\n" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:84 -msgid "" +" }\n" +"\n" " // ANCHOR: Library_print_books\n" " //fn print_books(self) {\n" " // unimplemented!()\n" @@ -13619,11 +12304,8 @@ msgid "" " for book in &self.books {\n" " println!(\"{}\", book);\n" " }\n" -" }" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:95 -msgid "" +" }\n" +"\n" " // ANCHOR: Library_oldest_book\n" " //fn oldest_book(self) -> Option<&Book> {\n" " // unimplemented!()\n" @@ -13632,26 +12314,18 @@ msgid "" " fn oldest_book(&self) -> Option<&Book> {\n" " self.books.iter().min_by_key(|book| book.year)\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:105 -msgid "" +"}\n" +"\n" "// ANCHOR: main\n" "// This shows the desired behavior. Uncomment the code below and\n" "// implement the missing methods. You will need to update the\n" "// method signatures, including the \"self\" parameter! You may\n" "// also need to update the variable bindings within main.\n" "fn main() {\n" -" let library = Library::new();" -msgstr "" -"// 아래 소스 주석을 제거하고 누락된 메서드를 구현하세요\n" -"// 미구현 메서드도 존재하므로 메서드 시그니처를 업데이트 하세요(self 포함)\n" -"fn main() {\n" -" let library = Library::new();" - -#: src/exercises/day-1/solutions-afternoon.md:115 -msgid "" +" 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" @@ -13669,44 +12343,29 @@ msgid "" " println!(\"{book}\");\n" " }\n" "}\n" -"// ANCHOR_END: main" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:134 -msgid "" +"// ANCHOR_END: main\n" +"\n" "#[test]\n" "fn test_library_len() {\n" " let mut library = Library::new();\n" " assert_eq!(library.len(), 0);\n" -" assert!(library.is_empty());" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:140 -msgid "" +" assert!(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" " assert_eq!(library.len(), 2);\n" " assert!(!library.is_empty());\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:146 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_library_is_empty() {\n" " let mut library = Library::new();\n" -" assert!(library.is_empty());" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:151 -msgid "" +" assert!(library.is_empty());\n" +"\n" " library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" " assert!(!library.is_empty());\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:155 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_library_print_books() {\n" " let mut library = Library::new();\n" @@ -13715,28 +12374,19 @@ msgid "" " // We could try and capture stdout, but let us just call the\n" " // method to start with.\n" " library.print_books();\n" -"}" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:165 -msgid "" +"}\n" +"\n" "#[test]\n" "fn test_library_oldest_book() {\n" " let mut library = Library::new();\n" -" assert!(library.oldest_book().is_none());" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:170 -msgid "" +" assert!(library.oldest_book().is_none());\n" +"\n" " library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" " assert_eq!(\n" " library.oldest_book().map(|b| b.title.as_str()),\n" " Some(\"Lord of the Rings\")\n" -" );" -msgstr "" - -#: src/exercises/day-1/solutions-afternoon.md:176 -msgid "" +" );\n" +"\n" " library.add_book(Book::new(\"Alice's Adventures in Wonderland\", 1865));\n" " assert_eq!(\n" " library.oldest_book().map(|b| b.title.as_str()),\n" @@ -13758,120 +12408,99 @@ msgstr "## 점과 다각형" msgid "([back to exercise](points-polygons.md))" msgstr "" -#: src/exercises/day-2/solutions-morning.md:22 +#: src/exercises/day-2/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" "#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" "// ANCHOR: Point\n" "pub struct Point {\n" " // ANCHOR_END: Point\n" " x: i32,\n" " y: i32,\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:30 -msgid "" +"}\n" +"\n" "// ANCHOR: Point-impl\n" "impl Point {\n" " // ANCHOR_END: Point-impl\n" " pub fn new(x: i32, y: i32) -> Point {\n" " Point { x, y }\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:37 -msgid "" -" pub fn magnitude(self) -> f64 {\n" +" }\n" +"\n" +" pub fn magnitude(self) -> f64 {\n" " f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:41 -msgid "" +" }\n" +"\n" " pub fn dist(self, other: Point) -> f64 {\n" " (self - other).magnitude()\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:49 -msgid "" +"}\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" " fn add(self, other: Self) -> Self::Output {\n" " Self {\n" " x: self.x + other.x,\n" " y: self.y + other.y,\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:57 -msgid "" +"}\n" +"\n" "impl std::ops::Sub for Point {\n" -" type Output = Self;" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:60 -msgid "" +" type Output = Self;\n" +"\n" " fn sub(self, other: Self) -> Self::Output {\n" " Self {\n" " x: self.x - other.x,\n" " y: self.y - other.y,\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:68 -msgid "" +"}\n" +"\n" "// ANCHOR: Polygon\n" "pub struct Polygon {\n" " // ANCHOR_END: Polygon\n" " points: Vec,\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:74 -msgid "" +"}\n" +"\n" "// ANCHOR: Polygon-impl\n" "impl Polygon {\n" " // ANCHOR_END: Polygon-impl\n" " pub fn new() -> Polygon {\n" " Polygon { points: Vec::new() }\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:81 -msgid "" +" }\n" +"\n" " pub fn add_point(&mut self, point: Point) {\n" " self.points.push(point);\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:85 -msgid "" +" }\n" +"\n" " pub fn left_most_point(&self) -> Option {\n" " self.points.iter().min_by_key(|p| p.x).copied()\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:89 -msgid "" +" }\n" +"\n" " pub fn iter(&self) -> impl Iterator {\n" " self.points.iter()\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:93 -msgid "" +" }\n" +"\n" " pub fn length(&self) -> f64 {\n" " if self.points.is_empty() {\n" " return 0.0;\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:98 -msgid "" +" }\n" +"\n" " let mut result = 0.0;\n" " let mut last_point = self.points[0];\n" " for point in &self.points[1..] {\n" @@ -13881,74 +12510,50 @@ msgid "" " result += last_point.dist(self.points[0]);\n" " result\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:109 -msgid "" +"}\n" +"\n" "// ANCHOR: Circle\n" "pub struct Circle {\n" " // ANCHOR_END: Circle\n" " center: Point,\n" " radius: i32,\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:116 -msgid "" +"}\n" +"\n" "// ANCHOR: Circle-impl\n" "impl Circle {\n" " // ANCHOR_END: Circle-impl\n" " pub fn new(center: Point, radius: i32) -> Circle {\n" " Circle { center, radius }\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:123 -msgid "" +" }\n" +"\n" " pub fn circumference(&self) -> f64 {\n" " 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:127 -msgid "" +" }\n" +"\n" " pub fn dist(&self, other: &Self) -> f64 {\n" " self.center.dist(other.center)\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:132 -msgid "" +"}\n" +"\n" "// ANCHOR: Shape\n" "pub enum Shape {\n" " Polygon(Polygon),\n" " Circle(Circle),\n" "}\n" -"// ANCHOR_END: Shape" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:139 -msgid "" +"// ANCHOR_END: Shape\n" +"\n" "impl From for Shape {\n" " fn from(poly: Polygon) -> Self {\n" " Shape::Polygon(poly)\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:145 -msgid "" +"}\n" +"\n" "impl From for Shape {\n" " fn from(circle: Circle) -> Self {\n" " Shape::Circle(circle)\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:151 -msgid "" +"}\n" +"\n" "impl Shape {\n" " pub fn perimeter(&self) -> f64 {\n" " match self {\n" @@ -13956,19 +12561,61 @@ msgid "" " Shape::Circle(circle) => circle.circumference(),\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:160 -msgid "" +"}\n" +"\n" "// ANCHOR: unit-tests\n" "#[cfg(test)]\n" "mod tests {\n" -" use super::*;" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:213 -msgid "" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" " #[test]\n" " fn test_shape_perimeters() {\n" " let mut poly = Polygon::new();\n" @@ -13987,12 +12634,8 @@ msgid "" " assert_eq!(perimeters, vec![15.48, 31.42]);\n" " }\n" "}\n" -"// ANCHOR_END: unit-tests" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:233 -#: src/exercises/day-2/solutions-afternoon.md:174 -msgid "" +"// ANCHOR_END: unit-tests\n" +"\n" "fn main() {}\n" "```" msgstr "" @@ -14009,8 +12652,23 @@ msgstr "## 룬 알고리즘" msgid "([back to exercise](luhn.md))" msgstr "" -#: src/exercises/day-2/solutions-afternoon.md:22 +#: src/exercises/day-2/solutions-afternoon.md:7 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: luhn\n" "pub fn luhn(cc_number: &str) -> bool {\n" " // ANCHOR_END: luhn\n" @@ -14029,24 +12687,15 @@ msgid "" " }\n" " None => return false,\n" " }\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:42 -msgid "" +" }\n" +"\n" " if digits_seen < 2 {\n" " return false;\n" -" }" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:46 -msgid "" +" }\n" +"\n" " sum % 10 == 0\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:49 -msgid "" +"}\n" +"\n" "fn main() {\n" " let cc_number = \"1234 5678 1234 5670\";\n" " println!(\n" @@ -14054,20 +12703,39 @@ msgid "" " cc_number,\n" " if luhn(cc_number) { \"yes\" } else { \"no\" }\n" " );\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:58 -msgid "" +"}\n" +"\n" "// ANCHOR: unit-tests\n" "#[test]\n" "fn test_non_digit_cc_number() {\n" " assert!(!luhn(\"foo\"));\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:89 -msgid "" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" "#[test]\n" "fn test_invalid_cc_number() {\n" " assert!(!luhn(\"4223 9826 4026 9299\"));\n" @@ -14086,8 +12754,23 @@ msgstr "## 문자열과 반복자" msgid "([back to exercise](strings-iterators.md))" msgstr "" -#: src/exercises/day-2/solutions-afternoon.md:117 +#: src/exercises/day-2/solutions-afternoon.md:102 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: prefix_matches\n" "pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" " // ANCHOR_END: prefix_matches\n" @@ -14095,11 +12778,8 @@ msgid "" " let request_paths = request_path\n" " .split('/')\n" " .map(|p| Some(p))\n" -" .chain(std::iter::once(None));" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:126 -msgid "" +" .chain(std::iter::once(None));\n" +"\n" " for (prefix, request_path) in prefixes.zip(request_paths) {\n" " match request_path {\n" " Some(request_path) => {\n" @@ -14111,28 +12791,45 @@ msgid "" " }\n" " }\n" " true\n" -"}" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:139 -msgid "" +"}\n" +"\n" "// ANCHOR: unit-tests\n" "#[test]\n" "fn test_matches_without_wildcard() {\n" " assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" " assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:166 -msgid "" +" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));\n" +"\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" +" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_matches_with_wildcard() {\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/bar/books\"\n" +" ));\n" +" assert!(prefix_matches(\n" +" \"/v1/publishers/*/books\",\n" +" \"/v1/publishers/foo/books/book1\"\n" +" ));\n" +"\n" " assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" " assert!(!prefix_matches(\n" " \"/v1/publishers/*/books\",\n" " \"/v1/publishers/foo/booksByAuthor\"\n" " ));\n" "}\n" -"// ANCHOR_END: unit-tests" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" msgstr "" #: src/exercises/day-3/solutions-morning.md:1 @@ -14147,20 +12844,85 @@ msgstr "## 간단한 GUI 라이브러리" msgid "([back to exercise](simple-gui.md))" msgstr "" -#: src/exercises/day-3/solutions-morning.md:22 +#: src/exercises/day-3/solutions-morning.md:7 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: setup\n" "pub trait Widget {\n" " /// Natural width of `self`.\n" -" fn width(&self) -> usize;" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:82 -msgid "// ANCHOR_END: setup" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:84 -msgid "" +" fn width(&self) -> usize;\n" +"\n" +" /// Draw the widget into a buffer.\n" +" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" +"\n" +" /// Draw the widget on standard output.\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" +" self.draw_into(&mut buffer);\n" +" println!(\"{buffer}\");\n" +" }\n" +"}\n" +"\n" +"pub struct Label {\n" +" label: String,\n" +"}\n" +"\n" +"impl Label {\n" +" fn new(label: &str) -> Label {\n" +" Label {\n" +" label: label.to_owned(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Button {\n" +" label: Label,\n" +" callback: Box,\n" +"}\n" +"\n" +"impl Button {\n" +" fn new(label: &str, callback: Box) -> Button {\n" +" Button {\n" +" label: Label::new(label),\n" +" callback,\n" +" }\n" +" }\n" +"}\n" +"\n" +"pub struct Window {\n" +" title: String,\n" +" widgets: Vec>,\n" +"}\n" +"\n" +"impl Window {\n" +" fn new(title: &str) -> Window {\n" +" Window {\n" +" title: title.to_owned(),\n" +" widgets: Vec::new(),\n" +" }\n" +" }\n" +"\n" +" fn add_widget(&mut self, widget: Box) {\n" +" self.widgets.push(widget);\n" +" }\n" +"}\n" +"\n" +"// ANCHOR_END: setup\n" +"\n" "// ANCHOR: Window-width\n" "impl Widget for Window {\n" " fn width(&self) -> usize {\n" @@ -14169,26 +12931,18 @@ msgid "" " self.title.chars().count(),\n" " self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" " )\n" -" }" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:94 -msgid "" +" }\n" +"\n" " // ANCHOR: Window-draw_into\n" " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" " // ANCHOR_END: Window-draw_into\n" " let mut inner = String::new();\n" " for widget in &self.widgets {\n" " widget.draw_into(&mut inner);\n" -" }" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:102 -msgid " let window_width = self.width();" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:104 -msgid "" +" }\n" +"\n" +" let window_width = self.width();\n" +"\n" " // TODO: after learning about error handling, you can change\n" " // draw_into to return Result<(), std::fmt::Error>. Then use\n" " // the ?-operator here instead of .unwrap().\n" @@ -14200,42 +12954,30 @@ msgid "" " }\n" " writeln!(buffer, \"+-{:- usize {\n" " // ANCHOR_END: Button-width\n" " self.label.width() + 8 // add a bit of padding\n" -" }" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:124 -msgid "" +" }\n" +"\n" " // ANCHOR: Button-draw_into\n" " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" " // ANCHOR_END: Button-draw_into\n" " let width = self.width();\n" " let mut label = String::new();\n" -" self.label.draw_into(&mut label);" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:131 -msgid "" +" self.label.draw_into(&mut label);\n" +"\n" " writeln!(buffer, \"+{:- usize {\n" @@ -14245,21 +12987,15 @@ msgid "" " .map(|line| line.chars().count())\n" " .max()\n" " .unwrap_or(0)\n" -" }" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:150 -msgid "" +" }\n" +"\n" " // ANCHOR: Label-draw_into\n" " fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" " // ANCHOR_END: Label-draw_into\n" " writeln!(buffer, \"{}\", &self.label).unwrap();\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/solutions-morning.md:157 -msgid "" +"}\n" +"\n" "// ANCHOR: main\n" "fn main() {\n" " let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" @@ -14286,25 +13022,61 @@ msgstr "## FFI래퍼" msgid "([back to exercise](safe-ffi-wrapper.md))" msgstr "" -#: src/exercises/day-3/solutions-afternoon.md:22 +#: src/exercises/day-3/solutions-afternoon.md:7 msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: ffi\n" "mod ffi {\n" -" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:53 -msgid "" +" use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort};\n" +"\n" +" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +" #[repr(C)]\n" +" pub struct DIR {\n" +" _data: [u8; 0],\n" +" _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" +" }\n" +"\n" +" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" +" #[repr(C)]\n" +" pub struct dirent {\n" +" pub d_ino: c_long,\n" +" pub d_off: c_ulong,\n" +" pub d_reclen: c_ushort,\n" +" pub d_type: c_char,\n" +" pub d_name: [c_char; 256],\n" +" }\n" +"\n" +" extern \"C\" {\n" +" pub fn opendir(s: *const c_char) -> *mut DIR;\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +" pub fn closedir(s: *mut DIR) -> c_int;\n" +" }\n" +"}\n" +"\n" +"use std::ffi::{CStr, CString, OsStr, OsString};\n" +"use std::os::unix::ffi::OsStrExt;\n" +"\n" "#[derive(Debug)]\n" "struct DirectoryIterator {\n" " path: CString,\n" " dir: *mut ffi::DIR,\n" "}\n" -"// ANCHOR_END: ffi" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:60 -msgid "" +"// ANCHOR_END: ffi\n" +"\n" "// ANCHOR: DirectoryIterator\n" "impl DirectoryIterator {\n" " fn new(path: &str) -> Result {\n" @@ -14320,11 +13092,8 @@ msgid "" " Ok(DirectoryIterator { path, dir })\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:77 -msgid "" +"}\n" +"\n" "// ANCHOR: Iterator\n" "impl Iterator for DirectoryIterator {\n" " type Item = OsString;\n" @@ -14343,11 +13112,8 @@ msgid "" " let os_str = OsStr::from_bytes(d_name.to_bytes());\n" " Some(os_str.to_owned())\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:97 -msgid "" +"}\n" +"\n" "// ANCHOR: Drop\n" "impl Drop for DirectoryIterator {\n" " fn drop(&mut self) {\n" @@ -14360,11 +13126,8 @@ msgid "" " }\n" " }\n" " }\n" -"}" -msgstr "" - -#: src/exercises/day-3/solutions-afternoon.md:111 -msgid "" +"}\n" +"\n" "// ANCHOR: main\n" "fn main() -> Result<(), String> {\n" " let iter = DirectoryIterator::new(\".\")?;\n" @@ -14387,28 +13150,39 @@ msgstr "## 식사하는 철학자들" msgid "([back to exercise](dining-philosophers.md))" msgstr "" -#: src/exercises/day-4/solutions-morning.md:22 +#: 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;\n" "use std::sync::{Arc, Mutex};\n" "use std::thread;\n" -"use std::time::Duration;" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:30 -msgid "" +"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" -"}" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:38 -msgid "" +"}\n" +"\n" "// ANCHOR: Philosopher-think\n" "impl Philosopher {\n" " fn think(&self) {\n" @@ -14416,83 +13190,59 @@ msgid "" " .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" " .unwrap();\n" " }\n" -" // ANCHOR_END: Philosopher-think" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:47 -msgid "" +" // 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();" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:54 -msgid "" +" 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" -"}" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:63 -msgid "" +"}\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);" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:67 -msgid "" +" let (tx, rx) = mpsc::sync_channel(10);\n" +"\n" " let forks = (0..PHILOSOPHERS.len())\n" " .map(|_| Arc::new(Mutex::new(Fork)))\n" -" .collect::>();" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:71 -msgid "" +" .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();" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:76 -msgid "" +" 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" -" }" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:83 -msgid "" +" }\n" +"\n" " let philosopher = Philosopher {\n" " name: PHILOSOPHERS[i].to_string(),\n" " thoughts: tx,\n" " left_fork,\n" " right_fork,\n" -" };" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:90 -msgid "" +" };\n" +"\n" " thread::spawn(move || {\n" " for _ in 0..100 {\n" " philosopher.eat();\n" " philosopher.think();\n" " }\n" " });\n" -" }" -msgstr "" - -#: src/exercises/day-4/solutions-morning.md:98 -msgid "" +" }\n" +"\n" " drop(tx);\n" " for thought in rx {\n" " println!(\"{thought}\");\n" diff --git a/po/pt-BR.po b/po/pt-BR.po index 888e2e0..0e8d136 100644 --- a/po/pt-BR.po +++ b/po/pt-BR.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Comprehensive Rust 🦀\n" "POT-Creation-Date: \n" -"PO-Revision-Date: \n" +"PO-Revision-Date: 2023-05-08 14:55+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: pt_BR\n" @@ -22,27 +22,27 @@ msgstr "Executando o Curso" #: src/SUMMARY.md:5 msgid "Course Structure" -msgstr "Estrutura do curso" +msgstr "Estrutura do Curso" #: src/SUMMARY.md:6 msgid "Keyboard Shortcuts" -msgstr "Atalhos do teclado" +msgstr "Atalhos do Teclado" #: src/SUMMARY.md:7 msgid "Using Cargo" -msgstr "Usando Cargo" +msgstr "Usando o Cargo" #: src/SUMMARY.md:8 msgid "Rust Ecosystem" -msgstr "Ecossistema de rust" +msgstr "O Ecossistema do Rust" #: src/SUMMARY.md:9 msgid "Code Samples" -msgstr "Amostras de código" +msgstr "Amostras de Código" #: src/SUMMARY.md:10 msgid "Running Cargo Locally" -msgstr "Executando Cargo Localmente" +msgstr "Executando o Cargo Localmente" #: src/SUMMARY.md:13 msgid "Day 1: Morning" @@ -62,7 +62,7 @@ msgstr "Olá Mundo!" #: src/SUMMARY.md:20 msgid "Small Example" -msgstr "Pequeno Exemplo" +msgstr "Um Pequeno Exemplo" #: src/SUMMARY.md:21 msgid "Why Rust?" @@ -70,15 +70,15 @@ msgstr "Por que Rust?" #: src/SUMMARY.md:22 msgid "Compile Time Guarantees" -msgstr "Garantias em tempo de compilação" +msgstr "Garantias em Tempo de Compilação" #: src/SUMMARY.md:23 msgid "Runtime Guarantees" -msgstr "Garantias de tempo de execução" +msgstr "Garantias em Tempo de Execução" #: src/SUMMARY.md:24 msgid "Modern Features" -msgstr "Recursos modernos" +msgstr "Recursos Modernos" #: src/SUMMARY.md:25 msgid "Basic Syntax" @@ -86,11 +86,11 @@ msgstr "Sintaxe Básica" #: src/SUMMARY.md:26 msgid "Scalar Types" -msgstr "Tipos escalares" +msgstr "Tipos Escalares" #: src/SUMMARY.md:27 msgid "Compound Types" -msgstr "Tipos de compostos" +msgstr "Tipos Compostos" #: src/SUMMARY.md:28 msgid "References" @@ -98,7 +98,7 @@ msgstr "Referências" #: src/SUMMARY.md:29 msgid "Dangling References" -msgstr "Referências pendentes" +msgstr "Referências Pendentes" #: src/SUMMARY.md:30 msgid "Slices" @@ -118,7 +118,7 @@ msgstr "Métodos" #: src/SUMMARY.md:34 msgid "Overloading" -msgstr "Sobrecargo" +msgstr "Sobrecarga" #: src/SUMMARY.md:35 src/SUMMARY.md:64 src/SUMMARY.md:88 src/SUMMARY.md:117 src/SUMMARY.md:146 src/SUMMARY.md:174 #: src/SUMMARY.md:197 src/SUMMARY.md:224 @@ -127,11 +127,11 @@ msgstr "Exercícios" #: src/SUMMARY.md:36 msgid "Implicit Conversions" -msgstr "Conversões implícitas" +msgstr "Conversões Implícitas" #: src/SUMMARY.md:37 msgid "Arrays and for Loops" -msgstr "Arrays e for Loops" +msgstr "Vetores e Laços For" #: src/SUMMARY.md:39 msgid "Day 1: Afternoon" @@ -143,7 +143,7 @@ msgstr "Variáveis" #: src/SUMMARY.md:42 msgid "Type Inference" -msgstr "Inferência de tipo" +msgstr "Inferência de Tipo" #: src/SUMMARY.md:43 msgid "static & const" @@ -151,15 +151,15 @@ msgstr "static & const" #: src/SUMMARY.md:44 msgid "Scopes and Shadowing" -msgstr "Escopos e Sombra" +msgstr "Escopos e Sobreposição" #: src/SUMMARY.md:45 msgid "Memory Management" -msgstr "Gerenciamento de memória" +msgstr "Gerenciamento de Memória" #: src/SUMMARY.md:46 msgid "Stack vs Heap" -msgstr "Pilha vs Heap" +msgstr "Stack vs Heap" #: src/SUMMARY.md:47 msgid "Stack Memory" @@ -171,15 +171,15 @@ msgstr "Gerenciamento Manual de Memória" #: src/SUMMARY.md:49 msgid "Scope-Based Memory Management" -msgstr "Gerenciamento de memória baseado em escopo" +msgstr "Gerenciamento de Memória Baseado em Escopo" #: src/SUMMARY.md:50 msgid "Garbage Collection" -msgstr "Garbage Collection (Coleta de lixo)" +msgstr "Garbage Collection (Coletor de lixo)" #: src/SUMMARY.md:51 msgid "Rust Memory Management" -msgstr "Gerenciamento de Memória Rust" +msgstr "Gerenciamento de Memória do Rust" #: src/SUMMARY.md:52 msgid "Comparison" @@ -191,23 +191,23 @@ msgstr "Ownership" #: src/SUMMARY.md:54 msgid "Move Semantics" -msgstr "Mover semântica" +msgstr "Semântica do move (mover)" #: src/SUMMARY.md:55 msgid "Moved Strings in Rust" -msgstr "Strings movidas em Rust" +msgstr "Strings Movidas em Rust" #: src/SUMMARY.md:56 msgid "Double Frees in Modern C++" -msgstr "Liberações duplas em C++ moderno" +msgstr "Liberações Duplas em C++ Moderno" #: src/SUMMARY.md:57 msgid "Moves in Function Calls" -msgstr "Movimentos em Chamadas de Função" +msgstr "Move em Chamadas de Função" #: src/SUMMARY.md:58 msgid "Copying and Cloning" -msgstr "Copiar e clonar" +msgstr "Copiar e Clonar" #: src/SUMMARY.md:59 msgid "Borrowing" @@ -219,23 +219,23 @@ msgstr "Empréstimos Compartilhados e Únicos" #: src/SUMMARY.md:61 msgid "Lifetimes" -msgstr "Tempos de vida (Lifetimes)" +msgstr "Tempos de Vida (Lifetimes)" #: src/SUMMARY.md:62 msgid "Lifetimes in Function Calls" -msgstr "Tempos de vida (Lifetimes) em chamadas de função" +msgstr "Tempos de vida (Lifetimes) em Chamadas de Função" #: src/SUMMARY.md:63 msgid "Lifetimes in Data Structures" -msgstr "Tempos de vida em estruturas de dados" +msgstr "Tempos de Vida em Estruturas de Dados" #: src/SUMMARY.md:65 msgid "Designing a Library" -msgstr "Projetando uma biblioteca" +msgstr "Projetando uma Biblioteca" #: src/SUMMARY.md:66 msgid "Iterators and Ownership" -msgstr "Iteradores e Ownership" +msgstr "Iteradores e Propriedade (Ownership)" #: src/SUMMARY.md:69 msgid "Day 2: Morning" @@ -247,19 +247,19 @@ msgstr "Structs" #: src/SUMMARY.md:75 msgid "Tuple Structs" -msgstr "Structs Tuplas" +msgstr "Structs como Tuplas" #: src/SUMMARY.md:76 msgid "Field Shorthand Syntax" -msgstr "Sintaxe abreviada de campos" +msgstr "Sintaxe Abreviada de Campos" #: src/SUMMARY.md:77 msgid "Enums" -msgstr "Enums" +msgstr "Enumerações (Enums)" #: src/SUMMARY.md:78 msgid "Variant Payloads" -msgstr "Cargos úteis variantes" +msgstr "Variantes de Carga Útil (payload)" #: src/SUMMARY.md:79 msgid "Enum Sizes" @@ -267,7 +267,7 @@ msgstr "Tamanhos de Enum" #: src/SUMMARY.md:81 msgid "Method Receiver" -msgstr "Receptor do método" +msgstr "Receptor de Método" #: src/SUMMARY.md:82 src/SUMMARY.md:157 src/SUMMARY.md:192 msgid "Example" @@ -275,7 +275,7 @@ msgstr "Exemplo" #: src/SUMMARY.md:83 msgid "Pattern Matching" -msgstr "Correspondência de padrões" +msgstr "Correspondência de Padrões" #: src/SUMMARY.md:84 msgid "Destructuring Enums" @@ -283,23 +283,23 @@ msgstr "Desestruturando Enums" #: src/SUMMARY.md:85 msgid "Destructuring Structs" -msgstr "Structs Destruidoras" +msgstr "Desestruturando Structs" #: src/SUMMARY.md:86 msgid "Destructuring Arrays" -msgstr "Desestruturando Arrays" +msgstr "Desestruturando Vetores" #: src/SUMMARY.md:87 msgid "Match Guards" -msgstr "Guardas de Match" +msgstr "Guardas de Correspondência (match)" #: src/SUMMARY.md:89 msgid "Health Statistics" -msgstr "Estatísticas de saúde" +msgstr "Estatísticas de Saúde" #: src/SUMMARY.md:90 msgid "Points and Polygons" -msgstr "Points e polígonos" +msgstr "Pontos e Polígonos" #: src/SUMMARY.md:92 msgid "Day 2: Afternoon" @@ -307,7 +307,7 @@ msgstr "Dia 2: Tarde" #: src/SUMMARY.md:94 msgid "Control Flow" -msgstr "Controle de fluxo" +msgstr "Controle de Fluxo" #: src/SUMMARY.md:95 msgid "Blocks" @@ -315,31 +315,31 @@ msgstr "Blocos" #: src/SUMMARY.md:96 msgid "if expressions" -msgstr "if expressões" +msgstr "Expressões Se (if)" #: src/SUMMARY.md:97 msgid "if let expressions" -msgstr "if let expressões" +msgstr "Expressões Se (if let)" #: src/SUMMARY.md:98 msgid "while expressions" -msgstr "enquanto expressões" +msgstr "Expressões Enquanto (while)" #: src/SUMMARY.md:99 msgid "while let expressions" -msgstr "while let expressões" +msgstr "Expressões Enquanto (while let)" #: src/SUMMARY.md:100 msgid "for expressions" -msgstr "for expressões" +msgstr "Expressões Para (for)" #: src/SUMMARY.md:101 msgid "loop expressions" -msgstr "expressões de loop" +msgstr "Expressões de Laço (loop)" #: src/SUMMARY.md:102 msgid "match expressions" -msgstr "expressões de match" +msgstr "Expressões de Correspondência (match)" #: src/SUMMARY.md:103 msgid "break & continue" @@ -347,7 +347,7 @@ msgstr "break e continue" #: src/SUMMARY.md:104 msgid "Standard Library" -msgstr "Biblioteca padrão" +msgstr "Biblioteca Padrão" #: src/SUMMARY.md:105 msgid "Option and Result" @@ -371,7 +371,7 @@ msgstr "Box" #: src/SUMMARY.md:110 msgid "Recursive Data Types" -msgstr "Tipos de dados recursivos" +msgstr "Tipos de Dados Recursivos" #: src/SUMMARY.md:111 msgid "Niche Optimization" @@ -387,7 +387,7 @@ msgstr "Módulos" #: src/SUMMARY.md:114 msgid "Visibility" -msgstr "Visibilage" +msgstr "Visibilidade" #: src/SUMMARY.md:115 msgid "Paths" @@ -395,15 +395,15 @@ msgstr "Caminhos" #: src/SUMMARY.md:116 msgid "Filesystem Hierarchy" -msgstr "Hierarquia do sistema de arquivos" +msgstr "Hierarquia do Sistema de Arquivos" #: src/SUMMARY.md:118 msgid "Luhn Algorithm" -msgstr "Algoritmo de LuhnName" +msgstr "Algoritmo de Luhn" #: src/SUMMARY.md:119 msgid "Strings and Iterators" -msgstr "Strings e iteradores" +msgstr "Strings e Iteradores" #: src/SUMMARY.md:122 msgid "Day 3: Morning" @@ -415,15 +415,15 @@ msgstr "Traits" #: src/SUMMARY.md:128 msgid "Deriving Traits" -msgstr "Traits derivados" +msgstr "Traits Derivados" #: src/SUMMARY.md:129 msgid "Default Methods" -msgstr "Métodos padrão" +msgstr "Métodos Padrão" #: src/SUMMARY.md:130 msgid "Important Traits" -msgstr "Traits importantes" +msgstr "Traits Importantes" #: src/SUMMARY.md:131 msgid "Iterator" @@ -451,15 +451,15 @@ msgstr "Drop" #: src/SUMMARY.md:137 msgid "Default" -msgstr "Métodos padrão" +msgstr "Default" #: src/SUMMARY.md:138 msgid "Generics" -msgstr "Genéricos" +msgstr "Generics" #: src/SUMMARY.md:139 msgid "Generic Data Types" -msgstr "Tipos de dados genéricos" +msgstr "Tipos de Dados Genéricos" #: src/SUMMARY.md:140 msgid "Generic Methods" @@ -471,11 +471,11 @@ msgstr "Limites de trait" #: src/SUMMARY.md:142 msgid "impl Trait" -msgstr "impl Trait" +msgstr "Trait impl" #: src/SUMMARY.md:143 msgid "Closures" -msgstr "fechamentos" +msgstr "Closures" #: src/SUMMARY.md:144 msgid "Monomorphization" @@ -483,11 +483,11 @@ msgstr "Monomorfização" #: src/SUMMARY.md:145 msgid "Trait Objects" -msgstr "Objetos de Trait" +msgstr "Objetos Trait" #: src/SUMMARY.md:147 msgid "A Simple GUI Library" -msgstr "Uma biblioteca GUI simples" +msgstr "Uma Biblioteca GUI Simples" #: src/SUMMARY.md:149 msgid "Day 3: Afternoon" @@ -495,23 +495,23 @@ msgstr "Dia 3: Tarde" #: src/SUMMARY.md:151 msgid "Error Handling" -msgstr "Manipulação de erros" +msgstr "Manipulação de Erros" #: src/SUMMARY.md:152 msgid "Panics" -msgstr "Pânico" +msgstr "Panics (Pânico)" #: src/SUMMARY.md:153 msgid "Catching Stack Unwinding" -msgstr "Capturando pilha desenrolando" +msgstr "Capturando o Desenrolar da Pilha" #: src/SUMMARY.md:154 msgid "Structured Error Handling" -msgstr "Tratamento de Erros Estruturado" +msgstr "Tratamento Estruturado de Erros" #: src/SUMMARY.md:155 msgid "Propagating Errors with ?" -msgstr "Propagando erros com ?" +msgstr "Propagando Erros com ?" #: src/SUMMARY.md:156 msgid "Converting Error Types" @@ -519,11 +519,11 @@ msgstr "Convertendo Tipos de Erro" #: src/SUMMARY.md:158 msgid "Deriving Error Enums" -msgstr "Derivando Enums de erro" +msgstr "Derivando Enums de Erro" #: src/SUMMARY.md:159 msgid "Dynamic Error Types" -msgstr "Tipos de erros dinâmicos" +msgstr "Tipos de Erros Dinâmicos" #: src/SUMMARY.md:160 msgid "Adding Context to Errors" @@ -531,39 +531,39 @@ msgstr "Adicionando Contexto aos Erros" #: src/SUMMARY.md:161 msgid "Testing" -msgstr "tests" +msgstr "Testando" #: src/SUMMARY.md:162 msgid "Unit Tests" -msgstr "tests de unage" +msgstr "Testes Unitários" #: src/SUMMARY.md:163 msgid "Test Modules" -msgstr "Módulos de teste" +msgstr "Módulos de Teste" #: src/SUMMARY.md:164 msgid "Documentation Tests" -msgstr "tests de Documentação" +msgstr "Testes de Documentação" #: src/SUMMARY.md:165 msgid "Integration Tests" -msgstr "tests de Integração" +msgstr "Testes de Integração" #: src/SUMMARY.md:166 msgid "Unsafe Rust" -msgstr "Unsafe Rust" +msgstr "Rust Inseguro (unsafe)" #: src/SUMMARY.md:167 msgid "Dereferencing Raw Pointers" -msgstr "Desreferenciando ponteiros brutos" +msgstr "Desreferenciando Ponteiros Brutos" #: src/SUMMARY.md:168 msgid "Mutable Static Variables" -msgstr "Variáveis estáticas mutáveis" +msgstr "Variáveis Estáticas Mutáveis" #: src/SUMMARY.md:169 msgid "Unions" -msgstr "Sindicatos" +msgstr "Uniões" #: src/SUMMARY.md:170 msgid "Calling Unsafe Functions" @@ -591,27 +591,27 @@ msgstr "Dia 4: Manhã" #: src/SUMMARY.md:183 msgid "Concurrency" -msgstr "Simultaneage" +msgstr "Concorrência" #: src/SUMMARY.md:184 msgid "Threads" -msgstr "Tópicos" +msgstr "Threads" #: src/SUMMARY.md:185 msgid "Scoped Threads" -msgstr "Tópicos com Escopo" +msgstr "Threads com Escopo" #: src/SUMMARY.md:186 msgid "Channels" -msgstr "Channels" +msgstr "Canais (channels)" #: src/SUMMARY.md:187 msgid "Unbounded Channels" -msgstr "Channels Ilimitados" +msgstr "Canais Ilimitados" #: src/SUMMARY.md:188 msgid "Bounded Channels" -msgstr "Channels Delimitados" +msgstr "Canais Delimitados" #: src/SUMMARY.md:189 msgid "Shared State" @@ -643,11 +643,11 @@ msgstr "Exemplos" #: src/SUMMARY.md:198 msgid "Dining Philosophers" -msgstr "Jantar com philosophers" +msgstr "Filósofos Jantando" #: src/SUMMARY.md:199 msgid "Multi-threaded Link Checker" -msgstr "Verificador de links multiencadeados" +msgstr "Verificador de Links Multi-Threads" #: src/SUMMARY.md:201 msgid "Day 4: Afternoon" @@ -663,7 +663,7 @@ msgstr "Configurar" #: src/SUMMARY.md:207 msgid "Build Rules" -msgstr "Regras de construção" +msgstr "Regras de Construção" #: src/SUMMARY.md:208 msgid "Binary" @@ -703,11 +703,11 @@ msgstr "Alterando API" #: src/SUMMARY.md:217 msgid "Logging" -msgstr "Exploração madeireira" +msgstr "Gerando Registros (Log)" #: src/SUMMARY.md:218 msgid "Interoperability" -msgstr "Interoperabilage" +msgstr "Interoperabilidade" #: src/SUMMARY.md:219 msgid "With C" @@ -719,7 +719,7 @@ msgstr "Chamando C com Bindgen" #: src/SUMMARY.md:221 msgid "Calling Rust from C" -msgstr "Chamando Rust de C" +msgstr "Chamando Rust do C" #: src/SUMMARY.md:222 msgid "With C++" @@ -788,7 +788,7 @@ msgid "" "and error handling. It also includes Android-specific content on the last day." msgstr "" "Este é um curso de Rust de quatro dias desenvolvido pela equipe do Android. O curso abrange\n" -"o espectro completo de Rust, desde a sintaxe básica até tópicos avançados como 'generics'\n" +"o espectro completo do Rust, desde a sintaxe básica até tópicos avançados como 'generics'\n" "e tratamento de erros. Também inclui conteúdo específico para Android no último dia." #: src/welcome.md:7 @@ -805,7 +805,7 @@ msgid "" "* Enable you to modify existing programs and write new programs in Rust.\n" "* Show you common Rust idioms." msgstr "" -"* Dar a você uma compreensão abrangente da sintaxe e linguagem de Rust.\n" +"* Dar a você uma compreensão abrangente da linguagem e da sintaxe de Rust.\n" "* Permitir que você modifique programas existentes e escreva novos programas em Rust.\n" "* Demonstrar expressões idiomáticas comuns de Rust." @@ -955,7 +955,7 @@ msgstr "" #: src/running-the-course.md:1 msgid "# Running the Course" -msgstr "# Executando o Curso" +msgstr "# Executando o curso" #: src/running-the-course.md:3 src/running-the-course/course-structure.md:3 msgid "> This page is for the course instructor." @@ -1036,7 +1036,7 @@ msgstr "" "5. Deixe as pessoas resolverem os exercícios sozinhas ou em pequenos grupos. Tenha certeza de\n" " perguntar às pessoas se elas estão com dificuldades ou se há algo em que você possa ajudar. Quando\n" " você vê que várias pessoas têm o mesmo problema, chame a turma\n" -" e oferecer uma solução, por exemplo, mostrando às pessoas onde encontrar as informações relevantes\n" +" e ofereça uma solução, por exemplo, mostrando às pessoas onde encontrar as informações relevantes\n" " na biblioteca padrão." #: src/running-the-course.md:38 @@ -1110,8 +1110,8 @@ msgid "" "* Day 4: Concurrency in Rust and interoperability with other languages" msgstr "" "* Dia 1: Rust básico, ownership e verificador de empréstimo.\n" -"* Dia 2: Tipos de dados compostos, correspondência de padrões, a biblioteca padrão.\n" -"* Dia 3: Traits e generics, tratamento de erros, testes, Rust inseguro.\n" +"* Dia 2: Tipos de dados compostos, correspondência de padrões e a biblioteca padrão.\n" +"* Dia 3: Traits e generics, tratamento de erros, testes e Rust inseguro.\n" "* Dia 4: Concorrência em Rust e interoperabilidade com outras linguagens" #: src/running-the-course/course-structure.md:12 @@ -1158,7 +1158,7 @@ msgstr "" #: src/cargo.md:1 msgid "# Using Cargo" -msgstr "# Usando cargo" +msgstr "# Usando o Cargo" #: src/cargo.md:3 msgid "" @@ -1232,7 +1232,7 @@ msgid "" "you prefer them, you can install the [Rust Plugin][5]. Please take note that as of January 2023 debugging only works on the " "CLion version of the JetBrains IDEA suite." msgstr "" -"Algumas Persons também gostam de usar a família de IDEs [JetBrains][4], que fazem suas próprias análises, mas têm suas " +"Algumas pessoas também gostam de usar a família de IDEs [JetBrains][4], que fazem suas próprias análises, mas têm suas " "próprias vantagens e desvantagens. Se você preferir, pode instalar o [Plugin Rust][5]. Observe que, a partir de Janeiro de " "2023, a depuração funciona apenas na versão CLion do pacote JetBrains IDEA." @@ -1253,7 +1253,7 @@ msgstr "" #: src/cargo/rust-ecosystem.md:1 msgid "# The Rust Ecosystem" -msgstr "# O ecossistema da rust" +msgstr "# O ecossistema do Rust" #: src/cargo/rust-ecosystem.md:3 msgid "The Rust ecosystem consists of a number of tools, of which the main ones are:" @@ -1289,9 +1289,9 @@ msgid "" msgstr "" "* `rustup`: o instalador e atualizador do toolchain do Rust. Esta ferramenta é utilizada para\n" " instalar e atualizar o `rustc` e o `cargo` quando novas versões do Rust forem lançadas.\n" -" Além disso, `rustup` também pode baixar documentação da biblioteca\n" +" Além disso, `rustup` também pode baixar a documentação da biblioteca\n" " padrão. Você pode ter várias versões do Rust instaladas ao mesmo tempo e `rustup`\n" -" permitirá que você alterne entre eles conforme necessário." +" permitirá que você alterne entre elas conforme necessário." #: 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/error-handling/try-operator.md:50 @@ -1374,7 +1374,7 @@ msgstr "" "recursos avançados, incluindo, entre outros:\n" " * Estrutura do projeto/pacote\n" " * [workspaces]\n" -" * Gerenciamento de Dependências de desenvolvimento e dependências de tempo de execução/cache\n" +" * Gerenciamento de dependências de desenvolvimento e dependências de tempo de execução/cache\n" " * [scripts de compilação]\n" " * [instalação global]\n" " * Também é extensível com plugins de subcomando (como [cargo clippy]).\n" @@ -1426,7 +1426,7 @@ msgid "" msgstr "" "A instalação do Cargo ainda assim é incentivada: será mais fácil para você fazer os\n" "exercícios. No último dia, faremos um exercício maior que mostra como\n" -"trabalhar com dependências e para isso você precisa do Cargo." +"trabalhar com dependências e para isso você precisará do Cargo." #: src/cargo/code-samples.md:11 msgid "The code blocks in this course are fully interactive:" @@ -1467,7 +1467,7 @@ msgid "" "* The embedded playgrounds cannot execute unit tests. Copy-paste the\n" " code and open it in the real Playground to demonstrate unit tests." msgstr "" -"* Os playgrounds incorporados não podem executar testes de unitários. Copie e cole o\n" +"* Os playgrounds incorporados não podem executar testes unitários. Copie e cole o\n" " código e abra-o no Playground real para demonstrar os testes unitários." #: src/cargo/code-samples.md:30 @@ -1520,7 +1520,7 @@ msgid "" "of the examples in this training:" msgstr "" "Com isso finalizado, siga estas etapas para criar um binário Rust a partir de um\n" -"dos exemplos neste treinamento:" +"dos exemplos deste treinamento:" #: src/cargo/running-locally.md:18 msgid "1. Click the \"Copy to clipboard\" button on the example you want to copy." @@ -1606,7 +1606,7 @@ msgid "" msgstr "" "7. Você pode adicionar dependências ao seu projeto editando `Cargo.toml`. Quando você\n" " executar os comandos `cargo`, ele irá baixar e compilar automaticamente\n" -" dependências para você." +" as dependências para você." #: src/cargo/running-locally.md:66 msgid "[1]: https://doc.rust-lang.org/book/ch01-01-installation.html" @@ -1674,13 +1674,13 @@ msgstr "" "* Eles devem fazer perguntas na hora, não as guarde para o fim.\n" "* A aula é para ser interativa e as discussões são muito encorajadas!\n" " * Como instrutor, você deve tentar manter as discussões relevantes, ou seja,\n" -" mantenha o que é relacionado a como Rust faz as coisas versus alguma outra linguagem. Pode ser\n" +" mantenha o que é relacionado a como o Rust faz as coisas versus alguma outra linguagem. Pode ser\n" " difícil encontrar o equilíbrio certo, mas erra ao permitir discussões\n" " uma vez que envolvem as pessoas muito mais do que uma comunicação unidirecional.\n" "* As perguntas provavelmente parecerão que estamos falando sobre as coisas antes dos slides.\n" " * Isso está perfeitamente OK! A repetição é uma parte importante do aprendizado. Lembre-se\n" " que os slides são apenas um suporte e você está livre para ignorá-los quando\n" -" Quiser." +" quiser." #: src/welcome-day-1.md:29 msgid "" @@ -1776,13 +1776,13 @@ msgstr "[1]: https://doc.rust-lang.org/std/sync/struct.Arc.html" #: src/hello-world.md:1 msgid "# Hello World!" -msgstr "# Olá Mundo!" +msgstr "# Olá mundo!" #: src/hello-world.md:3 msgid "" "Let us jump into the simplest possible Rust program, a classic Hello World\n" "program:" -msgstr "Vamos pular para o programa em Rust mais simples possível, um clássico Hello World:" +msgstr "Vamos pular para o programa em Rust mais simples possível, o clássico \"Olá Mundo\":" #: src/hello-world.md:6 msgid "" @@ -1792,6 +1792,11 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"fn main() {\n" +" println!(\"Olá 🌍!\");\n" +"}\n" +"```" #: src/hello-world.md:12 msgid "What you see:" @@ -1839,11 +1844,11 @@ msgid "" " arguments (no function [overloading](basic-syntax/functions-interlude.md))." msgstr "" "* Rust usa macros para situações em que você deseja ter um número variável de\n" -" argumentos (sem [overloading](sintaxe-básica/funções-interlude.md) de funções)." +" argumentos (sem [overloading](basic-syntax/functions-interlude.md) de funções)." #: src/hello-world/small-example.md:1 msgid "# Small Example" -msgstr "# Pequeno Exemplo" +msgstr "# Um pequeno exemplo" #: src/hello-world/small-example.md:3 msgid "Here is a small example program in Rust:" @@ -1870,7 +1875,7 @@ msgstr "" "```rust,editable\n" "fn main() { // Ponto de entrada do programa\n" " let mut x: i32 = 6; // Atribuição de uma variável mutável\n" -" print!(\"{x}\"); // Macro para escrever na tela, como printf\n" +" print!(\"{x}\"); // Macro para escrever na tela, como printf\n" " while x != 1 { // Sem parênteses ao redor de expressões\n" " if x % 2 == 0 { // Matemática como em outras linguagens\n" " x = x / 2;\n" @@ -2002,11 +2007,11 @@ msgid "" msgstr "" "* Nenhuma variável não inicializada.\n" "* Sem vazamentos de memória (_quase_, veja as notas).\n" -"* Sem double-free.\n" -"* Sem 'user-afer-free'.\n" +"* Sem _double-free_.\n" +"* Sem _user-afer-free_'.\n" "* Sem ponteiros `NULL`.\n" "* Sem mutexes bloqueados esquecidos.\n" -"* Sem condições de corridas threads.\n" +"* Sem concorrência de dados entre _threads_.\n" "* Nenhuma invalidação de iteradores." #: src/why-rust/compile-time.md:16 @@ -2032,7 +2037,7 @@ msgstr "" " ser para obter variáveis estáticas inicializadas e dimensionadas em tempo de execução\n" "* Você pode usar [`std::mem::forget`] para fazer o compilador \"esquecer\" sobre\n" " um valor (o que significa que o destrutor nunca é executado).\n" -"* Você também pode criar acidentalmente um [referência cíclica] com `Rc` ou\n" +"* Você também pode criar acidentalmente uma [referência cíclica] com `Rc` ou\n" " `Arc`.\n" "* Na verdade, alguns considerarão preencher infinitamente uma coleção\n" " como vazamento de memória e Rust não protege disso." @@ -2068,7 +2073,7 @@ msgid "" "* Array access is bounds checked.\n" "* Integer overflow is defined." msgstr "" -"* O acesso à arrays tem limites verificados.\n" +"* O acesso à vetores tem limites verificados.\n" "* Estouro de números inteiros é definido." #: src/why-rust/runtime.md:12 @@ -2144,7 +2149,7 @@ msgid "" msgstr "" "* Abstrações de custo zero, semelhantes ao C++, significa que você não precisa 'pagar'\n" " com memória ou CPU por construções de programação de alto nível. Por exemplo,\n" -" escrever um loop usando `for` deve resultar aproximadamente nos mesmas instruções\n" +" escrever um loop usando `for` deve resultar aproximadamente nas mesmas instruções\n" " de baixo nível como ao usar a construção `.iter().fold()`." #: src/why-rust/modern.md:28 @@ -2196,7 +2201,7 @@ msgid "" " community is still working on finding the best solution --- and perhaps there\n" " isn't a single \"best solution\" for some of these things." msgstr "" -" O raciocínio por trás disso é que a funcionalidades na biblioteca padrão não podem\n" +" O raciocínio por trás disso é que as funcionalidades na biblioteca padrão não podem\n" " ser descartadas, portanto têm que ser muito estáveis. Para os exemplos acima, a comunidade\n" " Rust ainda está trabalhando para encontrar a melhor solução --- e talvez não\n" " haja uma única \"melhor solução\" para algumas dessas coisas." @@ -2241,7 +2246,7 @@ msgstr "" #: src/basic-syntax.md:1 msgid "# Basic Syntax" -msgstr "# Sintaxe Básica" +msgstr "# Sintaxe básica" #: src/basic-syntax.md:3 msgid "Much of the Rust syntax will be familiar to you from C, C++ or Java:" @@ -2279,8 +2284,8 @@ msgid "" msgstr "" "| | Tipos | Literais |\n" "|---------------------------|--------------------------------------------|-------------------------------|\n" -"| Inteiro sinalizado | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `-10`, `0`, `1_000`, `123i64` |\n" -"| Inteiro não sinalizado | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, `10u16` |\n" +"| Inteiro com sinal | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `-10`, `0`, `1_000`, `123i64` |\n" +"| Inteiro sem sinal | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, `10u16` |\n" "| Ponto flutuante | `f32`, `f64` | `3.14`, `-10.0e20`, `2f32` |\n" "| Strings | `&str` | `\"foo\"`, `r#\"\\\\\"#` |\n" "| Valores Unicode escalares | `char` | `'a'`, `'α'`, `'∞'` |\n" @@ -2316,12 +2321,12 @@ msgid "" msgstr "" "| | Tipos | Literais |\n" "|--------|-------------------------------|-----------------------------------|\n" -"| Arrays | `[T; N]` | `[20, 30, 40]`, `[0; 3]` |\n" -"| Tuplas | `()`, `(T,)`, `(T1, T2)`, ... | `()`, `('x',)`, `('x', 1.2)`, ... |" +"| Vetores | `[T; N]` | `[20, 30, 40]`, `[0; 3]` |\n" +"| Tuplas | `()`, `(T,)`, `(T1, T2)`, ... | `()`, `('x',)`, `('x', 1.2)`, ... |" #: src/basic-syntax/compound-types.md:8 msgid "Array assignment and access:" -msgstr "Atribuição e acesso a arrays:" +msgstr "Atribuição e acesso a vetores:" #: src/basic-syntax/compound-types.md:10 msgid "" @@ -2355,10 +2360,17 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let t: (i8, bool) = (7, true);\n" +" println!(\"1º índice: {}\", t.0);\n" +" println!(\"2º índice: {}\", t.1);\n" +"}\n" +"```" #: src/basic-syntax/compound-types.md:32 msgid "Arrays:" -msgstr "Arrays:" +msgstr "Vetores:" #: src/basic-syntax/compound-types.md:34 msgid "" @@ -2366,13 +2378,13 @@ msgid "" " Note that the length of the array is *part of its type*, which means that `[u8; 3]` and\n" " `[u8; 4]` are considered two different types." msgstr "" -"* Arrays possuem elementos do mesmo tipo, `T`, e comprimento, `N`, que é uma constante de tempo de compilação.\n" -" Observe que o comprimento do array é *parte de seu tipo*, o que significa que `[u8; 3]` e\n" +"* Vetores possuem elementos do mesmo tipo, `T`, e comprimento, `N`, que é uma constante de tempo de compilação.\n" +" Observe que o comprimento do vetor é *parte de seu tipo*, o que significa que `[u8; 3]` e\n" " `[u8; 4]` são considerados dois tipos diferentes." #: src/basic-syntax/compound-types.md:38 msgid "* We can use literals to assign values to arrays." -msgstr "* Podemos usar literais para atribuir valores a arrays." +msgstr "* Podemos usar literais para atribuir valores a vetores." #: src/basic-syntax/compound-types.md:40 msgid "" @@ -2388,7 +2400,7 @@ msgstr "" #: src/basic-syntax/compound-types.md:45 msgid "* Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read." -msgstr "* Adicionando `#`, por exemplo `{a:#?}`, chama um formatado de \"impressão bonita\", que pode ser mais fácil de ler." +msgstr "* Adicionando `#`, por exemplo `{a:#?}`, chama um formatador de \"impressão bonita\", que pode ser mais fácil de ler." #: src/basic-syntax/compound-types.md:47 msgid "Tuples:" @@ -2396,7 +2408,7 @@ msgstr "Tuplas:" #: src/basic-syntax/compound-types.md:49 msgid "* Like arrays, tuples have a fixed length." -msgstr "* Assim como os arrays, as tuplas têm um comprimento fixo." +msgstr "* Assim como os vetores, as tuplas têm um comprimento fixo." #: src/basic-syntax/compound-types.md:51 msgid "* Tuples group together values of different types into a compound type." @@ -2560,7 +2572,7 @@ msgstr "" #: src/basic-syntax/slices.md:26 msgid "* To easily create a slice of the full array, we can therefore use `&a[..]`." -msgstr "* Para criar facilmente uma slice do array completo, podemos usar `&a[..]`." +msgstr "* Para criar facilmente uma slice do vetor completo, podemos usar `&a[..]`." #: src/basic-syntax/slices.md:28 msgid "" @@ -2575,7 +2587,7 @@ msgid "" " you cannot do it through `a` after you created a slice, but you can read the data from both `a` and `s` safely. \n" " More details will be explained in the borrow checker section." msgstr "" -"* `s` é uma referência a uma slice de `i32`s. Observe que o tipo de `s` (`&[i32]`) não menciona mais o tamanho do array. " +"* `s` é uma referência a uma slice de `i32`. Observe que o tipo de `s` (`&[i32]`) não menciona mais o tamanho do vetor. " "Isso nos permite realizar cálculos em slices de tamanhos diferentes.\n" " \n" "* As slices sempre pegam emprestado de outro objeto. Neste exemplo, `a` deve permanecer 'vivo' (no escopo) por pelo menos " @@ -2601,6 +2613,10 @@ msgid "" " let s1: &str = \"World\";\n" " println!(\"s1: {s1}\");" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let s1: &str = \"Mundo\";\n" +" println!(\"s1: {s1}\");" #: src/basic-syntax/string-slices.md:10 msgid "" @@ -2614,6 +2630,15 @@ msgid "" "}\n" "```" msgstr "" +" let mut s2: String = String::from(\"Olá \");\n" +" println!(\"s2: {s2}\");\n" +" s2.push_str(s1);\n" +" println!(\"s2: {s2}\");\n" +" \n" +" let s3: &str = &s2[6..];\n" +" println!(\"s3: {s3}\");\n" +"}\n" +"```" #: src/basic-syntax/string-slices.md:20 msgid "Rust terminology:" @@ -2660,7 +2685,7 @@ msgid "" " \n" "" msgstr "" -"* A macro `format!()` é uma maneira conveniente de gerar uma string a partir de valores dinâmicos. Isto\n" +"* A macro `format!()` é uma maneira conveniente de gerar uma string a partir de valores dinâmicos. Ela\n" " aceita os mesmos formatadores que `println!()`.\n" " \n" "* Você pode emprestar slices `&str` de `String` via `&` e, opcionalmente, selecionar um intervalo.\n" @@ -2718,7 +2743,7 @@ msgid "" " }\n" "}" msgstr "" -"fn fizzbuzz(n: u32) -> () { // // Nenhum valor de retorno significa retornar o tipo `()`\n" +"fn fizzbuzz(n: u32) -> () { // // Nenhum valor de retorno significa retornar o tipo unitário `()`\n" " match (is_divisible_by(n, 3), is_divisible_by(n, 5)) {\n" " (true, true) => println!(\"fizzbuzz\"),\n" " (true, false) => println!(\"fizz\"),\n" @@ -2804,9 +2829,9 @@ msgid "" "}" msgstr "" "```rust,editable\n" -"struct Rectangle {\n" -" width: u32,\n" -" height: u32,\n" +"struct Retangulo {\n" +" largura: u32,\n" +" altura: u32,\n" "}" #: src/basic-syntax/methods.md:12 @@ -2816,6 +2841,10 @@ msgid "" " self.width * self.height\n" " }" msgstr "" +"impl Retangulo {\n" +" fn area(&self) -> u32 {\n" +" self.largura * self.altura\n" +" }" #: src/basic-syntax/methods.md:17 msgid "" @@ -2824,6 +2853,10 @@ msgid "" " }\n" "}" msgstr "" +" fn aumenta_largura(&mut self, delta: u32) {\n" +" self.largura += delta;\n" +" }\n" +"}" #: src/basic-syntax/methods.md:22 msgid "" @@ -2835,6 +2868,13 @@ msgid "" "}\n" "```" msgstr "" +"fn main() {\n" +" let mut ret = Retangulo { largura: 10, altura: 5 };\n" +" println!(\"Área inicial: {}\", ret.area());\n" +" ret.aumenta_largura(5);\n" +" println!(\"Nova área: {}\", ret.area());\n" +"}\n" +"```" #: src/basic-syntax/methods.md:30 msgid "* We will look much more at methods in today's exercise and in tomorrow's class." @@ -2875,6 +2915,10 @@ msgid "" " if std::process::id() % 2 == 0 { a } else { b }\n" "}" msgstr "" +"```rust,editable\n" +"fn escolha_um(a: T, b: T) -> T {\n" +" if std::process::id() % 2 == 0 { a } else { b }\n" +"}" #: src/basic-syntax/functions-interlude.md:19 msgid "" @@ -2884,13 +2928,18 @@ msgid "" "}\n" "```" msgstr "" +"fn main() {\n" +" println!(\"Cara ou coroa: {}\", escolha_um(\"cara\", \"coroa\"));\n" +" println!(\"Bônus: {}\", escolha_um(500, 1000));\n" +"}\n" +"```" #: src/basic-syntax/functions-interlude.md:27 msgid "" "* When using generics, the standard library's `Into` can provide a kind of limited\n" " polymorphism on argument types. We will see more details in a later section." msgstr "" -"* Ao usar generics, o `Into` da biblioteca padrão pode fornecer um tipo polimorfismo\n" +"* Ao usar generics, o `Into` da biblioteca padrão pode fornecer um tipo polimórfico\n" " limitado nos tipos do argumento. Veremos mais detalhes em uma seção posterior." #: src/basic-syntax/functions-interlude.md:30 @@ -2911,7 +2960,7 @@ msgstr "* Conversões implícitas entre tipos." #: src/exercises/day-1/morning.md:7 msgid "* Arrays and `for` loops." -msgstr "* Arrays e loops `for`." +msgstr "* Vetores e laços `for`." #: src/exercises/day-1/morning.md:11 msgid "A few things to consider while solving the exercises:" @@ -2947,7 +2996,7 @@ msgstr "Depois de ver os exercícios, você pode ver as [soluções] fornecidas. #: src/exercises/day-1/morning.md:24 src/exercises/day-2/morning.md:13 src/exercises/day-3/morning.md:9 #: src/exercises/day-4/morning.md:14 msgid "[solutions]: solutions-morning.md" -msgstr "[soluções]:solutions-morning.md" +msgstr "[soluções]: solutions-morning.md" #: src/exercises/day-1/morning.md:26 msgid "[Using Cargo]: ../../cargo.md" @@ -2995,7 +3044,7 @@ msgid "" "Implementing these traits is how a type expresses that it can be converted into\n" "another type." msgstr "" -"Todos os tipos inteiro do Rust implementam os traits [`From`][1] e [`Into`][2]\n" +"Todos os tipos inteiros do Rust implementam os traits [`From`][1] e [`Into`][2]\n" "para nos deixar converter entre eles. Os traits `From` tem um único `from()`\n" "e da mesma forma, o trait `Into` tem um único método `into()`.\n" "A implementação dessas características é como um tipo expressa que pode ser convertido em\n" @@ -3055,11 +3104,11 @@ msgstr "" #: src/exercises/day-1/for-loops.md:1 msgid "# Arrays and `for` Loops" -msgstr "# Arrays e loops `for`" +msgstr "# Vetores e laços `for`" #: src/exercises/day-1/for-loops.md:3 msgid "We saw that an array can be declared like this:" -msgstr "Vimos que um array pode ser declarado assim:" +msgstr "Vimos que um vetor pode ser declarado assim:" #: src/exercises/day-1/for-loops.md:5 msgid "" @@ -3067,10 +3116,13 @@ msgid "" "let array = [10, 20, 30];\n" "```" msgstr "" +"```rust\n" +"let vetor = [10, 20, 30];\n" +"```" #: src/exercises/day-1/for-loops.md:9 msgid "You can print such an array by asking for its debug representation with `{:?}`:" -msgstr "Você pode imprimir tal array solicitando sua representação de depuração com `{:?}`:" +msgstr "Você pode imprimir tal vetor solicitando sua representação de depuração com `{:?}`:" #: src/exercises/day-1/for-loops.md:11 msgid "" @@ -3081,13 +3133,19 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let vetor = [10, 20, 30];\n" +" println!(\"Vetor: {vetor:?}\");\n" +"}\n" +"```" #: src/exercises/day-1/for-loops.md:18 msgid "" "Rust lets you iterate over things like arrays and ranges using the `for`\n" "keyword:" msgstr "" -"Rust permite iterar em coisas como arrays e intervalos usando um `for`\n" +"Rust permite iterar em coisas como vetores e intervalos usando um laço `for`\n" ":" #: src/exercises/day-1/for-loops.md:21 @@ -3101,6 +3159,14 @@ msgid "" " }\n" " println!();" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let vetor = [10, 20, 30];\n" +" print!(\"Interagindo com o vetor:\");\n" +" for n in vetor {\n" +" print!(\" {n}\");\n" +" }\n" +" println!();" #: src/exercises/day-1/for-loops.md:30 msgid "" @@ -3112,27 +3178,34 @@ msgid "" "}\n" "```" msgstr "" +" print!(\"Interagindo sobre uma faixa:\");\n" +" for i in 0..3 {\n" +" print!(\" {}\", vetor[i]);\n" +" }\n" +" println!();\n" +"}\n" +"```" #: src/exercises/day-1/for-loops.md:38 msgid "" "Use the above to write a function `pretty_print` which pretty-print a matrix and\n" "a function `transpose` which will transpose a matrix (turn rows into columns):" msgstr "" -"Use o exercício acima para escrever uma função `pretty_print` que imprime um array e\n" -"uma função `transpose` que irá transpor um array (transformar linhas em colunas):" +"Use o exercício acima para escrever uma função `pretty_print` que imprime uma matriz e\n" +"uma função `transpose` que irá transpor uma matriz (transformar linhas em colunas):" #: src/exercises/day-1/for-loops.md:41 msgid "" "```bob\n" -" ⎛⎡1 2 3⎤⎞ ⎡1 4 7⎤\n" -"\"transpose\"⎜⎢4 5 6⎥⎟ \"==\"⎢2 5 8⎥\n" -" ⎝⎣7 8 9⎦⎠ ⎣3 6 9⎦\n" +" ⎛⎡1 2 3⎤⎞ ⎡1 4 7⎤\n" +"\"transpose\" ⎜⎢4 5 6⎥⎟ \"==\" ⎢2 5 8⎥\n" +" ⎝⎣7 8 9⎦⎠ ⎣3 6 9⎦\n" "```" msgstr "" #: src/exercises/day-1/for-loops.md:47 msgid "Hard-code both functions to operate on 3 × 3 matrices." -msgstr "Limite ambas as funções a operar em arrays 3 × 3." +msgstr "Limite ambas as funções a operar em matrizes 3 × 3." #: src/exercises/day-1/for-loops.md:49 msgid "" @@ -3155,6 +3228,9 @@ msgid "" " unimplemented!()\n" "}" msgstr "" +"fn transposta(matriz: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +" unimplemented!()\n" +"}" #: src/exercises/day-1/for-loops.md:60 msgid "" @@ -3162,6 +3238,9 @@ msgid "" " unimplemented!()\n" "}" msgstr "" +"fn impressao_formatada(matriz: &[[i32; 3]; 3]) {\n" +" unimplemented!()\n" +"}" #: src/exercises/day-1/for-loops.md:64 msgid "" @@ -3173,7 +3252,7 @@ msgid "" " ];" msgstr "" "fn main() {\n" -" let matrix = [\n" +" let matriz = [\n" " [101, 102, 103], // <-- o comentário faz com que o rustfmt adicione uma nova linha\n" " [201, 202, 203],\n" " [301, 302, 303],\n" @@ -3184,6 +3263,8 @@ msgid "" " println!(\"matrix:\");\n" " pretty_print(&matrix);" msgstr "" +" println!(\"matriz:\");\n" +" impressao_formatada(&matriz);" #: src/exercises/day-1/for-loops.md:74 msgid "" @@ -3193,6 +3274,11 @@ msgid "" "}\n" "```" msgstr "" +" let transposta = transposta(matriz);\n" +" println!(\"Transposta:\");\n" +" impressao_formatada(&transposta);\n" +"}\n" +"```" #: src/exercises/day-1/for-loops.md:80 msgid "## Bonus Question" @@ -3204,7 +3290,7 @@ msgid "" "argument and return types? Something like `&[&[i32]]` for a two-dimensional\n" "slice-of-slices. Why or why not?" msgstr "" -"Você poderia usar slices `&[i32]` em vez de Arrays 3 × 3 estáticos para o seu\n" +"Você poderia usar slices `&[i32]` em vez de matrizes 3 × 3 estáticos para o seu\n" "argumentos e tipos de retorno? Algo como `&[&[i32]]` para um slice-de-slices\n" "bidimensional. Por que ou por que não?" @@ -3221,8 +3307,8 @@ msgid "" "The solution and the answer to the bonus section are available in the \n" "[Solution](solutions-morning.md#arrays-and-for-loops) section." msgstr "" -"A solução e a resposta para a seção de bônus estão disponíveis no\n" -"Seção [Solution](solutions-morning.md#arrays-and-for-loops)." +"A solução e a resposta para a seção de bônus estão disponíveis na\n" +"Seção [Soluções](solutions-morning.md#arrays-and-for-loops)." #: src/basic-syntax/variables.md:1 msgid "# Variables" @@ -3273,6 +3359,10 @@ msgid "" " println!(\"u32: {x}\");\n" "}" msgstr "" +"```rust,editable\n" +"fn recebe_u32(x: u32) {\n" +" println!(\"u32: {x}\");\n" +"}" #: src/basic-syntax/type-inference.md:10 msgid "" @@ -3280,6 +3370,9 @@ msgid "" " println!(\"i8: {y}\");\n" "}" msgstr "" +"fn recebe_u8(y: i8) {\n" +" println!(\"i8: {y}\");\n" +"}" #: src/basic-syntax/type-inference.md:14 msgid "" @@ -3296,6 +3389,11 @@ msgid "" "}\n" "```" msgstr "" +" recebe_u32(x);\n" +" recebe_u8(y);\n" +" // recebe_u32(y);\n" +"}\n" +"```" #: src/basic-syntax/type-inference.md:26 msgid "" @@ -3347,7 +3445,7 @@ msgstr "" #: src/basic-syntax/static-and-const.md:1 msgid "# Static and Constant Variables" -msgstr "# Variáveis Estáticas e Constantes" +msgstr "# Variáveis estáticas e constantes" #: src/basic-syntax/static-and-const.md:3 msgid "Global state is managed with static and constant variables." @@ -3390,7 +3488,7 @@ msgstr "" #: src/basic-syntax/static-and-const.md:27 msgid "According the the [Rust RFC Book][1] these are inlined upon use." -msgstr "De acordo com o [Rust RFC Book] [1], eles são expandidos no próprio local (inline) após o uso." +msgstr "De acordo com o [Rust RFC Book][1], eles são expandidos no próprio local (inline) após o uso." #: src/basic-syntax/static-and-const.md:29 msgid "## `static`" @@ -3421,7 +3519,7 @@ msgid "" "As noted in the [Rust RFC Book][1], these are not inlined upon use and have an actual associated memory location. This is " "useful for unsafe and embedded code, and the variable lives through the entirety of the program execution." msgstr "" -"Conforme observado no [Rust RFC Book][1], `static` e `const` não são expandidos em linha (inlined) quando utilizados uso e " +"Conforme observado no [Rust RFC Book][1], `static` e `const` não são expandidos em linha (inlined) quando utilizados e " "possuem um local de memória real associado. Isso é útil para código inseguro e embarcado, e a variável sobrevive durante " "toda a execução do programa." @@ -3446,7 +3544,7 @@ msgstr "[1]: https://rust-lang.github.io/rfcs/0246-const-vs-static.html" #: src/basic-syntax/scopes-shadowing.md:1 msgid "# Scopes and Shadowing" -msgstr "# Escopos e Sobreposição" +msgstr "# Escopos e sobreposição" #: src/basic-syntax/scopes-shadowing.md:3 msgid "" @@ -3463,6 +3561,10 @@ msgid "" " let a = 10;\n" " println!(\"before: {a}\");" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let a = 10;\n" +" println!(\"Antes: {a}\");" #: src/basic-syntax/scopes-shadowing.md:11 msgid "" @@ -3470,6 +3572,9 @@ msgid "" " let a = \"hello\";\n" " println!(\"inner scope: {a}\");" msgstr "" +" {\n" +" let a = \"Olá\";\n" +" println!(\"Escopo interno: {a}\");" #: src/basic-syntax/scopes-shadowing.md:15 msgid "" @@ -3477,6 +3582,9 @@ msgid "" " println!(\"shadowed in inner scope: {a}\");\n" " }" msgstr "" +" let a = true;\n" +" println!(\"Sobreposição no escopo interno: {a}\");\n" +" }" #: src/basic-syntax/scopes-shadowing.md:19 msgid "" @@ -3484,6 +3592,9 @@ msgid "" "}\n" "```" msgstr "" +" println!(\"Depois: {a}\");\n" +"}\n" +"```" #: src/basic-syntax/scopes-shadowing.md:25 msgid "" @@ -3526,7 +3637,7 @@ msgid "" "* Full control via manual memory management: C, C++, Pascal, ...\n" "* Full safety via automatic memory management at runtime: Java, Python, Go, Haskell, ..." msgstr "" -"* Controle total através gerenciamento manual de memória: C, C++, Pascal, ...\n" +"* Controle total através do gerenciamento manual de memória: C, C++, Pascal, ...\n" "* Segurança total através do gerenciamento automático de memória em tempo de execução: Java, Python, Go, Haskell, ..." #: src/memory-management.md:8 @@ -3551,7 +3662,7 @@ msgstr "Primeiro, vamos rever como o gerenciamento de memória funciona." #: src/memory-management/stack-vs-heap.md:1 msgid "# The Stack vs The Heap" -msgstr "# O Stack vs O Heap" +msgstr "# Stack (pilha) vs Heap" #: src/memory-management/stack-vs-heap.md:3 msgid "" @@ -3581,7 +3692,7 @@ msgstr "" #: src/memory-management/stack.md:1 msgid "# Stack Memory" -msgstr "# Memória de Pilha (stack Memory)" +msgstr "# Memória de pilha (stack Memory)" #: src/memory-management/stack.md:3 msgid "" @@ -3601,10 +3712,9 @@ msgid "" msgstr "" #: src/memory-management/stack.md:12 -#, fuzzy msgid "" "```bob\n" -" Stack Heap\n" +" Stack Heap\n" ".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" ": : : :\n" ": s1 : : :\n" @@ -3617,6 +3727,19 @@ msgid "" "`- - - - - - - - - - - - - -'\n" "```" msgstr "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | e | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" #: src/memory-management/stack.md:28 msgid "" @@ -3636,7 +3759,7 @@ msgstr "" #: src/memory-management/stack.md:32 msgid "* We can inspect the memory layout with `unsafe` code. However, you should point out that this is rightfully unsafe!" -msgstr "* Pode-se inspecionar o layout de memória com `unsafe` code. Entretanto, deve-se salientar que isto é inseguro!" +msgstr "* Pode-se inspecionar o layout de memória com código `unsafe`. Entretanto, deve-se salientar que isto é inseguro!" #: src/memory-management/stack.md:34 msgid "" @@ -3655,6 +3778,20 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let mut s1 = String::from(\"Olá\");\n" +" s1.push(' ');\n" +" s1.push_str(\"mundo\");\n" +" // NÃO FAÇA ISSO EM CASA! Somente com propósito educacional.\n" +" // String não provém nenhuma garantia sobre o seu layout, então isso pode levar\n" +" // a um comportamento indefinido.\n" +" unsafe {\n" +" let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);\n" +" println!(\"Ponteiro = {ptr:#x}, tamanho = {len}, capacidade = {capacity}\");\n" +" }\n" +"}\n" +"```" #: src/memory-management/stack.md:51 msgid "" @@ -3712,7 +3849,7 @@ msgstr "# Gerenciamento de memória baseado em escopo" #: src/memory-management/scope-based.md:3 msgid "Constructors and destructors let you hook into the lifetime of an object." -msgstr "Construtores e destruidores permitem que a tempo de vida de um objeto seja rastreado." +msgstr "Construtores e destrutores permitem que o tempo de vida de um objeto seja rastreado." #: src/memory-management/scope-based.md:5 msgid "" @@ -3745,6 +3882,11 @@ msgid "" "}\n" "```" msgstr "" +"```c++\n" +"void say_hello(std::unique_ptr person) {\n" +" std::cout << \"Olá \" << person->name << std::endl;\n" +"}\n" +"```" #: src/memory-management/scope-based.md:20 msgid "" @@ -3760,7 +3902,7 @@ msgstr "" #: src/memory-management/scope-based.md:25 msgid "Special move constructors are used when passing ownership to a function:" -msgstr "Construtores de movimentos especiais são usados ao passar a \"ownership\" para uma função:" +msgstr "Construtores especiais de movimento (move) são usados ao passar a \"ownership\" para uma função:" #: src/memory-management/scope-based.md:27 msgid "" @@ -3772,7 +3914,7 @@ msgstr "" #: src/memory-management/garbage-collection.md:1 msgid "# Automatic Memory Management" -msgstr "# Gerenciamento Automático de Memória" +msgstr "# Gerenciamento automático de memória" #: src/memory-management/garbage-collection.md:3 msgid "" @@ -3806,10 +3948,15 @@ msgid "" "}\n" "```" msgstr "" +"```java\n" +"void sayHello(Person person) {\n" +" System.out.println(\"Olá \" + person.getName());\n" +"}\n" +"```" #: src/memory-management/rust.md:1 msgid "# Memory Management in Rust" -msgstr "# Gerenciamento de memória em Rust" +msgstr "# Gerenciamento de memória do Rust" #: src/memory-management/rust.md:3 msgid "Memory management in Rust is a mix:" @@ -3831,7 +3978,7 @@ msgstr "" #: src/memory-management/rust.md:10 msgid "It achieves this by modeling _ownership_ explicitly." -msgstr "Ele consegue isso modelando _ownership_ explicitamente." +msgstr "Ele consegue isso modelando a propriedade (_ownership_) explicitamente." #: src/memory-management/rust.md:14 msgid "" @@ -3840,11 +3987,11 @@ msgid "" "errors in C." msgstr "" "* Neste ponto, se perguntado como, você pode mencionar que em Rust isso geralmente é tratado por wrappers RAII como [Box], " -"[Vec], [Rc] ou [Arc]. Eles encapsulam a ownership e a alocação de memória por vários meios e evitam possíveis erros em C." +"[Vec], [Rc] ou [Arc]. Eles encapsulam a propriedade (ownership) e a alocação de memória por vários meios e evitam possíveis erros em C." #: src/memory-management/rust.md:16 msgid "* You may be asked about destructors here, the [Drop] trait is the Rust equivalent." -msgstr "* Você pode ser questionado sobre destruidores aqui, o trait [Drop] é o equivalente ao Rust." +msgstr "* Você pode ser questionado sobre destrutores aqui, o trait [Drop] é o equivalente em Rust." #: src/memory-management/rust.md:20 msgid "" @@ -3921,7 +4068,7 @@ msgid "" " * Can reject valid programs." msgstr "" "* Manual como C:\n" -" * Use-after-free.\n" +" * Uso após a liberação (use-after-free).\n" " * Liberações duplas (double-free).\n" " * Vazamento de memória.\n" "* Automático como Java:\n" @@ -3929,7 +4076,7 @@ msgstr "" " * Atrasos na execução de destrutores.\n" "* Baseado em escopo como C++:\n" " * Complexo, o programador deve optar em utilizá-las.\n" -" * Potencial para uso pós-livre (user-after-free).\n" +" * Potencial para uso após a liberação (user-after-free).\n" "* Obrigado pelo compilador e baseado em escopo como Rust:\n" " * Alguma complexidade inicial.\n" " * Pode rejeitar programas válidos." @@ -3951,6 +4098,8 @@ msgid "" "```rust,editable,compile_fail\n" "struct Point(i32, i32);" msgstr "" +"```rust,editable,compile_fail\n" +"struct Ponto(i32, i32);" #: src/ownership.md:9 msgid "" @@ -3963,6 +4112,14 @@ msgid "" "}\n" "```" msgstr "" +"fn main() {\n" +" {\n" +" let p = Ponto(3, 4);\n" +" println!(\"x: {}\", p.0);\n" +" }\n" +" println!(\"y: {}\", p.1);\n" +"}\n" +"```" #: src/ownership.md:18 msgid "" @@ -3976,11 +4133,11 @@ msgstr "" #: src/ownership/move-semantics.md:1 msgid "# Move Semantics" -msgstr "# Semântica de mover (move)" +msgstr "# Semântica do `move` (mover)" #: src/ownership/move-semantics.md:3 msgid "An assignment will transfer ownership between variables:" -msgstr "Uma atribuição transferirá a ownership entre variáveis:" +msgstr "Uma atribuição transferirá a propriedade (ownership) entre variáveis:" #: src/ownership/move-semantics.md:5 msgid "" @@ -3993,6 +4150,14 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Olá!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" #: src/ownership/move-semantics.md:14 msgid "" @@ -4040,7 +4205,7 @@ msgid "" "* When `s1` goes out of scope, nothing happens (it has been moved from)." msgstr "" "* Os dados no heap de `s1` são reutilizados para `s2`.\n" -"* Quando `s1` sai do escopo, nada acontece (foi movido de)." +"* Quando `s1` sai do escopo, nada acontece (foi movido dele)." #: src/ownership/moved-strings-rust.md:13 msgid "Before move to `s2`:" @@ -4064,19 +4229,32 @@ msgid "" "`- - - - - - - - - - - - - -'\n" "```" msgstr "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| R | u | s | t | :\n" +": | len | 4 | : : +----+----+----+----+ :\n" +": | capacity | 4 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - -'\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" #: src/ownership/moved-strings-rust.md:30 msgid "After move to `s2`:" msgstr "Depois de mover para `s2`:" #: src/ownership/moved-strings-rust.md:32 -#, fuzzy msgid "" "```bob\n" " Stack Heap\n" ".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" ": : : :\n" -": s1 \"(inaccessible)\" : : :\n" +": s1 \"(inaccessible)\" : : :\n" ": +-----------+-------+ : : +----+----+----+----+ :\n" ": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" ": | len | 4 | : | : +----+----+----+----+ :\n" @@ -4093,6 +4271,26 @@ msgid "" "`- - - - - - - - - - - - - -'\n" "```" msgstr "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 \"(inacessível)\" : : :\n" +": +------------+------+ : : +----+----+----+----+ :\n" +": | ponteiro | o---+---+--+--+-->| R | u | s | t | :\n" +": | tamanho | 4 | : | : +----+----+----+----+ :\n" +": | capacidade | 4 | : | : :\n" +": +------------+------+ : | : :\n" +": : | `- - - - - - - - - - - - - -'\n" +": s2 : |\n" +": +------------+------+ : |\n" +": | ponteiro | o---+---+--'\n" +": | tamanho | 4 | :\n" +": | capacidade | 4 | :\n" +": +------------+------+ :\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" #: src/ownership/double-free-modern-cpp.md:1 msgid "# Double Frees in Modern C++" @@ -4175,7 +4373,7 @@ msgstr "" #: src/ownership/moves-function-calls.md:1 msgid "# Moves in Function Calls" -msgstr "# Movimentos em chamadas de Função" +msgstr "# Move (mover) em chamadas de Função" #: src/ownership/moves-function-calls.md:3 msgid "" @@ -4192,6 +4390,10 @@ msgid "" " println!(\"Hello {name}\")\n" "}" msgstr "" +"```rust,editable\n" +"fn diz_ola(nome: String) {\n" +" println!(\"Olá {nome}\")\n" +"}" #: src/ownership/moves-function-calls.md:11 msgid "" @@ -4202,6 +4404,12 @@ msgid "" "}\n" "```" msgstr "" +"fn main() {\n" +" let nome = String::from(\"Alice\");\n" +" diz_ola(nome);\n" +" // diz_ola(nome);\n" +"}\n" +"```" #: src/ownership/moves-function-calls.md:20 msgid "" @@ -4220,7 +4428,7 @@ msgstr "" "* `main` pode manter a ownership se passar `name` como uma referência (`&name`) e se `say_hello` aceitar uma referência " "como um parâmetro.\n" "* Alternativamente, `main` pode passar um clone de `name` na primeira chamada (`name.clone()`).\n" -"* Rust torna mais difícil do que C++ criar cópias inadvertidamente, tornando a semântica de movimento o padrão e forçando " +"* Rust torna mais difícil do que o C++ a criação de cópias inadvertidamente, tornando a semântica de movimento o padrão e forçando " "os programadores a tornar os clones explícitos." #: src/ownership/copy-clone.md:1 @@ -4267,7 +4475,7 @@ msgid "" msgstr "" "```rust, editable\n" "#[derive(Copy, Clone, Debug)]\n" -"struct Point(i32, i32);" +"struct Ponto(i32, i32);" #: src/ownership/copy-clone.md:22 msgid "" @@ -4280,7 +4488,7 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let p1 = Point(3, 4);\n" +" let p1 = Ponto(3, 4);\n" " let p2 = p1;\n" " println!(\"p1: {p1:?}\");\n" " println!(\"p2: {p2:?}\");\n" @@ -4339,15 +4547,15 @@ msgstr "" #: src/ownership/borrowing.md:1 msgid "# Borrowing" -msgstr "# Empréstimo" +msgstr "# Empréstimo (Borrowing)" #: src/ownership/borrowing.md:3 msgid "" "Instead of transferring ownership when calling a function, you can let a\n" "function _borrow_ the value:" msgstr "" -"Em vez de transferir a ownership ao chamar uma função, você pode permitir que um\n" -"função _emprestar_ o valor:" +"Em vez de transferir a ownership ao chamar uma função, você pode permitir que uma\n" +"função _empreste_ o valor:" #: src/ownership/borrowing.md:6 src/ownership/lifetimes-function-calls.md:5 msgid "" @@ -4357,7 +4565,7 @@ msgid "" msgstr "" "```rust, editable\n" "#[derive(Debug)]\n" -"struct Point(i32, i32);" +"struct Ponto(i32, i32);" #: src/ownership/borrowing.md:10 msgid "" @@ -4365,8 +4573,8 @@ msgid "" " Point(p1.0 + p2.0, p1.1 + p2.1)\n" "}" msgstr "" -"fn add(p1: &Point, p2: &Point) -> Point {\n" -" Point(p1.0 + p2.0, p1.1 + p2.1)\n" +"fn somar(p1: &Ponto, p2: &Ponto) -> Ponto {\n" +" Ponto(p1.0 + p2.0, p1.1 + p2.1)\n" "}" #: src/ownership/borrowing.md:14 @@ -4380,9 +4588,9 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" +" let p1 = Ponto(3, 4);\n" +" let p2 = Ponto(10, 20);\n" +" let p3 = somar(&p1, &p2);\n" " println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" "}\n" "```" @@ -4392,8 +4600,8 @@ msgid "" "* The `add` function _borrows_ two points and returns a new point.\n" "* The caller retains ownership of the inputs." msgstr "" -"* A função `add` _pega emprestado_ dois Points e retorna um novo Point.\n" -"* O chamador mantém a ownership das entradas." +"* A função `somar` _pega emprestado_ (_borrowing_) dois Pontos e retorna um novo Ponto.\n" +"* O chamador mantém a _ownership_ das entradas." #: src/ownership/borrowing.md:27 msgid "" @@ -4403,9 +4611,9 @@ msgid "" "change, while the stay the same when changing to the \"RELEASE\" setting:" msgstr "" "Notas sobre retornos de pilha:\n" -"* Demonstre que o retorno de `add` é barato porque o compilador pode eliminar a operação de cópia. Altere o código acima " +"* Demonstre que o retorno de `somar` é barato porque o compilador pode eliminar a operação de cópia. Altere o código acima " "para imprimir endereços de pilha e execute-o no [Playground]. No nível de otimização \"DEBUG\", os endereços devem mudar, " -"enquanto os permanecem os mesmos ao mudar para a configuração \"RELEASE\":" +"enquanto permanecem os mesmos ao mudar para a configuração \"RELEASE\":" #: src/ownership/borrowing.md:30 msgid "" @@ -4415,7 +4623,7 @@ msgid "" msgstr "" " ```rust, editable\n" " #[derive(Debug)]\n" -" struct Point(i32, i32);" +" struct Ponto(i32, i32);" #: src/ownership/borrowing.md:34 msgid "" @@ -4425,8 +4633,8 @@ msgid "" " p\n" " }" msgstr "" -" fn add(p1: &Point, p2: &Point) -> Point {\n" -" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" +" fn somar(p1: &Ponto, p2: &Ponto) -> Ponto {\n" +" let p = Ponto(p1.0 + p2.0, p1.1 + p2.1);\n" " println!(\"&p.0: {:p}\", &p.0);\n" " p\n" " }" @@ -4446,9 +4654,9 @@ msgid "" "this is not an issue at all. If RVO did not happen, Rust will always performs a simple and efficient `memcpy` copy." msgstr "" " fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" +" let p1 = Ponto(3, 4);\n" +" let p2 = Ponto(10, 20);\n" +" let p3 = somar(&p1, &p2);\n" " println!(\"&p3.0: {:p}\", &p3.0);\n" " println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" " }\n" @@ -4534,7 +4742,7 @@ msgstr "# Tempos de vida" #: src/ownership/lifetimes.md:3 msgid "A borrowed value has a _lifetime_:" -msgstr "Um valor emprestado tem um _lifetime_:" +msgstr "Um valor emprestado tem um tempo de vida (_lifetime_):" #: src/ownership/lifetimes.md:5 msgid "" @@ -4547,9 +4755,9 @@ msgid "" " * Lifetime annotations create constraints; the compiler verifies that there is\n" " a valid solution." msgstr "" -"* O tempo de vida pode ser excluído: `add(p1: &Point, p2: &Point) -> Point`.\n" +"* O tempo de vida pode ser omitido: `add(p1: &Point, p2: &Point) -> Point`.\n" "* Tempos de vida também podem ser explícitos: `&'a Point`, `&'document str`.\n" -"* Leia `&'um Point` como \"um `Point` emprestado que é válido por pelo menos o\n" +"* Leia `&'a Point` como \"um `Point` emprestado que é válido por pelo menos o\n" " tempo de vida `a`\".\n" "* Os tempos de vida são sempre inferidos pelo compilador: você não pode atribuir um tempo de vida\n" " você mesmo.\n" @@ -4558,7 +4766,7 @@ msgstr "" #: src/ownership/lifetimes-function-calls.md:1 msgid "# Lifetimes in Function Calls" -msgstr "# Tempos de vida em Chamadas de Função" +msgstr "# Tempos de vida em chamadas de função" #: src/ownership/lifetimes-function-calls.md:3 msgid "In addition to borrowing its arguments, a function can return a borrowed value:" @@ -4570,7 +4778,7 @@ msgid "" " if p1.0 < p2.0 { p1 } else { p2 }\n" "}" msgstr "" -"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +"fn mais_a_esquerda<'a>(p1: &'a Ponto, p2: &'a Ponto) -> &'a Ponto{\n" " if p1.0 < p2.0 { p1 } else { p2 }\n" "}" @@ -4585,10 +4793,10 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p2: Point = Point(20, 20);\n" -" let p3: &Point = left_most(&p1, &p2);\n" -" println!(\"Point mais à esquerda: {:?}\", p3);\n" +" let p1: Ponto = Ponto(10, 10);\n" +" let p2: Ponto = Ponto(20, 20);\n" +" let p3: &Ponto = mais_a_esquerda(&p1, &p2);\n" +" println!(\"Ponto mais à esquerda: {:?}\", p3);\n" "}\n" "```" @@ -4602,7 +4810,7 @@ msgid "" msgstr "" "* `'a` é um parâmetro genérico, é inferido pelo compilador.\n" "* Os tempos de vida começam com `'` e `'a` é um name padrão típico.\n" -"* Leia `&'um Point` como \"um `Point` emprestado que é válido por pelo menos o\n" +"* Leia `&'a Ponto` como \"um `Ponto` emprestado que é válido por pelo menos o\n" " tempo de vida `a`\".\n" " * A parte _pelo menos_ é importante quando os parâmetros estão em escopos diferentes." @@ -4616,7 +4824,7 @@ msgstr "" "* Mova a declaração de `p2` e `p3` para um novo escopo (`{ ... }`), resultando no seguinte código:\n" " ```rust, ignore\n" " #[derive(Debug)]\n" -" struct Point(i32, i32);" +" struct Ponto(i32, i32);" #: src/ownership/lifetimes-function-calls.md:36 msgid "" @@ -4624,7 +4832,7 @@ msgid "" " if p1.0 < p2.0 { p1 } else { p2 }\n" " }" msgstr "" -" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" fn mais_a_esquerda<'a>(p1: &'a Ponto, p2: &'a Ponto) -> &'a Ponto {\n" " if p1.0 < p2.0 { p1 } else { p2 }\n" " }" @@ -4643,13 +4851,13 @@ msgid "" " Note how this does not compile since `p3` outlives `p2`." msgstr "" " fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p3: &Point;\n" +" let p1: Ponto = Ponto(10, 10);\n" +" let p3: &Ponto;\n" " {\n" -" let p2: Point = Point(20, 20);\n" -" p3 = left_most(&p1, &p2);\n" +" let p2: Ponto = Ponto(20, 20);\n" +" p3 = mais_a_esquerda(&p1, &p2);\n" " }\n" -" println!(\"left-most point: {:?}\", p3);\n" +" println!(\"Ponto mais à esquerda: {:?}\", p3);\n" " }\n" " ```\n" " Observe como isso não compila, pois `p3` sobrevive a `p2`." @@ -4665,8 +4873,8 @@ msgid "" " * Which one is it? The compiler needs to 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 "" -"* Redefina o espaço de trabalho e altere a assinatura da função para `fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> " -"&'b Point`. Isso não será compilado porque a relação entre os tempos de vida `'a` e `'b` não é clara.\n" +"* Redefina o espaço de trabalho e altere a assinatura da função para `fn mais_a_esquerda<'a, 'b>(p1: &'a Ponto, p2: &'a Ponto) -> " +"&'b Ponto`. Isso não será compilado porque a relação entre os tempos de vida `'a` e `'b` não é clara.\n" "* Outra forma de explicar:\n" " * Duas referências a dois valores são emprestadas por uma função e a função retorna\n" " outra referência.\n" @@ -4676,7 +4884,7 @@ msgstr "" #: src/ownership/lifetimes-data-structures.md:1 msgid "# Lifetimes in Data Structures" -msgstr "# Tempos de vida em Structs de dados" +msgstr "# Tempos de vida em estruturas de dados" #: src/ownership/lifetimes-data-structures.md:3 msgid "If a data type stores borrowed data, it must be annotated with a lifetime:" @@ -4690,7 +4898,7 @@ msgid "" msgstr "" "```rust, editable\n" "#[derive(Debug)]\n" -"struct Highlight<'doc>(&'doc str);" +"struct Destaque<'doc>(&'doc str);" #: src/ownership/lifetimes-data-structures.md:9 msgid "" @@ -4698,7 +4906,7 @@ msgid "" " println!(\"Bye {text}!\");\n" "}" msgstr "" -"fn erase(texto: String) {\n" +"fn apagar(texto: String) {\n" " println!(\"Tchau {texto}!\");\n" "}" @@ -4715,12 +4923,12 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let text = String::from(\"The quick brown fox jumps over the lazy dog.\");\n" -" let fox = Highlight(&text[4..19]);\n" -" let dog = Highlight(&text[35..43]);\n" -" // erase(texto);\n" -" println!(\"{fox:?}\");\n" -" println!(\"{dog:?}\");\n" +" let texto = String::from(\"A esperta raposa marrom pula sobre o cachorro preguiçoso.\");\n" +" let raposa = Destaque(&texto[2..23]);\n" +" let cachorro = Destaque(&texto[37..57]);\n" +" // apagar(texto);\n" +" println!(\"{raposa:?}\");\n" +" println!(\"{cachorro:?}\");\n" "}\n" "```" @@ -4737,15 +4945,15 @@ msgid "" "itself. Those are very advanced use cases.\n" "" msgstr "" -"* No exemplo acima, a anotação em `Highlight` impõe que os dados subjacentes ao `&str` contido vivam pelo menos tanto " -"quanto qualquer instância de `Highlight` que usa esses dados.\n" -"* Se `text` for consumido antes do final do tempo de vida de `fox` (ou `dog`), o verificador de empréstimo lançará um " +"* No exemplo acima, a anotação em `Destaque` impõe que os dados subjacentes ao `&str` contido vivam pelo menos tanto " +"quanto qualquer instância de `Destaque` que usa esses dados.\n" +"* Se `texto` for consumido antes do final do tempo de vida de `raposa` (ou `cachorro`), o verificador de empréstimo lançará um " "erro.\n" "* Tipos com dados emprestados forçam os usuários a manter os dados originais. Isso pode ser útil para criar exibições " -"leves, mas geralmente as torna um pouco mais difíceis de usar.\n" -"* Quando possível, faça com que as Structs de dados possuam seus dados diretamente.\n" -"* Algumas Structs com várias referências internas podem ter mais de uma anotação vitalícia. Isso pode ser necessário se " -"houver necessage de descrever relacionamentos de tempo de vida entre as próprias referências, além do tempo de vida da " +"leves, mas geralmente as tornam um pouco mais difíceis de usar.\n" +"* Quando possível, faça com que as _Structs_ de dados possuam seus dados diretamente.\n" +"* Algumas _Structs_ com várias referências internas podem ter mais de uma anotação vitalícia. Isso pode ser necessário se " +"houver necessidade de descrever relacionamentos de tempo de vida entre as próprias referências, além do tempo de vida da " "própria estrutura. Esses são casos de uso muito avançados.\n" "" @@ -4767,7 +4975,7 @@ msgstr "* Iteradores e ownership (difícil)." #: src/exercises/day-1/afternoon.md:13 src/exercises/day-2/afternoon.md:9 msgid "[solutions]: solutions-afternoon.md" -msgstr "[soluções]: soluções-tarde.md" +msgstr "[soluções]: solutions-afternoon.md" #: src/exercises/day-1/book-library.md:1 msgid "# Designing a Library" @@ -4778,7 +4986,7 @@ msgid "" "We will learn much more about structs and the `Vec` type tomorrow. For now,\n" "you just need to know part of its API:" msgstr "" -"Aprenderemos muito mais sobre structs e o tipo `Vec` amanhã. Por agora,\n" +"Aprenderemos muito mais sobre structs e o tipo `Vec` amanhã. Por hora,\n" "você só precisa conhecer parte de sua API:" #: src/exercises/day-1/book-library.md:6 @@ -4796,10 +5004,10 @@ msgid "" msgstr "" "```rust, editable\n" "fn main() {\n" -" let mut vec = vec![10, 20];\n" -" vec.push(30);\n" -" println!(\"valor do meio: {}\", vec[vec.len() / 2]);\n" -" for item in vec.iter() {\n" +" let mut vetor = vec![10, 20];\n" +" vetor.push(30);\n" +" println!(\"valor do meio: {}\", vetor[vetor.len() / 2]);\n" +" for item in vetor.iter() {\n" " println!(\"item: {item}\");\n" " }\n" "}\n" @@ -4819,25 +5027,23 @@ msgid "" " books: Vec,\n" "}" msgstr "" -"struct Library {\n" -" books: Vec,\n" +"struct Biblioteca {\n" +" livros: Vec,\n" "}" #: src/exercises/day-1/book-library.md:28 src/exercises/day-1/solutions-afternoon.md:27 -#, fuzzy msgid "" "struct Book {\n" " title: String,\n" " year: u16,\n" "}" msgstr "" -"struct Book {\n" -" título: String,\n" -" year: u16,\n" +"struct Livro {\n" +" titulo: String,\n" +" ano: u16,\n" "}" #: src/exercises/day-1/book-library.md:33 src/exercises/day-1/solutions-afternoon.md:32 -#, fuzzy msgid "" "impl Book {\n" " // This is a constructor, used below.\n" @@ -4849,12 +5055,12 @@ msgid "" " }\n" "}" msgstr "" -"impl Book {\n" +"impl Livro {\n" " // Este é um construtor, usado abaixo.\n" -" fn new(title: &str, ano: u16) -> Book {\n" -" Book {\n" -" title: String::from(title),\n" -" year,\n" +" fn new(titulo: &str, ano: u16) -> Livro {\n" +" Livro {\n" +" titulo: String::from(titulo),\n" +" ano,\n" " }\n" " }\n" "}" @@ -4869,22 +5075,21 @@ msgid "" "}" msgstr "" "// Isso torna possível imprimir valores de livro com {}.\n" -"impl std::fmt::Display for Book {\n" +"impl std::fmt::Display for Livro {\n" " fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n" -" write!(f, \"{} ({})\", self.title, self.year)\n" +" write!(f, \"{} ({})\", self.titulo, self.ano)\n" " }\n" "}" #: src/exercises/day-1/book-library.md:50 -#, fuzzy msgid "" "impl Library {\n" " fn new() -> Library {\n" " unimplemented!()\n" " }" msgstr "" -"impl Library {\n" -" fn new() -> Library {\n" +"impl Biblioteca {\n" +" fn new() -> Biblioteca {\n" " unimplemented!()\n" " }" @@ -4894,7 +5099,7 @@ msgid "" " // unimplemented!()\n" " //}" msgstr "" -" //fn len(self) -> usize {\n" +" //fn tamanho(self) -> usize {\n" " // unimplemented!()\n" " //}" @@ -4904,7 +5109,7 @@ msgid "" " // unimplemented!()\n" " //}" msgstr "" -" //fn is_empty(self) -> bool {\n" +" //fn tem_livros(self) -> bool {\n" " // unimplemented!()\n" " //}" @@ -4914,7 +5119,7 @@ msgid "" " // unimplemented!()\n" " //}" msgstr "" -" //fn add_book(self, book: Book) {\n" +" //fn adiciona_livro(self, livro: Livro) {\n" " // unimplemented!()\n" " //}" @@ -4924,7 +5129,7 @@ msgid "" " // unimplemented!()\n" " //}" msgstr "" -" //fn print_books(self) {\n" +" //fn imprime_acervo(self) {\n" " // unimplemented!()\n" " //}" @@ -4935,7 +5140,7 @@ msgid "" " //}\n" "}" msgstr "" -" //fn oldest_book(self) -> Option<&Book> {\n" +" //fn livro_mais_antigo(self) -> Option<&Livro> {\n" " // unimplemented!()\n" " //}\n" "}" @@ -4950,14 +5155,13 @@ msgid "" " let library = Library::new();" msgstr "" "// Isso mostra o comportamento desejado. Descomente o código abaixo e\n" -"// implementa os métodos ausentes. Você precisará atualizar o\n" -"// assinaturas de método, incluindo o parâmetro \"self\"! Você pode\n" -"// também precisa atualizar as ligações de variáveis dentro de main.\n" +"// implemente os métodos ausentes. Você precisará atualizar as\n" +"// assinaturas de método, incluindo o parâmetro \"self\"! Você poderá\n" +"// também precisar atualizar as ligações de variáveis dentro de main.\n" "fn main() {\n" -" let library = Library::new();" +" let biblioteca = Biblioteca::new();" #: src/exercises/day-1/book-library.md:83 -#, fuzzy msgid "" " //println!(\"Our library is empty: {}\", library.is_empty());\n" " //\n" @@ -4975,19 +5179,19 @@ msgid "" "}\n" "```" msgstr "" -" //println!(\"Nossa biblioteca está vazia: {}\", 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" -" //library.print_books();\n" -" //\n" -" //corresponde à library.oldest_book() {\n" -" // Some(book) => println!(\"Meu livro mais antigo é {book}\"),\n" -" // None => println!(\"Minha biblioteca está vazia!\"),\n" -" //}\n" -" //\n" -" //println!(\"Nossa biblioteca tem {} livros\", library.len());\n" +" // println!(\"Nossa biblioteca está vazia: {}\", biblioteca.tem_livros());\n" +" // \n" +" // biblioteca.adiciona_livro(Livro::new(\"Lord of the Rings\", 1954));\n" +" // biblioteca.adiciona_livro(Livro::new(\"Alice's Adventures in Wonderland\", 1865));\n" +" // \n" +" // biblioteca.imprime_acervo();\n" +" // \n" +" // match biblioteca.livro_mais_antigo() {\n" +" // Some(livro) => println!(\"Meu livro mais antigo é {livro}\"),\n" +" // None => println!(\"Minha biblioteca está vazia!\"),\n" +" // }\n" +" // \n" +" // println!(\"Nossa biblioteca tem {} livros\", biblioteca.tamanho());\n" "}\n" "```" @@ -4999,7 +5203,7 @@ msgid "" msgstr "" "
\n" " \n" -"[Solution](solutions-afternoon.md#designing-a-library)" +"[Soluções](solutions-afternoon.md#designing-a-library)" #: src/exercises/day-1/iterators-and-ownership.md:1 msgid "# Iterators and Ownership" @@ -5012,22 +5216,21 @@ msgid "" "[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)\n" "traits." msgstr "" -"O modelo de ownership do Rust afeta muitas APIs. Um exemplo disso é o\n" +"O modelo de _ownership_ do Rust afeta muitas APIs. Um exemplo disso são os _traits_\n" "[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) e\n" -"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)\n" -"características." +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)." #: src/exercises/day-1/iterators-and-ownership.md:8 msgid "## `Iterator`" -msgstr "## `Iterador`" +msgstr "## `Iterator` (iterador)" #: src/exercises/day-1/iterators-and-ownership.md:10 msgid "" "Traits are like interfaces: they describe behavior (methods) for a type. The\n" "`Iterator` trait simply says that you can call `next` until you get `None` back:" msgstr "" -"Os traits são como interfaces: eles descrevem o comportamento (métodos) para um tipo. o\n" -"O trait `Iterator` simplesmente diz que você pode chamar `next` até obter `None` de volta:" +"Os _traits_ são como interfaces: eles descrevem o comportamento (métodos) para um tipo. o\n" +"O _trait_ `Iterator` simplesmente diz que você pode chamar `next` até obter `None` como retorno:" #: src/exercises/day-1/iterators-and-ownership.md:13 msgid "" @@ -5118,7 +5321,7 @@ msgid "" "The `Iterator` trait tells you how to _iterate_ once you have created an\n" "iterator. The related trait `IntoIterator` tells you how to create the iterator:" msgstr "" -"O trait `Iterator` informa como _iterar_ depois de criar um\n" +"O _trait_ `Iterator` informa como _iterar_ depois de criar um\n" "iterador. A característica relacionada `IntoIterator` informa como criar o iterador:" #: src/exercises/day-1/iterators-and-ownership.md:53 @@ -5185,7 +5388,7 @@ msgstr "" #: src/exercises/day-1/iterators-and-ownership.md:83 msgid "## `for` Loops" -msgstr "## `for` Loops" +msgstr "## Laços `for`" #: src/exercises/day-1/iterators-and-ownership.md:85 msgid "" @@ -5193,7 +5396,7 @@ msgid "" "They call `into_iter()` on an expression and iterates over the resulting\n" "iterator:" msgstr "" -"Agora que conhecemos `Iterator` e `IntoIterator`, podemos construir loops `for`.\n" +"Agora que conhecemos `Iterator` e `IntoIterator`, podemos construir laços `for`.\n" "Eles chamam `into_iter()` em uma expressão e itera sobre o resultado\n" "iterador:" @@ -5213,8 +5416,8 @@ msgid "" " println!(\"word: {word}\");\n" " }" msgstr "" -" for word in &v {\n" -" println!(\"word: {word}\");\n" +" for palavra in &v {\n" +" println!(\"Palavra: {palavra}\");\n" " }" #: src/exercises/day-1/iterators-and-ownership.md:97 @@ -5225,15 +5428,15 @@ msgid "" "}\n" "```" msgstr "" -" for word in v {\n" -" println!(\"word: {word}\");\n" +" for palavra in v {\n" +" println!(\"Palavra: {palavra}\");\n" " }\n" "}\n" "```" #: src/exercises/day-1/iterators-and-ownership.md:103 msgid "What is the type of `word` in each loop?" -msgstr "Qual é o tipo de `palavra` em cada loop?" +msgstr "Qual é o tipo de `palavra` em cada laço?" #: src/exercises/day-1/iterators-and-ownership.md:105 msgid "" @@ -5253,19 +5456,19 @@ msgstr "" #: src/welcome-day-2.md:1 msgid "# Welcome to Day 2" -msgstr "# Bem-vindo ao Dia 2" +msgstr "# Bem-vindo ao dia 2" #: src/welcome-day-2.md:3 msgid "Now that we have seen a fair amount of Rust, we will continue with:" -msgstr "Agora que vimos uma boa quantage de Rust, continuaremos com:" +msgstr "Agora que vimos uma boa quantidade de Rust, continuaremos com:" #: src/welcome-day-2.md:5 msgid "* Structs, enums, methods." -msgstr "* Structs, enums, métodos." +msgstr "* Estruturas (`structs`), enumerações (`enums`) e métodos." #: src/welcome-day-2.md:7 msgid "* Pattern matching: destructuring enums, structs, and arrays." -msgstr "* Correspondência de padrões: desestruturando enums, structs e arrays." +msgstr "* Correspondência de padrões: desestruturando enumerações, estruturas e vetores." #: src/welcome-day-2.md:9 msgid "" @@ -5285,15 +5488,15 @@ msgstr "" #: src/welcome-day-2.md:15 msgid "* Modules: visibility, paths, and filesystem hierarchy." -msgstr "* Módulos: visibilage, caminhos e hierarquia do sistema de arquivos." +msgstr "* Módulos: visibilidade, caminhos e hierarquia do sistema de arquivos." #: src/structs.md:1 msgid "# Structs" -msgstr "# Structs" +msgstr "# Estruturas (Structs)" #: src/structs.md:3 msgid "Like C and C++, Rust has support for custom structs:" -msgstr "Como C e C++, Rust tem suporte para structs personalizados:" +msgstr "Como C e C++, Rust tem suporte para `structs` personalizadas:" #: src/structs.md:5 msgid "" @@ -5304,9 +5507,9 @@ msgid "" "}" msgstr "" "```rust, editable\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" +"struct Pessoa {\n" +" nome: String,\n" +" idade: u8,\n" "}" #: src/structs.md:11 @@ -5330,20 +5533,20 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let mut pedro = Person {\n" -" name: String::from(\"Pedro\"),\n" -" age: 27,\n" +" let mut pedro = Pessoa {\n" +" nome: String::from(\"Pedro\"),\n" +" idade: 27,\n" " };\n" -" println!(\"{} is {} years old\", pedro.name, pedro.age);\n" +" println!(\"{} tem {} anos.\", pedro.nome, pedro.idade);\n" " \n" -" pedro.age = 28;\n" -" println!(\"{} is {} years old\", pedro.name, pedro.age);\n" +" pedro.idade= 28;\n" +" println!(\"{} tem {} anos.\", pedro.nome, pedro.idade);\n" " \n" -" let jackie = Person {\n" -" name: String::from(\"Jackie\"),\n" +" let jackie = Pessoa {\n" +" nome: String::from(\"Jackie\"),\n" " ..pedro\n" " };\n" -" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" +" println!(\"{} tem {} anos.\", jackie.nome, jackie.idade);\n" "}\n" "```" @@ -5353,7 +5556,7 @@ msgid "" "Key Points: " msgstr "" "
\n" -"Points chave:" +"Pontos chave:" #: src/structs.md:32 msgid "" @@ -5367,23 +5570,26 @@ msgid "" " * The next slide will introduce Tuple structs, used when the field names are not important.\n" "* The syntax `..peter` allows us to copy the majority of the fields from the old struct without having to explicitly type " "it all out. It must always be the last element." + msgstr "" "* Structs funcionam como em C ou C++.\n" " * Como em C++, e ao contrário de C, nenhum typedef é necessário para definir um tipo.\n" " * Ao contrário do C++, não há herança entre structs.\n" "* Os métodos são definidos em um bloco `impl`, que veremos nos próximos slides.\n" -"* Este pode ser um bom momento para que as Persons saibam que existem diferentes tipos de structs.\n" -" * Structs de tamanho zero `por exemplo, struct Foo;` podem ser usadas ao implementar uma característica em algum tipo, " -"mas não possuem nenhum dado que você deseja armazenar no próprio valor.\n" -" * O próximo slide apresentará as Structs Tuple." +"* Este pode ser um bom momento para que as pessoas saibam que existem diferentes tipos de structs.\n" +" * _Structs_ de tamanho zero `por exemplo, struct Foo;` podem ser usadas ao implementar uma característica em algum tipo,\n" +"mas não possuem nenhum dado que você deseja armazenar nelas.\n" +" * O próximo slide apresentará as estruturas tuplas (_Tuple Structs_) usadas quando o nome dos campos não são importantes.\n" +"* A sintaxe `..pedro` permite a cópia da maioria do campos de uma _struct_ sem precisar explicitar seus tipos.\n" +" Ele precisa ser o último elemento." #: src/structs/tuple-structs.md:1 msgid "# Tuple Structs" -msgstr "# Structs Tuplas" +msgstr "# Estruturas Tupla (Tuple Structs)" #: src/structs/tuple-structs.md:3 msgid "If the field names are unimportant, you can use a tuple struct:" -msgstr "Se os names dos campos não forem importantes, você pode usar uma estrutura de tupla:" +msgstr "Se os nomes dos campos não forem importantes, você pode usar uma estrutura de tupla:" #: src/structs/tuple-structs.md:5 msgid "" @@ -5391,7 +5597,7 @@ msgid "" "struct Point(i32, i32);" msgstr "" "```rust, editable\n" -"struct Point(i32, i32);" +"struct Ponto(i32, i32);" #: src/structs/tuple-structs.md:8 msgid "" @@ -5402,7 +5608,7 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let p = Point(17, 23);\n" +" let p = Ponto(17, 23);\n" " println!(\"({}, {})\", p.0, p.1);\n" "}\n" "```" @@ -5450,7 +5656,7 @@ msgid "" msgstr "" "fn main() {\n" " let force = compute_thruster_force();\n" -" ift_thruster_force(force);\n" +" set_thruster_force(force);\n" "}" #: src/structs/tuple-structs.md:33 src/traits/default.md:36 src/generics/trait-objects.md:86 @@ -5462,14 +5668,14 @@ msgid "" "Newtypes are a great way to encode additional information about the value in a primitive type, for example:\n" " * The number is measured in some units: `Newtons` in the example above.\n" " * The value passed some validation when it was created, so you no longer have to validate it again at every use: " -"'PhoneNumber(String)` or `OddNumber(u32)`.\n" +" `PhoneNumber(String)` or `OddNumber(u32)`.\n" " \n" "
" msgstr "" "Newtypes são uma ótima maneira de codificar informações adicionais sobre o valor em um tipo primitivo, por exemplo:\n" -" * O número é medido em algumas unages: `Newtons` no exemplo acima.\n" +" * O número é medido em algumas unidades: `Newtons` no exemplo acima.\n" " * O valor passou por alguma validação quando foi criado, então você não precisa mais validá-lo novamente a cada uso: " -"'PhoneNumber(String)` ou `OddNumber(u32)`.\n" +" `PhoneNumber(String)` ou `OddNumber(u32)`.\n" " \n" "
" @@ -5482,7 +5688,7 @@ msgid "" "If you already have variables with the right names, then you can create the\n" "struct using a shorthand:" msgstr "" -"Se você já tiver variáveis com os names corretos, poderá criar o\n" +"Se você já tiver variáveis com os nomes corretos, poderá criar o\n" "struct usando uma abreviação:" #: src/structs/field-shorthand.md:6 src/methods.md:6 @@ -5496,9 +5702,9 @@ msgid "" msgstr "" "```rust, editable\n" "#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" +"struct Pessoa {\n" +" nome: String,\n" +" idade: u8,\n" "}" #: src/structs/field-shorthand.md:13 @@ -5509,9 +5715,9 @@ msgid "" " }\n" "}" msgstr "" -"impl Person {\n" -" fn new(name: String, age: u8) -> Person {\n" -" Person { name, age }\n" +"impl Pessoa {\n" +" fn new(nome: String, idade: u8) -> Pessoa {\n" +" Pessoa { nome, idade }\n" " }\n" "}" @@ -5524,14 +5730,14 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let peter = Person::new(String::from(\"Peter\"), 27);\n" -" println!(\"{peter:?}\");\n" +" let pedro = Pessoa::new(String::from(\"Pedro\"), 27);\n" +" println!(\"{pedro:?}\");\n" "}\n" "```" #: src/structs/field-shorthand.md:27 msgid "The `new` function could be written using `Self` as a type, as it is interchangeable with the struct type name" -msgstr "A função `new` pode ser escrita usando `Self` como um tipo, já que é intercambiável com o name do tipo struct" +msgstr "A função `new` pode ser escrita usando `Self` como um tipo, já que é intercambiável com o name do tipo _struct_" #: src/structs/field-shorthand.md:29 msgid "" @@ -5546,9 +5752,9 @@ msgid "" "" msgstr "" "```rust, ignore\n" -"impl Person {\n" -" fn new(name: String, age: u8) -> Self {\n" -" Self { name, age }\n" +"impl Pessoa {\n" +" fn new(nome: String, idade: u8) -> Self {\n" +" Self { nome, idade }\n" " }\n" "}\n" "```\n" @@ -5557,15 +5763,15 @@ msgstr "" #: src/enums.md:1 msgid "# Enums" -msgstr "# Enums" +msgstr "# Enumerações (Enums)" #: src/enums.md:3 msgid "" "The `enum` keyword allows the creation of a type which has a few\n" "different variants:" msgstr "" -"A palavra-chave `enum` permite a criação de um tipo que possui alguns\n" -"diferentes variantes:" +"A palavra-chave `enum` permite a criação de um tipo que possui algumas\n" +"variações diferentes:" #: src/enums.md:6 msgid "" @@ -5575,7 +5781,7 @@ msgid "" "}" msgstr "" "```rust, editable\n" -"fn generate_random_number() -> i32 {\n" +"fn gerador_numero_aleatorio() -> i32 {\n" " 4 // Escolhido por jogada de dados justa. Garantido para ser aleatório.\n" "}" @@ -5588,9 +5794,9 @@ msgid "" "}" msgstr "" "#[derive(Debug)]\n" -"enum CoinFlip {\n" -" Heads,\n" -" Tails,\n" +"enum CaraCoroa {\n" +" Cara,\n" +" Coroa,\n" "}" #: src/enums.md:17 @@ -5604,12 +5810,12 @@ msgid "" " }\n" "}" msgstr "" -"fn flip_coin() -> CoinFlip {\n" -" let random_number = generate_random_number();\n" -" if random_number % 2 == 0 {\n" -" return CoinFlip::Heads;\n" +"fn jogar_moeda() -> CaraCoroa {\n" +" let numero_aleatorio = gerador_numero_aleatorio();\n" +" if numero_aleatorio % 2 == 0 {\n" +" return CaraCoroa::Cara;\n" " } else {\n" -" return CoinFlip::Tails;\n" +" return CaraCoroa::Coroa;\n" " }\n" "}" @@ -5621,7 +5827,7 @@ msgid "" "```" msgstr "" "fn main() {\n" -" println!(\"You got: {:?}\", flip_coin());\n" +" println!(\"Você tem: {:?}\", jogar_moeda());\n" "}\n" "```" @@ -5633,7 +5839,7 @@ msgid "" msgstr "" "
\n" " \n" -"Points chave:" +"Pontos chave:" #: src/enums.md:35 msgid "" @@ -5661,14 +5867,14 @@ msgstr "" #: src/enums/variant-payloads.md:1 msgid "# Variant Payloads" -msgstr "# cargos úteis variantes" +msgstr "# Variantes de carga útil (payloads)" #: src/enums/variant-payloads.md:3 msgid "" "You can define richer enums where the variants carry data. You can then use the\n" "`match` statement to extract the data from each variant:" msgstr "" -"Você pode definir enums mais ricos onde as variantes carregam dados. Você pode então usar o\n" +"Você pode definir enums mais ricos onde as variantes carregam dados. Você pode então usar a\n" "instrução `match` para extrair os dados de cada variante:" #: src/enums/variant-payloads.md:6 @@ -5698,7 +5904,7 @@ msgid "" " }\n" "}" msgstr "" -"#[rustfmt::pular]\n" +"#[rustfmt::skip]\n" "fn inspect(event: WebEvent) {\n" " match event{\n" " WebEvent::PageLoad => println!(\"página carregada\"),\n" @@ -5744,8 +5950,10 @@ msgid "" "* `WebEvent::Click { ... }` is not exactly the same as `WebEvent::Click(Click)` with a top level `struct Click { ... }`. " "The inlined version cannot implement traits, for example." msgstr "" -"* No exemplo acima, acessar o `char` em `KeyPress`, ou `x` e `y` em `Click` só funciona dentro de uma instrução `match`.\n" +"* No exemplo acima, acessar o `char` em `KeyPress`, ou `x` e `y` em `Click` só funciona dentro de uma instrução `match`\n" +" ou em uma expressão `if let`.\n" "* `match` inspeciona um campo discriminante oculto no `enum`.\n" +"* É possível recuperar o campo discriminante chamando `std::mem::discriminant()`.\n" "* `WebEvent::Click { ... }` não é exatamente o mesmo que `WebEvent::Click(Click)` com um `struct Click { ... }` de nível " "superior. A versão embutida não pode implementar traits, por exemplo." @@ -5755,7 +5963,7 @@ msgstr "# Tamanhos de Enum" #: src/enums/sizes.md:3 msgid "Rust enums are packed tightly, taking constraints due to alignment into account:" -msgstr "Rust enums são empacotados firmemente, levando em consideração as restrições devido ao alinhamento:" +msgstr "Enums, em Rust, são empacotados firmemente, levando em consideração as restrições devido ao alinhamento:" #: src/enums/sizes.md:5 msgid "" @@ -5772,6 +5980,12 @@ msgid "" " };\n" "}" msgstr "" +"macro_rules! dbg_size {\n" +" ($t:ty) => {\n" +" println!(\"{}: tamano: {} byte(s), alinhamento: {} byte(s)\",\n" +" stringify!($t), size_of::<$t>(), align_of::<$t>());\n" +" };\n" +"}" #: src/enums/sizes.md:15 msgid "" @@ -5810,7 +6024,7 @@ msgstr "" #: src/enums/sizes.md:37 msgid "* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout.html)." -msgstr "* Consulte a [Referência Rust](https://doc.rust-lang.org/reference/type-layout.html)." +msgstr "* Consulte a [Referência do Rust](https://doc.rust-lang.org/reference/type-layout.html)." #: src/enums/sizes.md:39 msgid "" @@ -5829,14 +6043,14 @@ msgid "" msgstr "" "
\n" " \n" -"Points chave:\n" -" * Internamente Rust está usando um campo (discriminante) para acompanhar a variante enum.\n" +"Pontos chave:\n" +" * Internamente Rust está usando um campo (discriminante) para acompanhar a variante da enum.\n" " * A Enum `Bar` demonstra que existe uma maneira de controlar o valor e o tipo discriminante. Se `repr` for removido, o " "tipo discriminante ocupa 2 bytes, porque 10001 cabe 2 bytes.\n" " * Como uma otimização de nicho, um discriminante de Enum é mesclado com o ponteiro para que `Option<&Foo>` seja do mesmo " "tamanho que `&Foo`.\n" " * `Option` é outro exemplo de empacotamento compacto.\n" -" * Para [alguns tipos](https://doc.rust-lang.org/std/option/#representation), Rust garante que `size_of::()` é igual a " +" * Para [alguns tipos](https://doc.rust-lang.org/std/option/#representation), Rust garante que o `size_of::()` é igual a " "`size_of:: >()`.\n" " * Tipos de tamanho zero permitem a implementação eficiente de `HashSet` usando `HashMap` com `()` como valor." @@ -5845,7 +6059,9 @@ msgid "" "Example code if you want to show how the bitwise representation *may* look like in practice.\n" "It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally " "unsafe." -msgstr "" +msgstr "Código de exemplo se você quiser mostrar como a representação bit a bit *pode* parecer na prática.\n" +" É importante observar que o compilador não oferece garantias quanto a essa representação, portanto, isso é totalmente " +"inseguro." #: src/enums/sizes.md:52 msgid "" @@ -5872,6 +6088,13 @@ msgid "" " dbg_bits!(false, u8);\n" " dbg_bits!(true, u8);" msgstr "" +"fn main() {\n" +" // TOTALMENTE INSEGURO. Rust não oferece nenhuma garantia sobre a\n" +" // representação bit a bit de tipos.\n" +" unsafe {\n" +" println!(\"Representação bit a bit do tipo bool\");\n" +" dbg_bits!(false, u8);\n" +" dbg_bits!(true, u8);" #: src/enums/sizes.md:69 msgid "" @@ -5880,6 +6103,10 @@ msgid "" " dbg_bits!(Some(false), u8);\n" " dbg_bits!(Some(true), u8);" msgstr "" +" println!(\"Representação bit a bit do tipo Option\");\n" +" dbg_bits!(None::, u8);\n" +" dbg_bits!(Some(false), u8);\n" +" dbg_bits!(Some(true), u8);" #: src/enums/sizes.md:74 msgid "" @@ -5889,6 +6116,11 @@ msgid "" " dbg_bits!(Some(None::), u8);\n" " dbg_bits!(None::>, u8);" msgstr "" +" println!(\"Representação bit a bit do tipo Option>\");\n" +" dbg_bits!(Some(Some(false)), u8);\n" +" dbg_bits!(Some(Some(true)), u8);\n" +" dbg_bits!(Some(None::), u8);\n" +" dbg_bits!(None::>, u8);" #: src/enums/sizes.md:80 msgid "" @@ -5899,10 +6131,16 @@ msgid "" "}\n" "```" msgstr "" +" println!(\"Representação bit a bit do tipo Option<&i32>\");\n" +" dbg_bits!(None::<&i32>, usize);\n" +" dbg_bits!(Some(&0i32), usize);\n" +" }\n" +"}\n" +"```" #: src/enums/sizes.md:87 msgid "More complex example if you want to discuss what happens when we chain more than 256 `Option`s together." -msgstr "" +msgstr "Exemplo mais complexo se você quiser discutir o que acontece quando encadeamos mais de 256 `Option` juntas." #: src/enums/sizes.md:89 msgid "" @@ -5930,6 +6168,17 @@ msgid "" " };\n" "}" msgstr "" +"// Macro para envolver um valor com Some() 2^n vezes onde n é o número de simbolos \"@\"\n" +"// É necessário aumentar o limite de recursão para utilizar essa macro.\n" +"macro_rules! many_options {\n" +" ($value:expr) => { Some($value) };\n" +" ($value:expr, @) => {\n" +" Some(Some($value))\n" +" };\n" +" ($value:expr, @ $($more:tt)+) => {\n" +" many_options!(many_options!($value, $($more)+), $($more)+)\n" +" };\n" +"}" #: src/enums/sizes.md:112 msgid "" @@ -5941,6 +6190,13 @@ msgid "" " assert_eq!(many_options!(false, @), Some(Some(false)));\n" " assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));" msgstr "" +"fn main() {\n" +" // TOTALMENTE INSEGURO. Rust não oferece nenhuma garantia sobre a\n" +" // representação bit a bit de tipos.\n" +" unsafe {\n" +" assert_eq!(many_options!(false), Some(false));\n" +" assert_eq!(many_options!(false, @), Some(Some(false)));\n" +" assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));" #: src/enums/sizes.md:120 msgid "" @@ -5948,6 +6204,9 @@ msgid "" " dbg_bits!(many_options!(false, @@@@@@@), u8);\n" " dbg_bits!(many_options!(true, @@@@@@@), u8);" msgstr "" +" println!(\"Representação bit a bit de uma cadeia de 128 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" +" dbg_bits!(many_options!(true, @@@@@@@), u8);" #: src/enums/sizes.md:124 msgid "" @@ -5955,6 +6214,9 @@ msgid "" " dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" " dbg_bits!(many_options!(true, @@@@@@@@), u16);" msgstr "" +" println!(\"Representação bit a bit de uma cadeia de 256 Option's.\");\n" +" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(true, @@@@@@@@), u16);" #: src/enums/sizes.md:128 msgid "" @@ -5966,6 +6228,13 @@ msgid "" "}\n" "```" msgstr "" +" println!(\"Representação bit a bit de uma cadeia de 257 Option's.\");\n" +" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" +" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" +" }\n" +"}\n" +"```" #: src/methods.md:3 msgid "" @@ -5983,9 +6252,9 @@ msgid "" " }\n" "}" msgstr "" -"impl Person {\n" -" fn say_hello(&self) {\n" -" println!(\"Olá, meu name é {}\", self.name);\n" +"impl Pessoa {\n" +" fn diz_ola(&self) {\n" +" println!(\"Olá, meu nome é {}\", self.nome);\n" " }\n" "}" @@ -6001,11 +6270,11 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let peter = Person {\n" -" name: String::from(\"Peter\"),\n" -" age: 27,\n" +" let pedro = Pessoa {\n" +" nome: String::from(\"Pedro\"),\n" +" idade: 27,\n" " };\n" -" peter.say_hello();\n" +" pedro.diz_ola();\n" "}\n" "```" @@ -6027,35 +6296,35 @@ msgid "" " \n" "
" msgstr "" -"Points chave:\n" +"Pontos chave:\n" "* Pode ser útil introduzir métodos comparando-os com funções.\n" " * Métodos são chamados em uma instância de um tipo (como struct ou enum), o primeiro parâmetro representa a instância " "como `self`.\n" " * Os desenvolvedores podem optar por usar métodos para aproveitar a sintaxe do receptor do método e ajudar a mantê-los " "mais organizados. Usando métodos, podemos manter todo o código de implementação em um local previsível.\n" -"* Highlight o uso da palavra-chave `self`, um receptor de método.\n" -" * Mostre que é um termo abreviado para `self:&Self` e talvez mostre como o name struct também poderia ser usado.\n" -" * Explique que Self é um alias de tipo para o tipo em que o bloco `impl` está e pode ser usado em qualquer outro lugar no " +"* Destaque o uso da palavra-chave `self`, um receptor de método.\n" +" * Mostre que é um termo abreviado para `self:&Self` e talvez mostre como o nome da struct também poderia ser usado.\n" +" * Explique que `Self` é um apelido de tipo para o tipo em que o bloco `impl` está e pode ser usado em qualquer outro lugar no " "bloco.\n" -" * Observe como self é usado como outras Structs e a notação de Point pode ser usada para se referir a campos " +" * Observe como _self_ é usado com outras _Structs_ e a notação de _ponto_ pode ser usada para se referir a campos " "individuais.\n" " * Este pode ser um bom momento para demonstrar como `&self` difere de `self` modificando o código e tentando executar " -"say_hello duas vezes.\n" -"* Descrevemos a distinção entre os receptores de método a seguir.\n" +"`diz_ola` duas vezes.\n" +"* Descreveremos a distinção entre os receptores de método a seguir.\n" " \n" "
" #: src/methods/receiver.md:1 msgid "# Method Receiver" -msgstr "# Método Receptor" +msgstr "# Receptores de métodos" #: src/methods/receiver.md:3 msgid "" "The `&self` above indicates that the method borrows the object immutably. There\n" "are other possible receivers for a method:" msgstr "" -"O `&self` acima indica que o método toma emprestado o objeto imutavelmente. Lá\n" -"são outros receptores possíveis para um método:" +"O `&self` acima indica que o método toma emprestado o objeto imutavelmente. Abaixo há\n" +"outros receptores possíveis para um método:" #: src/methods/receiver.md:6 msgid "" @@ -6072,18 +6341,18 @@ msgid "" "* No receiver: this becomes a static method on the struct. Typically used to\n" " create constructors which are called `new` by convention." msgstr "" -"* `&self`: pega emprestado o objeto do chamador usando um compartilhado e imutável\n" -" referência. O objeto pode ser usado novamente depois.\n" -"* `&mut self`: pega emprestado o objeto do chamador usando um único e mutável\n" -" referência. O objeto pode ser usado novamente depois.\n" -"* `self`: toma posse do objeto e o afasta do chamador. o\n" +"* `&self`: pega emprestado o objeto do chamador como uma referência compartilhada\n" +" e mutável. O objeto pode ser usado novamente depois.\n" +"* `&mut self`: pega emprestado o objeto do chamador como uma referência única\n" +" e mutável. O objeto pode ser usado novamente depois.\n" +"* `self`: toma posse do objeto e o afasta do chamador.\n" " O método se torna o proprietário do objeto. O objeto será descartado (desalocado)\n" " quando o método retorna, a menos que sua ownership seja explicitamente\n" -" transmitido.\n" +" transmitida.\n" "* `mut self`: o mesmo que acima, mas enquanto o método possui o objeto, ele pode\n" -" transformá-lo também. A ownership completa não significa automaticamente mutabilage.\n" +" alterá-lo também. A ownership completa não significa automaticamente mutabilidade.\n" "* Sem receptor: isso se torna um método static na estrutura. Normalmente usado para\n" -" crie construtores que são chamados `new` por convenção." +" criar construtores que, por convenção, são chamados `new`." #: src/methods/receiver.md:19 msgid "" @@ -6093,7 +6362,7 @@ msgid "" msgstr "" "Além das variantes de `self`, também existem\n" "[tipos especiais de wrapper](https://doc.rust-lang.org/reference/special-types-and-traits.html)\n" -"podem ser tipos de receptores, como `Box`." +"que podem ser tipos de receptores, como `Box`." #: src/methods/receiver.md:23 msgid "" @@ -6108,8 +6377,8 @@ msgstr "" "
\n" " \n" "Considere enfatizar \"compartilhado e imutável\" e \"único e mutável\". Essas restrições sempre vêm\n" -"juntos no Rust devido às regras do verificador emprestado, e `self` não é exceção. Não será possível\n" -"referenciar um struct de vários locais e chamar um método mutante (`&mut self`) nele.\n" +"juntos no Rust devido às regras do verificador de empréstimo, e `self` não é uma exceção. Não será possível\n" +"referenciar um struct de vários locais e chamar um método mutável (`&mut self`) nele.\n" " \n" "
" @@ -6118,7 +6387,6 @@ msgid "# Example" msgstr "# Exemplo" #: src/methods/example.md:3 -#, fuzzy msgid "" "```rust,editable\n" "#[derive(Debug)]\n" @@ -6129,8 +6397,8 @@ msgid "" msgstr "" "```rust, editable\n" "#[derive(Debug)]\n" -"struct Raça {\n" -" name: String,\n" +"struct Corrida {\n" +" nome: String,\n" " voltas: Vec,\n" "}" @@ -6141,20 +6409,22 @@ msgid "" " Race { name: String::from(name), laps: Vec::new() }\n" " }" msgstr "" +"impl Corrida {\n" +" fn new(nome: &str) -> Corrida { // Um método estático, sem a definição de um receptor.\n" +" Corrida { nome: String::from(nome), voltas: Vec::new() }\n" +" }" #: src/methods/example.md:15 -#, fuzzy msgid "" " fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write access to self\n" " self.laps.push(lap);\n" " }" msgstr "" -" fn add_lap(&mut self, lap: i32) { // Acesso de leitura e gravação emprestado exclusivo para self\n" -" self.laps.push(volta);\n" +" fn adiciona_volta(&mut self, volta: i32) { // Acesso emprestado de leitura e gravação exclusivo para self\n" +" self.voltas.push(volta);\n" " }" #: src/methods/example.md:19 -#, fuzzy msgid "" " fn print_laps(&self) { // Shared and read-only borrowed access to self\n" " println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" @@ -6163,10 +6433,10 @@ msgid "" " }\n" " }" msgstr "" -" fn print_laps(&self) { // Acesso emprestado compartilhado e somente leitura a si mesmo\n" -" println!(\"Gravadas {} voltas para {}:\", self.laps.len(), self.name);\n" -" for (idx, lap) in self.laps.iter().enumerate() {\n" -" println!(\"Volta {idx}: {volta} seg\");\n" +" fn imprime_voltas(&self) { // Acesso emprestado compartilhado e somente leitura para self\n" +" println!(\"Gravadas {} voltas para {}:\", self.voltas.len(), self.nome);\n" +" for (idx, volta) in self.voltas.iter().enumerate() {\n" +" println!(\"Volta {idx}: {volta} seg.\");\n" " }\n" " }" @@ -6178,14 +6448,13 @@ msgid "" " }\n" "}" msgstr "" -" fn finish(self) { // ownership exclusiva de self\n" -" let total = self.laps.iter().sum::();\n" -" println!(\"A corrida {} terminou, tempo total da volta: {}\", self.name, total);\n" +" fn finaliza(self) { // ownership exclusiva de self\n" +" let total = self.voltas.iter().sum::();\n" +" println!(\"A corrida {} terminou, tempo total da volta: {}\", self.nome, total);\n" " }\n" "}" #: src/methods/example.md:32 -#, fuzzy msgid "" "fn main() {\n" " let mut race = Race::new(\"Monaco Grand Prix\");\n" @@ -6200,14 +6469,14 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let mut race = Race::new(\"Grande Prêmio de Mônaco\");\n" -" corrida.add_lap(70);\n" -" corrida.add_lap(68);\n" -" corrida.print_laps();\n" -" corrida.add_lap(71);\n" -" corrida.print_laps();\n" -" race.finish();\n" -" // corrida.add_lap(42);\n" +" let mut corrida = Corrida::new(\"Grande Prêmio de Mônaco\");\n" +" corrida.adiciona_volta(70);\n" +" corrida.adiciona_volta(68);\n" +" corrida.imprime_voltas();\n" +" corrida.adiciona_volta(71);\n" +" corrida.imprime_voltas();\n" +" corrida.finaliza();\n" +" // corrida.adiciona_volta(42);\n" "}\n" "```" @@ -6228,7 +6497,7 @@ msgid "" msgstr "" "
\n" " \n" -"Points chave:\n" +"Pontos chave:\n" "* Todos os quatro métodos aqui usam um receptor de método diferente.\n" " * Você pode apontar como isso muda o que a função pode fazer com os valores das variáveis e se/como ela pode ser usada " "novamente em `main`.\n" @@ -6236,7 +6505,8 @@ msgstr "" "* Observe que, embora os receptores do método sejam diferentes, as funções não estáticas são chamadas da mesma maneira no " "corpo principal. Rust permite referenciar e desreferenciar automaticamente ao chamar métodos. Rust adiciona automaticamente " "`&`, `*`, `muts` para que esse objeto corresponda à assinatura do método.\n" -"* Você pode apontar que `print_laps` está usando um vetor iterado. Descrevemos os vetores com mais detalhes à tarde." +"* Você pode apontar que `print_laps` está usando um vetor iterado. Descreveremos os vetores com mais\n" +"detalhes à tarde." #: src/pattern-matching.md:1 msgid "# Pattern Matching" @@ -6247,8 +6517,8 @@ msgid "" "The `match` keyword let you match a value against one or more _patterns_. The\n" "comparisons are done from top to bottom and the first match wins." msgstr "" -"A palavra-chave `match` permite que você corresponda um valor a um ou mais _patterns_. o\n" -"as comparações são feitas de cima para baixo e a primeira partida vence." +"A palavra-chave `match` permite que você corresponda um valor a um ou mais _padrões_ (_patterns_). As\n" +" comparações são feitas de cima para baixo e a primeira correspondência encontrada é selecionada." #: src/pattern-matching.md:6 msgid "The patterns can be simple values, similarly to `switch` in C and C++:" @@ -6278,7 +6548,7 @@ msgstr "" " match input {\n" " 'q' => println!(\"Sair\"),\n" " 'a' | 's' | 'w' | 'd' => println!(\"Movendo-se\"),\n" -" '0'..='9' => println!(\"Number input\"),\n" +" '0'..='9' => println!(\"Entrada numérica\"),\n" " _ => println!(\"Algo mais\"),\n" " }\n" "}\n" @@ -6307,8 +6577,8 @@ msgid "" msgstr "" "
\n" " \n" -"Points chave:\n" -"* Você pode apontar como alguns caracteres específicos estão sendo usados quando em um padrão\n" +"Pontos chave:\n" +"* Você pode apontar como alguns caracteres específicos podem ser usados em um padrão\n" " * `|` como um `ou`\n" " * `..` pode expandir o quanto for necessário\n" " * `1..=5` representa um intervalo inclusivo\n" @@ -6323,7 +6593,7 @@ msgstr "" #: src/pattern-matching/destructuring-enums.md:1 msgid "# Destructuring Enums" -msgstr "# Desestruturando Enums" +msgstr "# Desestruturando enunerações (Enums)" #: src/pattern-matching/destructuring-enums.md:3 msgid "" @@ -6331,7 +6601,7 @@ msgid "" "you inspect the structure of your types. Let us start with a simple `enum` type:" msgstr "" "Os padrões também podem ser usados para vincular variáveis a partes de seus valores. É assim\n" -"você inspeciona a estrutura de seus tipos. Vamos começar com um tipo `enum` simples:" +"que você inspeciona a estrutura de seus tipos. Vamos começar com um tipo `enum` simples:" #: src/pattern-matching/destructuring-enums.md:6 msgid "" @@ -6341,6 +6611,11 @@ msgid "" " Err(String),\n" "}" msgstr "" +"```rust,editable\n" +"enum Result {\n" +" Ok(i32),\n" +" Err(String),\n" +"}" #: src/pattern-matching/destructuring-enums.md:12 msgid "" @@ -6352,11 +6627,11 @@ msgid "" " }\n" "}" msgstr "" -"fn divide_in_two(n: i32) -> Result {\n" +"fn divide_por_dois(n: i32) -> Result {\n" " if n % 2 == 0 {\n" " Result::Ok(n/2)\n" " } else {\n" -" Result::Err(format!(\"não é possível dividir {} em duas partes iguais\", n))\n" +" Result::Err(format!(\"Não é possível dividir {} em duas partes iguais\", n))\n" " }\n" "}" @@ -6373,9 +6648,9 @@ msgid "" msgstr "" "fn main() {\n" " let n = 100;\n" -" match divide_in_two(n) {\n" +" match divide_por_dois(n) {\n" " Result::Ok(metade) => println!(\"{n} dividido em dois é {metade}\"),\n" -" Result::Err(msg) => println!(\"desculpe, ocorreu um erro: {msg}\"),\n" +" Result::Err(msg) => println!(\"Desculpe, ocorreu um erro: {msg}\"),\n" " }\n" "}\n" "```" @@ -6386,8 +6661,8 @@ msgid "" "arm, `half` is bound to the value inside the `Ok` variant. In the second arm,\n" "`msg` is bound to the error message." msgstr "" -"Aqui usamos os braços para _desestruturar_ o valor `Resultado`. Em primeiro\n" -"arm, `half` está vinculado ao valor dentro da variante `Ok`. No segundo braço,\n" +"Aqui usamos a verificação de correspondência para _desestruturar_ o valor contido em `Result`. Na primeira\n" +"verificação de correspondência, `metade` está vinculado ao valor dentro da variante `Ok`. Na segunda,\n" "`msg` está vinculado à mensagem de erro." #: src/pattern-matching/destructuring-enums.md:35 @@ -6397,14 +6672,14 @@ msgid "" "* You can try adding a third variant to the enum definition and displaying the errors when running the code. Point out the " "places where your code is now inexhaustive and how the compiler tries to give you hints." msgstr "" -"Points chave:\n" +"Pontos chave:\n" "* A expressão `if`/`else` está retornando um enum que é posteriormente descompactado com um `match`.\n" "* Você pode tentar adicionar uma terceira variante à definição de Enum e exibir os erros ao executar o código. Aponte os " -"lugares onde seu código agora é inexaustivo e como o compilador tenta lhe dar dicas." +"lugares onde seu código agora é \"não exaustivo\" e como o compilador tenta lhe dar dicas." #: src/pattern-matching/destructuring-structs.md:1 msgid "# Destructuring Structs" -msgstr "# Desestruturando Structs" +msgstr "# Desestruturando estruturas (Structs)" #: src/pattern-matching/destructuring-structs.md:3 msgid "You can also destructure `structs`:" @@ -6438,7 +6713,7 @@ msgid "" "```\n" "
" msgstr "" -"#[rustfmt::pular]\n" +"#[rustfmt::skip]\n" "fn main() {\n" " let foo = Foo { x: (1, 2), y: 3 };\n" " match foo {\n" @@ -6455,17 +6730,20 @@ msgid "" "* Add a new field to `Foo` and make changes to the pattern as needed.\n" "
" msgstr "" +"* Altere os valores literais em `foo` para corresponderem com outros padrões.\n" +"* Adicione um novo campo em `Foo` e faça as alterações no padrão" +" conforme necessário.\n" +"
" #: src/pattern-matching/destructuring-arrays.md:1 msgid "# Destructuring Arrays" -msgstr "# Desestruturando Arrays" +msgstr "# Desestruturando Vetores" #: src/pattern-matching/destructuring-arrays.md:3 msgid "You can destructure arrays, tuples, and slices by matching on their elements:" -msgstr "Você pode desestruturar arrays, tuplas e slices combinando seus elementos:" +msgstr "Você pode desestruturar vetores, tuplas e slices combinando seus elementos:" #: src/pattern-matching/destructuring-arrays.md:5 -#, fuzzy msgid "" "```rust,editable\n" "#[rustfmt::skip]\n" @@ -6481,7 +6759,7 @@ msgid "" "```" msgstr "" "```rust, editable\n" -"#[rustfmt::pular]\n" +"#[rustfmt::skip]\n" "fn main() {\n" " let triplo = [0, -2, 3];\n" " println!(\"Fale-me sobre {triplo:?}\");\n" @@ -6495,7 +6773,7 @@ msgstr "" #: src/pattern-matching/destructuring-arrays.md:20 msgid "* Destructuring of slices of unknown length also works with patterns of fixed length." -msgstr "" +msgstr "* Desestruturar slices de tamanho desconhecido também funciona com padrões de tamanho fixo." #: src/pattern-matching/destructuring-arrays.md:22 msgid "" @@ -6521,18 +6799,30 @@ msgid "" "* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`\n" "
" msgstr "" +"#[rustfmt::skip]\n" +"fn inspect(slice: &[i32]) {\n" +" println!(\"Fale-me sobre {slice:?}\");\n" +" match slice {\n" +" &[0, y, z] => println!(\"O primeiro é 0, y = {y}, e z = {z}\"),\n" +" &[1, ..] => println!(\"O primeiro é 1 e o restante é ignorado\"),\n" +" _ => println!(\"Todos os elementos foram ignorados\"),\n" +" }\n" +"}\n" +"```\n" +"* Mostre as correspondências com o final do padrão usando `[.., b]` e `[a@..,b]`\n" +"" #: src/pattern-matching/match-guards.md:1 msgid "# Match Guards" -msgstr "# Guardas de jogo" +msgstr "# Guardas de correspondência (match guards)" #: src/pattern-matching/match-guards.md:3 msgid "" "When matching, you can add a _guard_ to a pattern. This is an arbitrary Boolean\n" "expression which will be executed if the pattern matches:" msgstr "" -"Ao match, você pode adicionar um _guard_ a um padrão. Este é um booleano arbitrário\n" -"expressão que será executada se o padrão corresponder:" +"Ao verificar uma correspondência, você pode adicionar um _guarda_ para um padrão. É uma expressão booleana\n" +"que será executada se o padrão corresponder:" #: src/pattern-matching/match-guards.md:6 msgid "" @@ -6551,7 +6841,7 @@ msgid "" "```" msgstr "" "```rust, editable\n" -"#[rustfmt::pular]\n" +"#[rustfmt::skip]\n" "fn main() {\n" " let pair = (2, -2);\n" " println!(\"Fale-me sobre {pair:?}\");\n" @@ -6577,13 +6867,14 @@ msgid "" "* The condition defined in the guard applies to every expression in a pattern with an `|`.\n" "" msgstr "" -"Points chave:\n" -"* Match guards como um recurso de sintaxe separado são importantes e necessários.\n" -"* Eles não são iguais à expressão 'if' separada dentro do braço de correspondência. Uma expressão `if` dentro do bloco de " -"ramificação (depois de `=>`) acontece depois que o braço de correspondência é selecionado. A falha na condição `if` dentro " -"desse bloco não resultará em outros braços\n" -"da expressão `match` original sendo considerada.\n" -"* Você pode usar as variáveis definidas no padrão em sua expressão if.\n" +"Pontos chave:\n" +"* Guardas de correspondência, como um recurso de sintaxe separado, são importantes e necessários.\n" +"Permitem expressar ideias mais complexas do que somente o padrão permitiria.\n" +"* Eles não são iguais à expressão `if` separada dentro do bloco de correspondência. Uma expressão `if` dentro do bloco de " +"ramificação (depois de `=>`) acontece depois que a correspondência é selecionada. A falha na condição `if` dentro " +"desse bloco não resultará em outras verificações de correspondência\n" +"da expressão `match` original serem consideradas.\n" +"* Você pode usar as variáveis definidas no padrão em sua expressão `if`.\n" "* A condição definida na guarda se aplica a todas as expressões em um padrão com um `|`.\n" "" @@ -6601,7 +6892,7 @@ msgstr "* Estrutura simples que rastreia as estatísticas de saúde." #: src/exercises/day-2/morning.md:7 msgid "* Multiple structs and enums for a drawing library." -msgstr "* Várias Structs e enumerações para uma biblioteca de desenho." +msgstr "* Várias estruturas e enumerações para uma biblioteca de desenho." #: src/exercises/day-2/health-statistics.md:1 msgid "# Health Statistics" @@ -6613,7 +6904,7 @@ msgid "" "need to keep track of users' health statistics." msgstr "" "Você está trabalhando na implementação de um sistema de monitoramento de saúde. Como parte disso, você\n" -"precisam acompanhar as estatísticas de saúde dos usuários." +"precisa acompanhar as estatísticas de saúde dos usuários." #: src/exercises/day-2/health-statistics.md:6 msgid "" @@ -6621,17 +6912,16 @@ msgid "" "struct definition. Your goal is to implement the stubbed out methods on the\n" "`User` `struct` defined in the `impl` block." msgstr "" -"Você começará com algumas funções fragmentadas em um bloco `impl`, bem como em um bloco `User`\n" -"definição de struct. Seu objetivo é implementar os métodos stubbed out no\n" -"`User` `struct` definido no bloco `impl`." +"Você começará com algumas funções fragmentadas em um bloco `impl` e também com a definição da estrutura `User`.\n" +"Seu objetivo é implementar os métodos esboçados para a\n" +"`struct` `User` definidos no bloco `impl`." #: src/exercises/day-2/health-statistics.md:10 msgid "" "Copy the code below to and fill in the missing\n" "methods:" msgstr "" -"Copie o código abaixo para e preencha os campos que faltam\n" -"métodos:" +"Copie o código abaixo para e implemente os métodos:" #: src/exercises/day-2/health-statistics.md:17 msgid "" @@ -6641,10 +6931,10 @@ msgid "" " weight: f32,\n" "}" msgstr "" -"struct User {\n" -" name: String,\n" -" age: u32,\n" -" weight: f32,\n" +"struct Usuario {\n" +" nome: String,\n" +" idade: u32,\n" +" peso: f32,\n" "}" #: src/exercises/day-2/health-statistics.md:23 @@ -6654,8 +6944,8 @@ msgid "" " unimplemented!()\n" " }" msgstr "" -"impl User {\n" -" pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +"impl Usuario {\n" +" pub fn new(nome: String, idade: u32, peso: f32) -> Self {\n" " unimplemented!()\n" " }" @@ -6665,7 +6955,7 @@ msgid "" " unimplemented!()\n" " }" msgstr "" -" pub fn name(&self) -> &str {\n" +" pub fn nome(&self) -> &str {\n" " unimplemented!()\n" " }" @@ -6675,7 +6965,7 @@ msgid "" " unimplemented!()\n" " }" msgstr "" -" pub fn age(&self) -> u32 {\n" +" pub fn idade(&self) -> u32 {\n" " unimplemented!()\n" " }" @@ -6685,7 +6975,7 @@ msgid "" " unimplemented!()\n" " }" msgstr "" -" pub fn weight(&self) -> f32 {\n" +" pub fn peso(&self) -> f32 {\n" " unimplemented!()\n" " }" @@ -6695,7 +6985,7 @@ msgid "" " unimplemented!()\n" " }" msgstr "" -" pub fn set_age(&mut self, new_age: u32) {\n" +" pub fn setar_idade(&mut self, nova_idade: u32) {\n" " unimplemented!()\n" " }" @@ -6706,7 +6996,7 @@ msgid "" " }\n" "}" msgstr "" -" pub fn set_weight(&mut self, new_weight: f32) {\n" +" pub fn setar_peso(&mut self, novo_peso: f32) {\n" " unimplemented!()\n" " }\n" "}" @@ -6719,8 +7009,8 @@ msgid "" "}" msgstr "" "fn main() {\n" -" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" println!(\"Tenho {} e minha age é {}\", bob.name(), bob.age());\n" +" let bob = Usuario::new(String::from(\"Bob\"), 32, 155.2);\n" +" println!(\"Sou {} e minha idade é {}\", bob.nome(), bob.idade());\n" "}" #: src/exercises/day-2/health-statistics.md:54 @@ -6732,9 +7022,9 @@ msgid "" "}" msgstr "" "#[test]\n" -"fn test_weight() {\n" -" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" assert_eq!(bob.weight(), 155.2);\n" +"fn test_peso() {\n" +" let bob = Usuario::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.peso(), 155.2);\n" "}" #: src/exercises/day-2/health-statistics.md:60 @@ -6749,17 +7039,17 @@ msgid "" "```" msgstr "" "#[test]\n" -"fn test_set_age() {\n" -" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" assert_eq!(bob.age(), 32);\n" -" bob.set_age(33);\n" -" assert_eq!(bob.age(), 33);\n" +"fn test_setar_idade() {\n" +" let mut bob = Usuario::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.idade(), 32);\n" +" bob.setar_idade(33);\n" +" assert_eq!(bob.idade(), 33);\n" "}\n" "```" #: src/exercises/day-2/points-polygons.md:1 msgid "# Polygon Struct" -msgstr "# Estrutura do Polígono" +msgstr "# Estrutura para polígono" #: src/exercises/day-2/points-polygons.md:3 msgid "" @@ -6767,9 +7057,9 @@ msgid "" "to and fill in the missing methods to make the\n" "tests pass:" msgstr "" -"Vamos criar uma estrutura `Polygon` que contém alguns Points. Copie o código abaixo\n" -"para e preencha os métodos que faltam para fazer o\n" -"tests passam:" +"Vamos criar uma estrutura `Poligono` que contém alguns `Pontos`. Copie o código abaixo\n" +"para e preencha os métodos que faltam para fazer os\n" +"testes passarem:" #: src/exercises/day-2/points-polygons.md:7 src/exercises/day-2/luhn.md:23 src/exercises/day-2/strings-iterators.md:12 msgid "" @@ -6787,8 +7077,8 @@ msgid "" " // add fields\n" "}" msgstr "" -"pub struct Point {\n" -" // adiciona campos\n" +"pub struct Ponto {\n" +" // adicione os campos\n" "}" #: src/exercises/day-2/points-polygons.md:15 @@ -6797,52 +7087,48 @@ msgid "" " // add methods\n" "}" msgstr "" -"impl Point {\n" -" // adiciona métodos\n" +"impl Ponto {\n" +" // adicione os métodos\n" "}" #: src/exercises/day-2/points-polygons.md:19 -#, fuzzy msgid "" "pub struct Polygon {\n" " // add fields\n" "}" msgstr "" -"pub struct Polígono {\n" -" // adiciona campos\n" +"pub struct Poligono {\n" +" // adicione os campos\n" "}" #: src/exercises/day-2/points-polygons.md:23 -#, fuzzy msgid "" "impl Polygon {\n" " // add methods\n" "}" msgstr "" -"impl Polígono {\n" -" // adiciona métodos\n" +"impl Poligono {\n" +" // adicione os métodos\n" "}" #: src/exercises/day-2/points-polygons.md:27 -#, fuzzy msgid "" "pub struct Circle {\n" " // add fields\n" "}" msgstr "" -"pub struct Círculo {\n" -" // adiciona campos\n" +"pub struct Circulo {\n" +" // adicione os campos\n" "}" #: src/exercises/day-2/points-polygons.md:31 -#, fuzzy msgid "" "impl Circle {\n" " // add methods\n" "}" msgstr "" -"impl Círculo {\n" -" // adiciona métodos\n" +"impl Circulo {\n" +" // adicione os métodos\n" "}" #: src/exercises/day-2/points-polygons.md:35 @@ -6852,9 +7138,9 @@ msgid "" " Circle(Circle),\n" "}" msgstr "" -"pub enum Shape {\n" -" Polygon(Polygon),\n" -" Circle(Circle),\n" +"pub enum Forma {\n" +" Poligono(Poligono),\n" +" Circulo(Circulo),\n" "}" #: src/exercises/day-2/points-polygons.md:40 src/testing/test-modules.md:15 @@ -6873,7 +7159,7 @@ msgid "" " (x * 100.0).round() / 100.0\n" " }" msgstr "" -" fn round_two_digits(x: f64) -> f64 {\n" +" fn arredonda_dois_digitos(x: f64) -> f64 {\n" " (x * 100.0).round() / 100.0\n" " }" @@ -6886,9 +7172,9 @@ msgid "" " }" msgstr "" " #[test]\n" -" fn test_point_magnitude() {\n" -" let p1 = Point::new(12, 13);\n" -" assert_eq!(round_two_digits(p1.magnitude()), 17,69);\n" +" fn test_magnitude_ponto() {\n" +" let p1 = Ponto::new(12, 13);\n" +" assert_eq!(arredonda_dois_digitos(p1.magnitude()), 17.69);\n" " }" #: src/exercises/day-2/points-polygons.md:54 src/exercises/day-2/solutions-morning.md:175 @@ -6901,10 +7187,10 @@ msgid "" " }" msgstr "" " #[test]\n" -" fn test_point_dist() {\n" -" let p1 = Point::new(10, 10);\n" -" let p2 = Point::new(14, 13);\n" -" assert_eq!(round_two_digits(p1.dist(p2)), 5,00);\n" +" fn test_distancia_pontos() {\n" +" let p1 = Ponto::new(10, 10);\n" +" let p2 = Ponto::new(14, 13);\n" +" assert_eq!(arredonda_dois_digitos(p1.dist(p2)), 5.00);\n" " }" #: src/exercises/day-2/points-polygons.md:61 src/exercises/day-2/solutions-morning.md:182 @@ -6917,10 +7203,10 @@ msgid "" " }" msgstr "" " #[test]\n" -" fn test_point_add() {\n" -" let p1 = Point::new(16, 16);\n" -" let p2 = p1 + Point::new(-4, 3);\n" -" assert_eq!(p2, Point::new(12, 19));\n" +" fn test_somar_pontos() {\n" +" let p1 = Ponto::new(16, 16);\n" +" let p2 = p1 + Ponto::new(-4, 3);\n" +" assert_eq!(p2, Ponto::new(12, 19));\n" " }" #: src/exercises/day-2/points-polygons.md:68 src/exercises/day-2/solutions-morning.md:189 @@ -6931,9 +7217,9 @@ msgid "" " let p2 = Point::new(16, 16);" msgstr "" " #[test]\n" -" fn test_polygon_left_most_point() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);" +" fn test_poligono_ponto_mais_a_esquerda() {\n" +" let p1 = Ponto::new(12, 13);\n" +" let p2 = Ponto::new(16, 16);" #: src/exercises/day-2/points-polygons.md:73 src/exercises/day-2/solutions-morning.md:194 msgid "" @@ -6943,10 +7229,10 @@ msgid "" " assert_eq!(poly.left_most_point(), Some(p1));\n" " }" msgstr "" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -" assert_eq!(poly.left_most_point(), Some(p1));\n" +" let mut poly = Poligono::new();\n" +" poly.adiciona_ponto(p1);\n" +" poly.adiciona_ponto(p2);\n" +" assert_eq!(poly.ponto_mais_a_esquerda(), Some(p1));\n" " }" #: src/exercises/day-2/points-polygons.md:79 src/exercises/day-2/solutions-morning.md:200 @@ -6957,9 +7243,9 @@ msgid "" " let p2 = Point::new(16, 16);" msgstr "" " #[test]\n" -" fn test_polygon_iter() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);" +" fn test_poligono_iter() {\n" +" let p1 = Ponto::new(12, 13);\n" +" let p2 = Ponto::new(16, 16);" #: src/exercises/day-2/points-polygons.md:84 src/exercises/day-2/solutions-morning.md:205 msgid "" @@ -6967,9 +7253,9 @@ msgid "" " poly.add_point(p1);\n" " poly.add_point(p2);" msgstr "" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);" +" let mut poly = Poligono::new();\n" +" poly.adiciona_ponto(p1);\n" +" poly.adiciona_ponto(p2);" #: src/exercises/day-2/points-polygons.md:88 src/exercises/day-2/solutions-morning.md:209 msgid "" @@ -6977,8 +7263,8 @@ msgid "" " assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" " }" msgstr "" -" let Points = poly.iter().cloned().collect::>();\n" -" assert_eq!(Points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" let pontos = poly.iter().cloned().collect::>();\n" +" assert_eq!(pontos, vec![Ponto::new(12, 13), Ponto::new(16, 16)]);\n" " }" #: src/exercises/day-2/points-polygons.md:92 @@ -7003,21 +7289,21 @@ msgid "" "}" msgstr "" " #[test]\n" -" fn test_shape_perimeters() {\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(Point::new(12, 13));\n" -" poly.add_point(Point::new(17, 11));\n" -" poly.add_point(Point::new(16, 16));\n" -" let shapes = vec![\n" -" Shape::de(poly),\n" -" Shape::de(Circle::new(Point::new(10, 20), 5)),\n" +" fn test_perimetros_da_forma() {\n" +" let mut poly = Poligono::new();\n" +" poly.adiciona_ponto(Ponto::new(12, 13));\n" +" poly.adiciona_ponto(Ponto::new(17, 11));\n" +" poly.adiciona_ponto(Ponto::new(16, 16));\n" +" let formas = vec![\n" +" Forma::from(poly),\n" +" Forma::from(Circulo::new(Ponto::new(10, 20), 5)),\n" " ];\n" -" let perimeters = shapes\n" +" let perimetros = formas\n" " .iter()\n" -" .map(Shape::perimeter)\n" -" .map(round_two_digits)\n" +" .map(Forma::perimetro)\n" +" .map(arredonda_dois_digitos)\n" " .collect::>();\n" -" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" assert_eq!(perimetros, vec![15.48, 31.42]);\n" " }\n" "}" @@ -7036,8 +7322,8 @@ msgid "" "Since the method signatures are missing from the problem statements, the key part\n" "of the exercise is to specify those correctly. Do not modify any of the tests." msgstr "" -"Como as assinaturas do método estão faltando nas declarações do problema, a parte principal\n" -"do exercício é especificá-los corretamente." +"Como as assinaturas dos métodos estão faltando nas declarações do problema, a parte principal\n" +"do exercício é especificá-las corretamente." #: src/exercises/day-2/points-polygons.md:120 msgid "" @@ -7049,7 +7335,7 @@ msgid "" msgstr "" "Outras partes interessantes do exercício:\n" " \n" -"* Derive um trait `Copy` para algumas Structs, já que em testes os métodos às vezes não emprestam seus argumentos.\n" +"* Derive um _trait_ `Copy` para algumas estruturas, já que em testes os métodos às vezes não emprestam seus argumentos.\n" "* Descubra que o trait `Add` deve ser implementado para que dois objetos sejam adicionados via \"+\"." #: src/control-flow.md:1 @@ -7066,7 +7352,7 @@ msgstr "" "Como vimos, `if` é uma expressão em Rust. É usado para condicionalmente\n" "avaliar um dos dois blocos, mas os blocos podem ter um valor que então se torna\n" "o valor da expressão `if`. Outras expressões de fluxo de controle funcionam de forma semelhante\n" -"em rust." +"em Rust." #: src/control-flow/blocks.md:1 msgid "# Blocks" @@ -7078,10 +7364,9 @@ msgid "" "block:" msgstr "" "Um bloco em Rust tem um valor e um tipo: o valor é a última expressão do\n" -"quadra:" +"bloco:" #: src/control-flow/blocks.md:6 -#, fuzzy msgid "" "```rust,editable\n" "fn main() {\n" @@ -7112,7 +7397,7 @@ msgstr "" " 3 + 4\n" " };\n" " println!(\"w: {w}\");\n" -" e * w\n" +" y * w\n" " };\n" " println!(\"z: {z}\");\n" " z - y\n" @@ -7136,6 +7421,10 @@ msgid "" " x + x\n" "}" msgstr "" +"```rust,editable\n" +"fn dobro(x: i32) -> i32 {\n" +" x + x\n" +"}" #: src/control-flow/blocks.md:33 msgid "" @@ -7144,10 +7433,14 @@ msgid "" "}\n" "```" msgstr "" +"fn main() {\n" +" println!(\"dobro: {}\", dobro(7));\n" +"}\n" +"```" #: src/control-flow/blocks.md:38 msgid "However if the last expression ends with `;`, then the resulting value and type is `()`." -msgstr "No entanto, se a última expressão terminar com `;`, o valor e o tipo resultante serão `()`." +msgstr "No entanto, se a última expressão terminar com `;` o valor e o tipo do retorno será `()`." #: src/control-flow/blocks.md:42 msgid "" @@ -7158,20 +7451,20 @@ msgid "" " \n" "" msgstr "" -"Points chave:\n" -"* O objetivo deste slide é mostrar que os blocos têm um tipo e valor em Rust.\n" -"* Você pode mostrar como o valor do bloco muda alterando a última linha do bloco. Por exemplo, adicionar/remover um Point e " -"vírgula ou usar um `return`.\n" +"Pontos chave:\n" +"* O objetivo deste slide é mostrar que os blocos têm um tipo e um valor em Rust.\n" +"* Você pode mostrar como o valor do bloco muda alterando a última linha do bloco. Por exemplo, adicionar/remover um ponto e " +"vírgula (`;`) ou usar um `return`.\n" " \n" "" #: src/control-flow/if-expressions.md:1 msgid "# `if` expressions" -msgstr "# expressões `if`" +msgstr "# Expressões Se (`if`)" #: src/control-flow/if-expressions.md:3 msgid "You use `if` very similarly to how you would in other languages:" -msgstr "Você usa `if` de forma muito semelhante a como faria em outros idiomas:" +msgstr "Você usa `if` de forma muito semelhante a como faria em outras linguagens:" #: src/control-flow/if-expressions.md:5 msgid "" @@ -7233,13 +7526,13 @@ msgid "" "" msgstr "" "Como `if` é uma expressão e deve ter um tipo específico, ambos os blocos de ramificação devem ter o mesmo tipo. Considere " -"mostrar o que acontece se você adicionar `;` depois de `x / 2` no segundo exemplo.\n" +"mostrar o que acontece se você adicionar um `;` depois de `x / 2` no segundo exemplo.\n" " \n" "" #: src/control-flow/if-let-expressions.md:1 msgid "# `if let` expressions" -msgstr "# expressões `if let`" +msgstr "# Expressões Se (`if let`)" #: src/control-flow/if-let-expressions.md:3 msgid "If you want to match a value against a pattern, you can use `if let`:" @@ -7262,9 +7555,9 @@ msgstr "" "fn main() {\n" " let arg = std::env::args().next();\n" " if let Some(value) = arg {\n" -" println!(\"name do programa: {value}\");\n" +" println!(\"nome do programa: {value}\");\n" " } else {\n" -" println!(\"Falta name?\");\n" +" println!(\"Falta o nome?\");\n" " }\n" "}\n" "```" @@ -7276,7 +7569,7 @@ msgid "" "Rust." msgstr "" "Consulte [correspondência de padrões](../pattern-matching.md) para obter mais detalhes sobre padrões em\n" -"rust." +"Rust." #: src/control-flow/if-let-expressions.md:21 msgid "" @@ -7292,11 +7585,11 @@ msgstr "" " * Para o caso de uso semelhante, considere demonstrar um recurso [`let else`](https://github.com/rust-lang/rust/" "pull/93628) recentemente estabilizado.\n" "* Um uso comum é lidar com valores `Some` ao trabalhar com `Option`.\n" -"* Ao contrário de `match`, `if let` não suporta cláusulas de guarda para casamento de padrões." +"* Ao contrário de `match`, `if let` não suporta cláusulas de guarda para correspondência de padrões." #: src/control-flow/while-expressions.md:1 msgid "# `while` expressions" -msgstr "# expressões `enquanto`" +msgstr "# Expressões enquanto (`while`)" #: src/control-flow/while-expressions.md:3 msgid "The `while` keyword works very similar to other languages:" @@ -7334,15 +7627,15 @@ msgstr "" #: src/control-flow/while-let-expressions.md:1 msgid "# `while let` expressions" -msgstr "# expressões `while let`" +msgstr "# Expressões enquanto (`while let`)" #: src/control-flow/while-let-expressions.md:3 msgid "" "Like with `if`, there is a `while let` variant which repeatedly tests a value\n" "against a pattern:" msgstr "" -"Como com `if`, há uma variante `while let` que testa repetidamente um valor\n" -"contra um padrão:" +"Como com `if`, há uma variante `while let` que testa repetidamente se um valor\n" +"corresponde a um padrão:" #: src/control-flow/while-let-expressions.md:6 msgid "" @@ -7377,8 +7670,8 @@ msgid "" "return `None`. The `while let` lets us keep iterating through all items." msgstr "" "Aqui o iterador retornado por `v.iter()` retornará uma `Option` em cada\n" -"chamada para `next ()`. Ele retorna `Some(x)` até que seja concluído, após o qual será\n" -"retorna 'Nenhum'. O `while let` nos permite continuar iterando por todos os itens." +"chamada para `next()`. Ele retorna `Some(x)` até que seja concluído e, em seguida, retorna \n" +"`None`. O `while let` nos permite continuar iterando por todos os itens, enquando houver." #: src/control-flow/while-let-expressions.md:27 msgid "" @@ -7388,23 +7681,23 @@ msgid "" " \n" "" msgstr "" -"* Saliente que o loop `while let` continuará enquanto o valor corresponder ao padrão.\n" -"* Você pode reescrever o loop `while let` como um loop infinito com uma instrução if que quebra quando não há valor para " +"* Saliente que o laço `while let` continuará enquanto o valor corresponder ao padrão.\n" +"* Você pode reescrever o laço `while let` como um laço infinito com uma instrução if que quebra quando não há valor para " "desempacotar para `iter.next()`. O `while let` fornece açúcar sintático para o cenário acima.\n" " \n" "" #: src/control-flow/for-expressions.md:1 msgid "# `for` expressions" -msgstr "# expressões `for`" +msgstr "# Expressões Para (`for`)" #: src/control-flow/for-expressions.md:3 msgid "" "The `for` expression is closely related to the `while let` expression. It will\n" "automatically call `into_iter()` on the expression and then iterate over it:" msgstr "" -"A expressão `for` está intimamente relacionada com a expressão `while let`. Será\n" -"chame automaticamente `into_iter()` na expressão e, em seguida, itere sobre ela:" +"A expressão `for` está intimamente relacionada com a expressão `while let`. É\n" +"chamado automaticamente `into_iter()` na expressão e, em seguida, iterado sobre ela:" #: src/control-flow/for-expressions.md:6 msgid "" @@ -7462,15 +7755,15 @@ msgstr "" #: src/control-flow/loop-expressions.md:1 msgid "# `loop` expressions" -msgstr "# expressões `loop`" +msgstr "# Expressões de laço (`loop`)" #: src/control-flow/loop-expressions.md:3 msgid "" "Finally, there is a `loop` keyword which creates an endless loop. Here you must\n" "either `break` or `return` to stop the loop:" msgstr "" -"Finalmente, há uma palavra-chave `loop` que cria um loop infinito. Aqui você deve\n" -"`break` ou `return` para parar o loop:" +"Finalmente, há uma palavra-chave `loop` que cria um laço infinito. Aqui você deve\n" +"usar `break` ou `return` para parar o laço:" #: src/control-flow/loop-expressions.md:6 msgid "" @@ -7498,18 +7791,21 @@ msgid "" " \n" "* Break the `loop` with a value (e.g. `break 8`) and print it out." msgstr "" +"
\n" +" \n" +"* Break o `loop` com um valor (ex. `break 8`) e mostre-o." #: src/control-flow/match-expressions.md:1 msgid "# `match` expressions" -msgstr "# expressões `match`" +msgstr "# Expressões de correspondência (`match`)" #: src/control-flow/match-expressions.md:3 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:" msgstr "" -"A palavra-chave `match` é usada para corresponder um valor a um ou mais padrões. No\n" -"nesse sentido, funciona como uma série de expressões `if let`:" +"A palavra-chave `match` é usada para corresponder um valor a um ou mais padrões. Nesse\n" +"sentido, funciona como uma série de expressões `if let`:" #: src/control-flow/match-expressions.md:6 msgid "" @@ -7533,8 +7829,8 @@ msgstr "" " Some(\"ls\") => println!(\"Serão alguns arquivos\"),\n" " Some(\"mv\") => println!(\"Vamos mover alguns arquivos\"),\n" " Some(\"rm\") => println!(\"Uh, perigoso!\"),\n" -" None => println!(\"Hmm, nenhum name de programa?\"),\n" -" _ => println!(\"name de programa desconhecido!\"),\n" +" None => println!(\"Hmm, nenhum nome de programa?\"),\n" +" _ => println!(\"Nome de programa desconhecido!\"),\n" " }\n" "}\n" "```" @@ -7544,7 +7840,7 @@ msgid "" "Like `if let`, each match arm must have the same type. The type is the last\n" "expression of the block, if any. In the example above, the type is `()`." msgstr "" -"Como `if let`, cada braço de correspondência deve ter o mesmo tipo. O tipo é o último\n" +"Como `if let`, cada braço de correspondência deve ter o mesmo tipo. O tipo é a última\n" "expressão do bloco, se houver. No exemplo acima, o tipo é `()`." #: src/control-flow/match-expressions.md:25 @@ -7559,10 +7855,19 @@ msgid "" " * We can now use pattern matching to match against the `&str` inside `Option`.\n" "
" msgstr "" +"
\n" +" \n" +"* Salve o resultado de uma expressão de correspondência `match` em uma variável e imprima-a.\n" +"* Remova `.as_deref()` e explique o erro gerado.\n" +" * `std::env::Agrs().next()` returns an `Option<&String>`, porém `match` não funciona com o tipo `String`.\n" +" * `as_deref()` transforma um tipo `Option` em `Option`. Nesse caso, transforma um `Option<&String>` em " +"`Option<&str>`.\n" +" * Agora podemos usar a correspondência de padrões em um `&str` dentro de um `Option`.\n" +"
" #: src/control-flow/break-continue.md:1 msgid "# `break` and `continue`" -msgstr "# `interromper` e `continuar`" +msgstr "# Interromper (`break`) e Continuar (`continue`)" #: src/control-flow/break-continue.md:3 msgid "" @@ -7570,9 +7875,9 @@ msgid "" "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:" msgstr "" -"Se você quiser sair de um loop mais cedo, use `break`, se quiser iniciar imediatamente\n" -"a próxima iteração usa `continue`. Ambos `continue` e `break` podem opcionalmente\n" -"pegue um argumento de rótulo que é usado para sair de loops aninhados:" +"Se você quiser sair de um laços mais cedo, use `break`, se quiser iniciar imediatamente\n" +"a próxima iteração use `continue`. Ambos `continue` e `break` podem opcionalmente\n" +"receber um rótulo como argumento que é usado para sair de laços aninhados:" #: src/control-flow/break-continue.md:7 msgid "" @@ -7598,14 +7903,14 @@ msgstr "" "fn main() {\n" " let v = vec![10, 20, 30];\n" " let mut iter = v.into_iter();\n" -" 'outer: while let Some(x) = iter.next() {\n" +" 'laco_externo: while let Some(x) = iter.next() {\n" " println!(\"x: {x}\");\n" " let mut i = 0;\n" " while i < x {\n" " println!(\"x: {x}, i: {i}\");\n" " i += 1;\n" " if i == 3 {\n" -" break 'outer;\n" +" break 'laco_externo;\n" " }\n" " }\n" " }\n" @@ -7614,7 +7919,7 @@ msgstr "" #: src/control-flow/break-continue.md:25 msgid "In this case we break the outer loop after 3 iterations of the inner loop." -msgstr "Neste caso, quebramos o loop externo após 3 iterações do loop interno." +msgstr "Neste caso, quebramos o laço externo após 3 iterações do laço interno." #: src/std.md:1 msgid "# Standard Library" @@ -7627,12 +7932,12 @@ msgid "" "smoothly because they both use the same `String` type." msgstr "" "Rust vem com uma biblioteca padrão que ajuda a estabelecer um conjunto de tipos comuns\n" -"usado pela biblioteca e programas Rust. Dessa forma, duas bibliotecas podem trabalhar juntas\n" +"usados pela biblioteca e programas Rust. Dessa forma, duas bibliotecas podem trabalhar juntas\n" "sem problemas porque ambos usam o mesmo tipo `String`." #: src/std.md:7 msgid "The common vocabulary types include:" -msgstr "Os tipos de vocabulário comuns incluem:" +msgstr "As palavras reservadas de tipo comuns incluem:" #: src/std.md:9 msgid "" @@ -7640,11 +7945,11 @@ msgid "" " and [error handling](error-handling.md)." msgstr "" "* Tipos [`Option` e `Result`](std/option-result.md): usados para valores opcionais\n" -" e [manipulação de erros](manipulação de erros.md)." +" e [manipulação de erros](error-handling.md)." #: src/std.md:12 msgid "* [`String`](std/string.md): the default string type used for owned data." -msgstr "* [`String`](std/string.md): o tipo de string padrão usado para dados de ownership." +msgstr "* [`String`](std/string.md): o tipo de cadeia de caracteres padrão extensível usado para dados." #: src/std.md:14 msgid "* [`Vec`](std/vec.md): a standard extensible vector." @@ -7655,8 +7960,7 @@ msgid "" "* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing\n" " algorithm." msgstr "" -"* [`HashMap`](std/hashmap.md): um tipo de mapa hash com um hashing configurável\n" -" algoritmo." +"* [`HashMap`](std/hashmap.md): um tipo de mapa hash com o algoritmo de hashing configurável." #: src/std.md:19 msgid "* [`Box`](std/box.md): an owned pointer for heap-allocated data." @@ -7682,7 +7986,7 @@ msgstr "" " * `core` inclui os tipos e funções mais básicos que não dependem de `libc`, alocador ou\n" " até mesmo a presença de um sistema operacional.\n" " * `alloc` inclui tipos que requerem um alocador de heap global, como `Vec`, `Box` e `Arc`.\n" -" * Os aplicativos Rust integrados geralmente usam apenas `core` e, às vezes, `alloc`." +" * Os aplicativos Rust embarcados geralmente usam apenas `core` e, às vezes, `alloc`." #: src/std/option-result.md:1 msgid "# `Option` and `Result`" @@ -7693,7 +7997,6 @@ msgid "The types represent optional data:" msgstr "Os tipos representam dados opcionais:" #: src/std/option-result.md:5 -#, fuzzy msgid "" "```rust,editable\n" "fn main() {\n" @@ -7703,20 +8006,19 @@ msgid "" msgstr "" "```rust, editable\n" "fn main() {\n" -" let números = vec![10, 20, 30];\n" -" let primeiro: Option<&i8> = números.primeiro();\n" -" println!(\"primeiro: {primeiro:?}\");" +" let numeros = vec![10, 20, 30];\n" +" let primeiro: Option<&i8> = numeros.first();\n" +" println!(\"Primeiro: {primeiro:?}\");" #: src/std/option-result.md:11 -#, fuzzy msgid "" " let idx: Result = numbers.binary_search(&10);\n" " println!(\"idx: {idx:?}\");\n" "}\n" "```" msgstr "" -" let idx: Result = numbers.binary_search(&10);\n" -" println!(\"idx: {idx:?}\");\n" +" let idx: Result = numeros.binary_search(&10);\n" +" println!(\"Indice: {idx:?}\");\n" "}\n" "```" @@ -7730,7 +8032,7 @@ msgid "" " * Otherwise, `Result::Err` contains the index where such an element should be inserted." msgstr "" "* `Option` e `Result` são amplamente usados não apenas na biblioteca padrão.\n" -"* `Option<&T>` tem sobrecargo de espaço zero em comparação com `&T`.\n" +"* `Option<&T>` tem sobrecarga de espaço zero em comparação com `&T`.\n" "* `Result` é o tipo padrão para implementar o tratamento de erros, como veremos no Dia 3.\n" "* `binary_search` retorna `Result`.\n" " * Se encontrado, `Result::Ok` contém o índice onde o elemento foi encontrado.\n" @@ -7742,7 +8044,7 @@ msgstr "# String" #: src/std/string.md:3 msgid "[`String`][1] is the standard heap-allocated growable UTF-8 string buffer:" -msgstr "[`String`][1] é o buffer de string UTF-8 expansível alocado por heap padrão:" +msgstr "[`String`][1] é o buffer padrão de cadeia de caracteres UTF-8 expansível e alocado no heap:" #: src/std/string.md:5 msgid "" @@ -7756,7 +8058,7 @@ msgstr "" "fn main() {\n" " let mut s1 = String::new();\n" " s1.push_str(\"Olá\");\n" -" println!(\"s1: len = {}, capacage = {}\", s1.len(), s1.capacity());" +" println!(\"s1: tamanho = {}, capacidade = {}\", s1.len(), s1.capacity());" #: src/std/string.md:11 msgid "" @@ -7768,7 +8070,7 @@ msgstr "" " let mut s2 = String::with_capacity(s1.len() + 1);\n" " s2.push_str(&s1);\n" " s2.push('!');\n" -" println!(\"s2: len = {}, capacage = {}\", s2.len(), s2.capacity());" +" println!(\"s2: tamanho = {}, capacidade = {}\", s2.len(), s2.capacity());" #: src/std/string.md:16 msgid "" @@ -7779,7 +8081,7 @@ msgid "" "```" msgstr "" " let s3 = String::from(\"🇨🇭\");\n" -" println!(\"s3: len = {}, número de caracteres = {}\", s3.len(),\n" +" println!(\"s3: tamanho = {}, número de caracteres = {}\", s3.len(),\n" " s3.chars().count());\n" "}\n" "```" @@ -7790,7 +8092,7 @@ msgid "" "`str` methods on a `String`." msgstr "" "`String` implementa [`Deref`][2], o que significa que você pode chamar todos\n" -"Métodos `str` em uma `String`." +"os métodos contidos em `str` em uma `String`." #: src/std/string.md:25 msgid "" @@ -7816,7 +8118,7 @@ msgstr "# `Vec`" #: src/std/vec.md:3 msgid "[`Vec`][1] is the standard resizable heap-allocated buffer:" -msgstr "[`Vec`][1] é o buffer redimensionável padrão alocado em heap:" +msgstr "[`Vec`][1] é o buffer padrão redimensionável alocado no heap:" #: src/std/vec.md:5 msgid "" @@ -7830,10 +8132,9 @@ msgstr "" "fn main() {\n" " let mut v1 = Vec::new();\n" " v1.push(42);\n" -" println!(\"v1: len = {}, capacage = {}\", v1.len(), v1.capacity());" +" println!(\"v1: tamanho = {}, capacidade = {}\", v1.len(), v1.capacity());" #: src/std/vec.md:11 -#, fuzzy msgid "" " let mut v2 = Vec::with_capacity(v1.len() + 1);\n" " v2.extend(v1.iter());\n" @@ -7843,7 +8144,7 @@ msgstr "" " let mut v2 = Vec::with_capacity(v1.len() + 1);\n" " v2.extend(v1.iter());\n" " v2.push(9999);\n" -" println!(\"v2: len = {}, capacage = {}\", v2.len(), v2.capacity());\n" +" println!(\"v2: tamanho = {}, capacidade = {}\", v2.len(), v2.capacity());\n" "}\n" "```" @@ -7852,6 +8153,8 @@ msgid "" " // Canonical macro to initialize a vector with elements.\n" " let mut v3 = vec![0, 0, 1, 2, 3, 4];" msgstr "" +" // Macro canônica para inicializar um vetor com elementos.\n" +" let mut v3 = vec![0, 0, 1, 2, 3, 4];" #: src/std/vec.md:19 msgid "" @@ -7859,6 +8162,9 @@ msgid "" " v3.retain(|x| x % 2 == 0);\n" " println!(\"{v3:?}\");" msgstr "" +" // Retém somente os elementos pares.\n" +" v3.retain(|x| x % 2 == 0);\n" +" println!(\"{v3:?}\");" #: src/std/vec.md:23 msgid "" @@ -7868,14 +8174,19 @@ msgid "" "}\n" "```" msgstr "" +" // Remove valores duplicados consecutivos.\n" +" v3.dedup();\n" +" println!(\"{v3:?}\");\n" +"}\n" +"```" #: src/std/vec.md:29 msgid "" "`Vec` implements [`Deref`][2], which means that you can call slice\n" "methods on a `Vec`." msgstr "" -"`Vec` implementa [`Deref`][2], o que significa que você pode chamar slice\n" -"métodos em um `Vec`." +"`Vec` implementa [`Deref`][2], o que significa que você pode chamar métodos de slice\n" +"em um `Vec`." #: src/std/vec.md:32 msgid "" @@ -7901,26 +8212,26 @@ msgid "" msgstr "" "
\n" " \n" -"* `Vec` é um tipo de coleção, junto com `String` e `HashMap`. Os dados que ele contém são armazenados\n" -" na pilha. Isso significa que a quantage de dados não precisa ser conhecida em tempo de compilação. pode crescer\n" +"* `Vec` é um tipo de coleção, como `String` e `HashMap`. Os dados que ele contém são armazenados\n" +" no heap. Isso significa que a quantidade de dados não precisa ser conhecida em tempo de compilação. Pode crescer\n" " ou encolher em tempo de execução.\n" -"* Observe como `Vec` também é um tipo genérico, mas você não precisa especificar `T` explicitamente. Como sempre\n" -" com inferência de tipo Rust, o `T` foi estabelecido durante a primeira chamada `push`.\n" -"* `vec![...]` é uma macro canônica para usar em vez de `Vec::new()` e suporta adicionar iniciais\n" -" elementos ao vetor.\n" -"* Para indexar o vetor, você usa `[` `]`, mas eles entrarão em pânico se estiverem fora dos limites. Alternativamente, " -"usando\n" -" `get` retornará uma `Option`. A função `pop` removerá o último elemento.\n" +"* Observe como `Vec` também é um tipo genérico, mas você não precisa especificar `T` explicitamente. Como sempre,\n" +" com a inferência de tipo Rust, o `T` foi estabelecido durante a primeira chamada `push`.\n" +"* `vec![...]` é uma macro canônica para usar em vez de `Vec::new()` e suporta adicionar elementos\n" +" iniciais ao vetor.\n" +"* Para indexar o vetor, você usa `[` `]`, mas uma excessão do tipo _pânico_ (`panic`) será gerada se o índice estiver\n" +"fora dos limites. Alternativamente, usando\n" +" `get` você obterá uma `Option`. A função `pop` removerá o último elemento.\n" "* Mostrar iterando sobre um vetor e alterando o valor:\n" " `for e in &mut v { *e += 50; }`" #: src/std/hashmap.md:1 msgid "# `HashMap`" -msgstr "#`HashMap`" +msgstr "# `HashMap`" #: src/std/hashmap.md:3 msgid "Standard hash map with protection against HashDoS attacks:" -msgstr "Mapa de hash padrão com proteção contra ataques HashDoS:" +msgstr "Mapa de _hash_ padrão com proteção contra ataques HashDoS:" #: src/std/hashmap.md:5 msgid "" @@ -7939,10 +8250,10 @@ msgid "" " page_counts.insert(\"Pride and Prejudice\".to_string(), 303);" msgstr "" "fn main() {\n" -" let mut page_counts = HashMap::new();\n" -" page_counts.insert(\"Aventuras de Huckleberry Finn\".to_string(), 207);\n" -" page_counts.insert(\"Contos de Fadas dos Grimms\".to_string(), 751);\n" -" page_counts.insert(\"Orgulho e Preconceito\".to_string(), 303);" +" let mut meus_livros = HashMap::new();\n" +" meus_livros.insert(\"Aventuras de Huckleberry Finn\".to_string(), 207);\n" +" meus_livros.insert(\"Contos de Fadas dos Grimms\".to_string(), 751);\n" +" meus_livros.insert(\"Orgulho e Preconceito\".to_string(), 303);" #: src/std/hashmap.md:14 msgid "" @@ -7951,13 +8262,12 @@ msgid "" " page_counts.len());\n" " }" msgstr "" -" if !page_counts.contains_key(\"Os Miseráveis\") {\n" -" println!(\"Conhecemos {} livros, mas não Os Miseráveis.\",\n" -" page_counts.len());\n" +" if !meus_livros.contains_key(\"Os Miseráveis\") {\n" +" println!(\"Tenho {} livros, mas não Os Miseráveis.\",\n" +" meus_livros.len());\n" " }" #: src/std/hashmap.md:19 -#, fuzzy msgid "" " for book in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" " match page_counts.get(book) {\n" @@ -7966,14 +8276,12 @@ msgid "" " }\n" " }" msgstr "" -" for book in [\"Orgulho e Preconceito\", \"Alice no País das Maravilhas\"] {\n" -" match page_counts.get(book) {\n" -" Some(count) => println!(\"{book}: {count} páginas\"),\n" -" None => println!(\"{book} é desconhecido.\")\n" +" for livro in [\"Orgulho e Preconceito\", \"Alice no País das Maravilhas\"] {\n" +" match meus_livros.get(livro) {\n" +" Some(paginas) => println!(\"{livro}: {paginas} páginas\"),\n" +" None => println!(\"{livro} é desconhecido.\")\n" " }\n" -" }\n" -"}\n" -"```" +" }" #: src/std/hashmap.md:26 msgid "" @@ -7983,6 +8291,11 @@ msgid "" " *page_count += 1;\n" " }" msgstr "" +" // Use o método .entry() para inserir um valor, caso este não seja encontrado.\n" +" for livro in [\"Pride and Prejudice\", \"Alice's Adventure in Wonderland\"] {\n" +" let meu_livro: &mut i32 = meus_livros.entry(livro.to_string()).or_insert(0);\n" +" *meu_livro += 1;\n" +" }" #: src/std/hashmap.md:32 msgid "" @@ -7990,18 +8303,21 @@ msgid "" "}\n" "```" msgstr "" +" println!(\"{meus_livros:#?}\");\n" +"}\n" +"```" #: src/std/hashmap.md:38 msgid "* Unlike `vec!`, there is unfortunately no standard `hashmap!` macro." -msgstr "" +msgstr "* Diferente de `vec!`, infelizmente não há uma macro padrão `hashmap!`." #: src/std/box.md:1 msgid "# `Box`" -msgstr "# `Caixa`" +msgstr "# `Box`" #: src/std/box.md:3 msgid "[`Box`][1] is an owned pointer to data on the heap:" -msgstr "[`Box`][1] é um ponteiro de ownership para dados no heap:" +msgstr "[`Box`][1] é um ponteiro de propriedade para dados no heap:" #: src/std/box.md:5 msgid "" @@ -8020,7 +8336,6 @@ msgstr "" "```" #: src/std/box.md:13 -#, fuzzy msgid "" "```bob\n" " Stack Heap\n" @@ -8036,16 +8351,16 @@ msgid "" "```" msgstr "" "```bob\n" -" Pilha\n" -".- - - - - - -. .- - - - - - -.\n" -": : : :\n" -": cinco : : :\n" -": +-----+ : : +-----+ :\n" -": | o---|---+-----+-->| 5 | :\n" -": +-----+ : : +-----+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - -' `- - - - - -'\n" +" Stack Heap\n" +".- - - - - - -. .- - - - - - -.\n" +": : : :\n" +": cinco : : :\n" +": +-----+ : : +-----+ :\n" +": | o---|---+-----+-->| 5 | :\n" +": +-----+ : : +-----+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - -' `- - - - - - -'\n" "```" #: src/std/box.md:26 @@ -8074,14 +8389,21 @@ msgid "" "store the data on the heap in a `Box` so only the pointer is moved.\n" "
" msgstr "" +"* `Box` é parecido com `std::unique_ptr` em C++. \n" +"* No exemplo acima, você pode remover o `*` na instrução `println!` graças ao `Deref`. \n" +"* Uma `Box` é útil quando você:\n" +" * Tem um tipo cujo tamanho não está disponível em tempo de compilação, mas o compilador Rust precisa saber o tamanho exato.\n" +" * Precisa transferir a propriedade de um dado grande. Ao invés de copiar grandes volumes de dados na pilha (`stack`),\n" +"os dados são armazenados usando uma `Box` na _heap_ e apenas o ponteiro é movido." +"" #: src/std/box-recursive.md:1 msgid "# Box with Recursive Data Structures" -msgstr "# Caixa com Structs de Dados Recursivas" +msgstr "# `Box` com estruturas de dados recursivas" #: src/std/box-recursive.md:3 msgid "Recursive data types or data types with dynamic sizes need to use a `Box`:" -msgstr "Tipos de dados recursivos ou tipos de dados com tamanhos dinâmicos precisam usar um `Box`:" +msgstr "Tipos de dados recursivos ou tipos de dados com tamanhos dinâmicos precisam usar uma `Box`:" #: src/std/box-recursive.md:5 src/std/box-niche.md:3 msgid "" @@ -8107,9 +8429,13 @@ msgid "" "}\n" "```" msgstr "" +"fn main() {\n" +" let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));\n" +" println!(\"{list:?}\");\n" +"}\n" +"```" #: src/std/box-recursive.md:18 -#, fuzzy msgid "" "```bob\n" " Stack Heap\n" @@ -8127,18 +8453,18 @@ msgid "" "```" msgstr "" "```bob\n" -" Pilha\n" -".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" -": : : :\n" -": Lista : : :\n" -": +--------+-------+ : : +--------+--------+ +--------+ ------+ :\n" -": | Etiqueta | Contras | : : .->| Etiqueta | Contras | .->| Etiqueta | nada | :\n" -": | 0 | 1 | : : | | 0 | 2 | | | ////// | //// | :\n" -": | 1 | o-----+----+-----+-' | 1 | o------+-' | ////// | //// | :\n" -": +--------+-------+ : : +--------+--------+ +--------+ ------+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": lista : : :\n" +": +--------+-------+ : : +--------+--------+ +--------+------+ :\n" +": | Tag | Cons | : : .->| Tag | Cons | .->| Tag | Nil | :\n" +": | 0 | 1 | : : | | 0 | 2 | | | ////// | //// | :\n" +": | 1 | o-----+----+-----+-' | 1 | o------+-' | ////// | //// | :\n" +": +--------+-------+ : : +--------+--------+ +--------+------+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" "```" #: src/std/box-recursive.md:33 @@ -8150,14 +8476,15 @@ msgid "" " \n" "* `Box` solves this problem as it has the same size as a regular pointer and just points at the next\n" "element of the `List` in the heap. " + msgstr "" "
\n" " \n" -"Se a `Caixa` não foi usada aqui e tentamos incorporar uma `Lista` diretamente na `Lista`,\n" +"Se a `Box` não for usada aqui e tentarmos incorporar uma `List` diretamente na `List`,\n" "o compilador não calcularia um tamanho fixo da estrutura na memória, pareceria infinito.\n" " \n" "`Box` resolve esse problema, pois tem o mesmo tamanho de um ponteiro normal e apenas aponta para o próximo\n" -"elemento da `Lista` na pilha.\n" +"elemento da `List` na _heap_.\n" " \n" "
" @@ -8168,6 +8495,8 @@ msgid "" " \n" "" msgstr "" +"* Remova a `Box` da definição da `List` e veja o erro apresentado pelo compilador. `Recursive with indirection` é o aviso que você vai receber." +"" #: src/std/box-niche.md:1 msgid "# Niche Optimization" @@ -8178,51 +8507,50 @@ msgid "" "A `Box` cannot be empty, so the pointer is always valid and non-`null`. This\n" "allows the compiler to optimize the memory layout:" msgstr "" -"Uma `Box` não pode estar vazia, então o ponteiro é sempre válido e não `nulo`. Esta\n" +"Uma `Box` não pode estar vazia, então o ponteiro é sempre válido e não `nulo`. Isto\n" "permite que o compilador otimize o layout da memória:" #: src/std/box-niche.md:19 -#, fuzzy msgid "" "```bob\n" " Stack Heap\n" -".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" -": : : :\n" -": list : : :\n" -": +--------+-------+ : : +--------+--------+ +--------+------+ :\n" -": | 0 | 1 | : : .->| 0 | 2 | .->| ////// | //// | :\n" -": | \"1/Tag\"| o-----+----+-----+-' | \"1/Tag\"| o-----+-' | \"1/Tag\"| null | :\n" -": +--------+-------+ : : +--------+--------+ +--------+------+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": list : : :\n" +": +----------+-------+ : : +----------+--------+ +----------+------+ :\n" +": | 0 | 1 | : : .->| 0 | 2 | .->| ////// | //// | :\n" +": | \"1/Tag\"| o-----+--+-----+-' | \"1/Tag\"| o-----+-' | \"1/Tag\"| null | :\n" +": +----------+-------+ : : +----------+--------+ +----------+------+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - - - -'\n" "```" msgstr "" "```bob\n" -" Pilha\n" -".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" -": : : :\n" -": Lista : : :\n" -": +--------+-------+ : : +--------+--------+ +--------+ ------+ :\n" -": | 0 | 1 | : : .->| 0 | 2 | .->| ////// | //// | :\n" -": | \"1/Etiqueta\"| o-----+----+-----+-' | \"1/Etiqueta\"| o-----+-' | \"1/Etiqueta\"| nulo | :\n" -": +--------+-------+ : : +--------+--------+ +--------+ ------+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - -'\n" +" Stack Heap\n" +".- - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": lista : : :\n" +": +----------+-------+ : : +----------+--------+ +----------+------+ :\n" +": | 0 | 1 | : : .->| 0 | 2 | .->| ////// | //// | :\n" +": | \"1/Tag\"| o-----+--+-----+-' | \"1/Tag\"| o-----+-' | \"1/Tag\"| null | :\n" +": +----------+-------+ : : +----------+--------+ +----------+------+ :\n" +": : : :\n" +": : : :\n" +"`- - - - - - - - - - - - -' '- - - - - - - - - - - - - - - - - - - - - - - - - -'\n" "```" #: src/std/rc.md:1 msgid "# `Rc`" -msgstr "#`Rc`" +msgstr "# `Rc`" #: src/std/rc.md:3 msgid "" "[`Rc`][1] is a reference-counted shared pointer. Use this when you need to refer\n" "to the same data from multiple places:" msgstr "" -"[`Rc`][1] é um ponteiro compartilhado com contagem de referência. Use isso quando precisar consultar\n" -"aos mesmos dados de vários lugares:" +"[`Rc`][1] é um ponteiro compartilhado com contagem de referência. Use-o quando precisar consultar\n" +"os mesmos dados a partir de vários locais:" #: src/std/rc.md:6 msgid "" @@ -8251,8 +8579,9 @@ msgid "" " that will get dropped." msgstr "" "Se você precisar alterar os dados dentro de um `Rc`, precisará agrupar os dados em\n" -"um tipo como [`Cell` ou `RefCell`][2]. Veja [`Arc`][3] se você estiver em um multi-threaded\n" -"contexto." +"um tipo como [`Cell` ou `RefCell`][2]. Veja [`Arc`][3] se você estiver em um contexto multi-threads.\n" +"Você pode regredir um ponteiro compartilhado dentro de um ponteiro [`Weak`][4] para criar ciclos\n" +"que serão descartados." #: src/std/rc.md:24 msgid "" @@ -8263,7 +8592,8 @@ msgid "" msgstr "" "[1]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n" "[2]: https://doc.rust-lang.org/std/cell/index.html\n" -"[3]: ../concurrency/shared_state/arc.md" +"[3]: ../concurrency/shared_state/arc.md\n" +"[4]: https://doc.rust-lang.org/std/rc/struct.Weak.html" #: src/std/rc.md:31 msgid "" @@ -8276,7 +8606,9 @@ msgid "" msgstr "" "* Como `std::shared_ptr` do C++.\n" "* `clone` é barato: cria um ponteiro para a mesma alocação e aumenta a contagem de referência.\n" -"* `make_mut` realmente clona o valor interno se necessário (\"clone-on-write\") e retorna uma referência mutável." +"* `make_mut` realmente clona o valor interno se necessário (\"clone-on-write\") e retorna uma referência mutável.\n" +"* Você pode invocar `downgrade()` em um `Rc` para obter um objeto contador de referências `Weak` para criar\n" +"ciclos que podem ser apropriadamente descartados (provavelmente combinados com `RefCell`)." #: src/std/rc.md:38 msgid "" @@ -8297,6 +8629,12 @@ msgid "" " children: Vec>>,\n" "}" msgstr "" +"#[derive(Debug)]\n" +"struct No {\n" +" valor: i64,\n" +" pai: Option>>,\n" +" filhos: Vec>>,\n" +"}" #: src/std/rc.md:49 msgid "" @@ -8313,15 +8651,26 @@ msgid "" " }));\n" " root.borrow_mut().children.push(child);" msgstr "" +"fn main() {\n" +" let mut raiz = Rc::new(RefCell::new(No {\n" +" valor: 42,\n" +" pai: None,\n" +" filhos: vec![],\n" +" }));\n" +" let filho = Rc::new(RefCell::new(No {\n" +" valor: 43,\n" +" filhos: vec![],\n" +" pai: Some(Rc::downgrade(&raiz))\n" +" }));\n" +" raiz.borrow_mut().filhos.push(filho);" #: src/std/rc.md:62 -#, fuzzy msgid "" " println!(\"graph: {root:#?}\");\n" "}\n" "```" msgstr "" -" println!(\"após: {a}\");\n" +" println!(\"grafo: {raiz:#?}\");\n" "}\n" "```" @@ -8331,11 +8680,11 @@ msgstr "# Módulos" #: src/modules.md:3 msgid "We have seen how `impl` blocks let us namespace functions to a type." -msgstr "Vimos como os blocos `impl` nos permitem funções de namespace para um tipo." +msgstr "Vimos como os blocos `impl` nos permitem funções de usando espaços de nomes (_namespace_) para um tipo." #: src/modules.md:5 msgid "Similarly, `mod` lets us namespace types and functions:" -msgstr "Da mesma forma, `mod` nos permite tipos e funções de namespace:" +msgstr "Da mesma forma, `mod` nos permite tipos e funções usando espaço de nomes:" #: src/modules.md:7 msgid "" @@ -8348,13 +8697,12 @@ msgid "" msgstr "" "```rust, editable\n" "mod foo {\n" -" pub fn do_something() {\n" -" println!(\"No módulo foo\");\n" +" pub fn qualquer_coisa() {\n" +" println!(\"Qualquer coisa no módulo foo\");\n" " }\n" "}" #: src/modules.md:14 -#, fuzzy msgid "" "mod bar {\n" " pub fn do_something() {\n" @@ -8362,9 +8710,9 @@ msgid "" " }\n" "}" msgstr "" -"barra de mods {\n" -" pub fn do_something() {\n" -" println!(\"No modulo da barra\");\n" +"mod bar {\n" +" pub fn qualquer_coisa() {\n" +" println!(\"Qualquer coisa no modulo bar\");\n" " }\n" "}" @@ -8377,8 +8725,8 @@ msgid "" "```" msgstr "" "fn main() {\n" -" foo::do_something();\n" -" bar::do_something();\n" +" foo::qualquer_coisa();\n" +" bar::qualquer_coisa();\n" "}\n" "```" @@ -8388,14 +8736,17 @@ msgid "" "* Crates are a tree of modules, where a binary crate creates an executable and a library crate compiles to a library.\n" "* Modules define organization, scope, and is the focus of this section." msgstr "" +"* Pacotes (packages) forneces funcionalidades e incluem o arquivo `Cargo.toml` que descreve como gerar o pacote com um ou mais _crates_.\n" +"* _Crates_ são arvores de módulos onde um _crate_ birário cria um executável e um _crate_ de biblioteca compila uma biblioteca.\n" +"* Módulos definem a organização, o escopo e são o foco desta sessão." #: src/modules/visibility.md:1 msgid "# Visibility" -msgstr "# Visibilage" +msgstr "# Visibilidade" #: src/modules/visibility.md:3 msgid "Modules are a privacy boundary:" -msgstr "Os módulos são um limite de privacage:" +msgstr "Os módulos são um limitador de privacidade:" #: src/modules/visibility.md:5 msgid "" @@ -8404,7 +8755,7 @@ msgid "" "* In other words, if an item is visible in module `foo`, it's visible in all the\n" " descendants of `foo`." msgstr "" -"* Os itens do módulo são privados por padrão (oculta detalhes de implementação).\n" +"* Os itens do módulo são privados por padrão (ocultam detalhes de implementação).\n" "* Os itens pai e irmão estão sempre visíveis." #: src/modules/visibility.md:10 @@ -8473,11 +8824,12 @@ msgstr "" #: src/modules/visibility.md:39 msgid "* Use the `pub` keyword to make mods public." -msgstr "" +msgstr "* Use a palavra reservada `pub` para tornar um módulo público." #: src/modules/visibility.md:41 msgid "Additionally, there are advanced `pub(...)` specifiers to restrict the scope of public visibility." -msgstr "" +msgstr "Adicionamente, existem especificadores `pub(...)` avançados para restringir o\n" +"escopo da visibilidade pública." #: src/modules/visibility.md:43 msgid "" @@ -8487,10 +8839,15 @@ msgid "" "* Less commonly, you can give visibility to a specific path.\n" "* In any case, visibility must be granted to an ancestor module (and all of its descendants)." msgstr "" +"* Veja a [Referência Rust](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-path-pubcrate-pubsuper-and-" +"pubself).\n" +"* `pub(crate)` é a configuração padrão de visibilidade.\n" +"* Menos comum, você pode dar visibilidade para um caminho específico.\n" +"* Em todo caso, a visibilidade deve ser concedida ao módulo ancestral (e a todos os seus descendentes)." #: src/modules/paths.md:1 msgid "# Paths" -msgstr "# caminhos" +msgstr "# Caminhos (paths)" #: src/modules/paths.md:3 msgid "Paths are resolved as follows:" @@ -8513,8 +8870,8 @@ msgid "" " * `bar::foo` refers to `foo` in the `bar` crate." msgstr "" "2. Como um caminho absoluto:\n" -" * `crate::foo` refere-se a `foo` na raiz da caixa atual,\n" -" * `bar::foo` refere-se a `foo` na caixa `bar`." +" * `crate::foo` refere-se a `foo` na raiz do _crate_ atual,\n" +" * `bar::foo` refere-se a `foo` no _crate_ `bar`." #: src/modules/filesystem.md:1 msgid "# Filesystem Hierarchy" @@ -8531,7 +8888,7 @@ msgid "" "```" msgstr "" "```rust,editable,compile_fail\n" -"jardim mod;\n" +"mod garden;\n" "```" #: src/modules/filesystem.md:9 @@ -8567,8 +8924,8 @@ msgid "" "* `src/lib.rs` (for a library crate)\n" "* `src/main.rs` (for a binary crate)" msgstr "" -"* `src/lib.rs` (para uma caixa de biblioteca)\n" -"* `src/main.rs` (para uma caixa binária)" +"* `src/lib.rs` (para um _crate_ de biblioteca)\n" +"* `src/main.rs` (para um _crate_ binário)" #: src/exercises/day-2/afternoon.md:1 msgid "# Day 2: Afternoon Exercises" @@ -8594,27 +8951,27 @@ msgstr "" #: src/exercises/day-2/luhn.md:7 msgid "* Ignore all spaces. Reject number with less than two digits." -msgstr "* Ignore todos os espaços. Rejeitar número com menos de dois dígitos." +msgstr "* Ignora todos os espaços. Rejeita números com menos de dois dígitos." #: src/exercises/day-2/luhn.md:9 msgid "" "* Moving from right to left, double every second digit: for the number `1234`,\n" " we double `3` and `1`." msgstr "" -"* Movendo-se da direita para a esquerda, dobre cada segundo dígito: para o número `1234`,\n" -" nós dobramos `3` e `1`." +"* Movendo-se da direita para a esquerda, dobra cada segundo dígito: para o número `1234`,\n" +" dobra os números `3` e `1`." #: src/exercises/day-2/luhn.md:12 msgid "" "* After doubling a digit, sum the digits. So doubling `7` becomes `14` which\n" " becomes `5`." msgstr "" -"* Depois de dobrar um dígito, some os dígitos. Assim, duplicar `7` torna-se `14` que\n" -" torna-se '5'." +"* Depois de dobrar um dígito, soma os dígitos. Assim, duplicar `7` resulta em `14` que\n" +" resulta em `5`." #: src/exercises/day-2/luhn.md:15 msgid "* Sum all the undoubled and doubled digits." -msgstr "* Some todos os dígitos duplicados e duplicados." +msgstr "* Soma todos os dígitos não duplicados e duplicados." #: src/exercises/day-2/luhn.md:17 msgid "* The credit card number is valid if the sum ends with `0`." @@ -8625,7 +8982,7 @@ msgid "" "Copy the following code to and implement the\n" "function:" msgstr "" -"Copie o seguinte código para e implemente o\n" +"Copie o seguinte código para e implemente a\n" "função:" #: src/exercises/day-2/luhn.md:27 @@ -8634,7 +8991,7 @@ msgid "" " unimplemented!()\n" "}" msgstr "" -"pub fn luhn(cc_number: &str) -> bool {\n" +"pub fn luhn(numero_cc: &str) -> bool {\n" " unimplemented!()\n" "}" @@ -8646,7 +9003,7 @@ msgid "" "}" msgstr "" "#[test]\n" -"fn test_non_digit_cc_number() {\n" +"fn test_numero_cc_nao_numerico() {\n" " assert!(!luhn(\"foo\"));\n" "}" @@ -8661,7 +9018,7 @@ msgid "" "}" msgstr "" "#[test]\n" -"fn test_empty_cc_number() {\n" +"fn test_numero_cc_vazio() {\n" " assert!(!luhn(\"\"));\n" " assert!(!luhn(\" \"));\n" " assert!(!luhn(\" \"));\n" @@ -8676,7 +9033,7 @@ msgid "" "}" msgstr "" "#[test]\n" -"fn test_single_digit_cc_number() {\n" +"fn test_numero_cc_um_numero() {\n" " assert!(!luhn(\"0\"));\n" "}" @@ -8688,7 +9045,7 @@ msgid "" "}" msgstr "" "#[test]\n" -"fn test_two_digit_cc_number() {\n" +"fn test_numero_cc_dois_numeros() {\n" " assert!(luhn(\" 0 0 \"));\n" "}" @@ -8702,7 +9059,7 @@ msgid "" "}" msgstr "" "#[test]\n" -"fn test_valid_cc_number() {\n" +"fn test_numero_cc_valido() {\n" " assert!(luhn(\"4263 9826 4026 9299\"));\n" " assert!(luhn(\"4539 3195 0343 6467\"));\n" " assert!(luhn(\"7992 7398 713\"));\n" @@ -8718,7 +9075,7 @@ msgid "" "}" msgstr "" "#[test]\n" -"fn test_invalid_cc_number() {\n" +"fn test_numero_cc_invalido() {\n" " assert!(!luhn(\"4223 9826 4026 9299\"));\n" " assert!(!luhn(\"4539 3195 0343 6476\"));\n" " assert!(!luhn(\"8273 1232 7352 0569\"));\n" @@ -8735,10 +9092,10 @@ msgid "" "_request paths_. The path prefixes can contain a wildcard character which\n" "matches a full segment. See the unit tests below." msgstr "" -"Neste exercício, você está implementando um componente de roteamento de um servidor web. o\n" -"servidor está configurado com um número de _path prefixes_ que são comparados\n" -"_pedir caminhos_. Os prefixos de caminho podem conter um caractere curinga que\n" -"corresponde a um segmento completo. Veja os testes de unage abaixo." +"Neste exercício, você está implementando um componente de roteamento de um servidor web. O\n" +"servidor está configurado com um número de _prefixos de caminhos_ que são comparados\n" +"com os _caminhos pedidos_. Os prefixos de caminho podem conter um caractere curinga que\n" +"corresponde a um segmento completo. Veja os testes unitários abaixo." #: src/exercises/day-2/strings-iterators.md:8 msgid "" @@ -8746,7 +9103,7 @@ msgid "" "pass. Try avoiding allocating a `Vec` for your intermediate results:" msgstr "" "Copie o seguinte código para e faça os testes\n" -"passar. Tente evitar alocar um `Vec` para seus resultados intermediários:" +"passarem. Tente evitar alocar um `Vec` para seus resultados intermediários:" #: src/exercises/day-2/strings-iterators.md:16 msgid "" @@ -8754,7 +9111,7 @@ msgid "" " unimplemented!()\n" "}" msgstr "" -"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" +"pub fn correspondencia_prefixo(prefixo: &str, caminho_requisitado: &str) -> bool {\n" " unimplemented!()\n" "}" @@ -8767,10 +9124,10 @@ msgid "" " assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" msgstr "" "#[test]\n" -"fn test_matches_without_wildcard() {\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" +"fn test_correspondencia_sem_curinga() {\n" +" assert!(correspondencia_prefixo(\"/v1/autores\", \"/v1/autores\"));\n" +" assert!(correspondencia_prefixo(\"/v1/autores\", \"/v1/autores/abc-123\"));\n" +" assert!(correspondencia_prefixo(\"/v1/autores\", \"/v1/autores/abc/livros\"));" #: src/exercises/day-2/strings-iterators.md:26 src/exercises/day-2/solutions-afternoon.md:146 msgid "" @@ -8779,9 +9136,9 @@ msgid "" " assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" "}" msgstr "" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/publishers\"));\n" +" assert!(!correspondencia_prefixo(\"/v1/autores\", \"/v1\"));\n" +" assert!(!correspondencia_prefixo(\"/v1/autores\", \"/v1/autoresLivros\"));\n" +" assert!(!correspondencia_prefixo(\"/v1/autores\", \"/v1/parent/autores\"));\n" "}" #: src/exercises/day-2/strings-iterators.md:31 src/exercises/day-2/solutions-afternoon.md:151 @@ -8802,18 +9159,18 @@ msgid "" " ));" msgstr "" "#[test]\n" -"fn test_matches_with_wildcard() {\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books\"\n" +"fn test_correspondencia_com_curinga() {\n" +" assert!(correspondencia_prefixo(\n" +" \"/v1/autores/*/livros\",\n" +" \"/v1/autores/foo/livros\"\n" " ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/bar/books\"\n" +" assert!(correspondencia_prefixo(\n" +" \"/v1/autores/*/livros\",\n" +" \"/v1/autores/bar/livros\"\n" " ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books/book1\"\n" +" assert!(correspondencia_prefixo(\n" +" \"/v1/autores/*/livros\",\n" +" \"/v1/autores/foo/livros/livro1\"\n" " ));" #: src/exercises/day-2/strings-iterators.md:46 @@ -8826,10 +9183,10 @@ msgid "" "}\n" "```" msgstr "" -" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" -" assert!(!prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/booksByAuthor\"\n" +" assert!(!correspondencia_prefixo(\"/v1/autores/*/livros\", \"/v1/autores\"));\n" +" assert!(!correspondencia_prefixo(\n" +" \"/v1/autores/*/livros\",\n" +" \"/v1/autores/foo/livrosPorAutor\"\n" " ));\n" "}\n" "```" @@ -8840,47 +9197,45 @@ msgstr "# Bem-vindo ao Dia 3" #: src/welcome-day-3.md:3 msgid "Today, we will cover some more advanced topics of Rust:" -msgstr "Hoje, abordaremos alguns tópicos mais avançados do Rust:" +msgstr "Hoje, abordaremos alguns tópicos mais avançados em Rust:" #: src/welcome-day-3.md:5 msgid "" "* Traits: deriving traits, default methods, and important standard library\n" " traits." msgstr "" -"* Características: características derivadas, métodos padrão e importante biblioteca padrão\n" -" características." +"* Traits (Características): Traits derivadas, métodos padrão e Traits importantes da biblioteca padrão." #: src/welcome-day-3.md:8 msgid "" "* Generics: generic data types, generic methods, monomorphization, and trait\n" " objects." msgstr "" -"* Genéricos: tipos de dados genéricos, métodos genéricos, monomorfização e trait\n" +"* Generics (Genéricos): tipos de dados genéricos, métodos genéricos, monomorfização e trait\n" " objetos." #: src/welcome-day-3.md:11 msgid "* Error handling: panics, `Result`, and the try operator `?`." -msgstr "* Tratamento de erros: panics, `Result` e o operador try `?`." +msgstr "* Tratamento de erros: pânico (_panics_), `Result` e o operador _try_ `?`." #: src/welcome-day-3.md:13 msgid "* Testing: unit tests, documentation tests, and integration tests." -msgstr "* Testes: tests de unage, testes de documentação e testes de integração." +msgstr "* Testes: testes unitários, testes de documentação e testes de integração." #: src/welcome-day-3.md:15 msgid "" "* Unsafe Rust: raw pointers, static variables, unsafe functions, and extern\n" " functions." msgstr "" -"* Rust inseguro: ponteiros brutos, variáveis estáticas, funções inseguras e funções externas\n" -" funções." +"* Rust inseguro (unsafe): ponteiros brutos, variáveis estáticas, funções inseguras e funções externas." #: src/traits.md:1 msgid "# Traits" -msgstr "# Características" +msgstr "# Traits (Características)" #: src/traits.md:3 msgid "Rust lets you abstract over types with traits. They're similar to interfaces:" -msgstr "Rust permite abstrair tipos com características. Eles são semelhantes às interfaces:" +msgstr "Rust permite abstrair características dos tipos usando `trait`. Eles são semelhantes às interfaces:" #: src/traits.md:5 msgid "" @@ -8890,25 +9245,23 @@ msgid "" "}" msgstr "" "```rust,editable\n" -"trait Greet {\n" -" fn say_hello(&self);\n" +"trait Saudar {\n" +" fn diz_ola(&self);\n" "}" #: src/traits.md:10 -#, fuzzy msgid "" "struct Dog {\n" " name: String,\n" "}" msgstr "" "struct Cachorro {\n" -" name: String,\n" +" nome: String,\n" "}" #: src/traits.md:14 -#, fuzzy msgid "struct Cat; // No name, cats won't respond to it anyway." -msgstr "Cat estrutura; // Sem name, os gatos não vão responder de qualquer maneira." +msgstr "struct Gato; // Sem nome, os gatos não vão responder de qualquer maneira." #: src/traits.md:16 msgid "" @@ -8918,9 +9271,9 @@ msgid "" " }\n" "}" msgstr "" -"impl Greet for Dog {\n" -" fn say_hello(&self) {\n" -" println!(\"Wuf, meu name é {}!\", self.name);\n" +"impl Saudar for Cachorro {\n" +" fn diz_ola(&self) {\n" +" println!(\"Wuf, meu nome é {}!\", self.nome);\n" " }\n" "}" @@ -8932,8 +9285,8 @@ msgid "" " }\n" "}" msgstr "" -"impl Greet for Cat {\n" -" fn say_hello(&self) {\n" +"impl Saudar for Gato {\n" +" fn diz_ola(&self) {\n" " println!(\"Miau!\");\n" " }\n" "}" @@ -8952,12 +9305,12 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let pets: Vec> = vec![\n" -" Box::new(Dog { name: String::from(\"Fido\") }),\n" -" Box::new(Cat),\n" +" let pets: Vec> = vec![\n" +" Box::new(Cachorro{ nome: String::from(\"Fido\") }),\n" +" Box::new(Gato),\n" " ];\n" " for pet in pets {\n" -" pet.say_hello();\n" +" pet.diz_ola();\n" " }\n" "}\n" "```" @@ -8973,13 +9326,13 @@ msgid "" "a pointer to the actual object and a pointer to the virtual method table for the `Greet` implementation of that particular " "object." msgstr "" -"* Traits podem especificar métodos pré-implementados (padrão) e métodos que os usuários devem implementar por conta " +"* _Traits_ podem especificar métodos pré-implementados (padrão) e métodos que os usuários devem implementar por conta " "própria. Os métodos com implementações padrão podem contar com os métodos necessários.\n" "* Os tipos que implementam uma determinada característica podem ser de tamanhos diferentes. Isso torna impossível ter " "coisas como `Vec` no exemplo acima.\n" "* `dyn Greet` é uma maneira de dizer ao compilador sobre um tipo de tamanho dinâmico que implementa `Greet`.\n" -"* No exemplo, `pets` mantém Fat Pointers para objetos que implementam `Greet`. O Fat Pointer consiste em dois componentes, " -"um ponteiro para o objeto real e um ponteiro para a tabela de métodos virtuais para a implementação `Greet` desse objeto em " +"* No exemplo, `pets` mantém _Fat Pointers_ para objetos que implementam `Greet`. O _Fat Pointer_ consiste em dois componentes, " +"um ponteiro para o objeto real e um ponteiro para a tabela de métodos virtuais para a implementação de `Greet` desse objeto em " "particular." #: src/traits.md:46 @@ -9006,7 +9359,7 @@ msgstr "# traits derivados" #: src/traits/deriving-traits.md:3 msgid "You can let the compiler derive a number of traits:" -msgstr "Você pode deixar o compilador derivar uma série de características:" +msgstr "Você pode deixar o compilador derivar uma série de traits:" #: src/traits/deriving-traits.md:5 msgid "" @@ -9018,6 +9371,13 @@ msgid "" " hit_points: u8,\n" "}" msgstr "" +"```rust,editable\n" +"#[derive(Debug, Clone, PartialEq, Eq, Default)]\n" +"struct Jogador {\n" +" nome: String,\n" +" forca: u8,\n" +" pontos_vida: u8,\n" +"}" #: src/traits/deriving-traits.md:13 msgid "" @@ -9030,9 +9390,9 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let p1 = Player::default();\n" +" let p1 = Jogador::default();\n" " let p2 = p1.clone();\n" -" println!(\"É {:?}\\negual a {:?}?\\nA resposta é {}!\", &p1, &p2,\n" +" println!(\"É {:?}\\nigual a {:?}?\\nA resposta é {}!\", &p1, &p2,\n" " if p1 == p2 { \"sim\" } else { \"não\" });\n" "}\n" "```" @@ -9043,7 +9403,7 @@ msgstr "# Métodos Padrão" #: src/traits/default-methods.md:3 msgid "Traits can implement behavior in terms of other trait methods:" -msgstr "As características podem implementar o comportamento em termos de outros métodos de característica:" +msgstr "Traits podem implementar o comportamento em termos de outros métodos de `trait`:" #: src/traits/default-methods.md:5 msgid "" @@ -9056,10 +9416,10 @@ msgid "" "}" msgstr "" "```rust,editable\n" -"trait Equals {\n" -" fn equal(&self, other: &Self) -> bool;\n" -" fn not_equal(&self, other: &Self) -> bool {\n" -" !self.equal(other)\n" +"trait Iguais {\n" +" fn igual(&self, outro: &Self) -> bool;\n" +" fn diferente(&self, outro: &Self) -> bool {\n" +" !self.igual(outro)\n" " }\n" "}" @@ -9069,7 +9429,7 @@ msgid "" "struct Centimeter(i16);" msgstr "" "#[derive(Debug)]\n" -"struct Centimeter(i16);" +"struct Centimetro(i16);" #: src/traits/default-methods.md:16 msgid "" @@ -9079,9 +9439,9 @@ msgid "" " }\n" "}" msgstr "" -"impl Equals for Centimeter {\n" -" fn equal(&self, other: &Centimeter) -> bool {\n" -" self.0 == other.0\n" +"impl Iguais for Centimetro {\n" +" fn igual(&self, outro: &Centimetro) -> bool {\n" +" self.0 == outro.0\n" " }\n" "}" @@ -9095,14 +9455,21 @@ msgid "" "}\n" "```" msgstr "" +"fn main() {\n" +" let a = Centimetro(10);\n" +" let b = Centimetro(20);\n" +" println!(\"{a:?} é igual a {b:?}: {}\", a.igual(&b));\n" +" println!(\"{a:?} é diferente de {b:?}: {}\", a.diferente(&b));\n" +"}\n" +"```" #: src/traits/important-traits.md:1 msgid "# Important Traits" -msgstr "# traits importantes" +msgstr "# Traits importantes" #: src/traits/important-traits.md:3 msgid "We will now look at some of the most common traits of the Rust standard library:" -msgstr "Veremos agora algumas das características mais comuns da biblioteca padrão do Rust:" +msgstr "Veremos agora os _Traits_ mais comuns da biblioteca padrão do Rust:" #: src/traits/important-traits.md:5 msgid "" @@ -9113,12 +9480,12 @@ msgid "" "* [`Drop`][9] used for defining destructors.\n" "* [`Default`][10] used to construct a default instance of a type." msgstr "" -"* [`Iterator`][1] and [`IntoIterator`][2] used in `for` loops,\n" -"* [`From`][3] and [`Into`][4] used to convert values,\n" -"* [`Read`][5] and [`Write`][6] used for IO,\n" -"* [`Add`][7], [`Mul`][8], ... used for operator overloading, and\n" -"* [`Drop`][9] used for defining destructors.\n" -"* [`Default`][10] used to construct a default instance of a type." +"* [`Iterator`][1] e [`IntoIterator`][2] usados em laços `for`,\n" +"* [`From`][3] e [`Into`][4] usados na converção de valores,\n" +"* [`Read`][5] e [`Write`][6] usados em operações de IO,\n" +"* [`Add`][7], [`Mul`][8], ... usado na sobrecarga de operadores,\n" +"* [`Drop`][9] usado para definir destrutores e\n" +"* [`Default`][10] usado para construir uma instância padrão para um tipo." #: src/traits/important-traits.md:12 msgid "" @@ -9140,7 +9507,7 @@ msgstr "# Iteradores" #: src/traits/iterator.md:3 msgid "You can implement the [`Iterator`][1] trait on your own types:" -msgstr "Você pode implementar o trait `Iterator` em seus próprios tipos:" +msgstr "Você pode implementar o _trait_ `Iterator` em seus próprios tipos:" #: src/traits/iterator.md:5 msgid "" @@ -9190,12 +9557,11 @@ msgid "" " \n" "" msgstr "" -"* `IntoIterator` é o recurso que faz com que os loops funcionem. É implementado por tipos de coleção, como\n" +"* `IntoIterator` é o recurso que faz com que os laços funcionem. É implementado por tipos de coleção, como\n" " `Vec` e referências a eles, como `&Vec` e `&[T]`. Os intervalos também o implementam.\n" -"* O trait `Iterator` implementa muitas operações de programação funcional comuns sobre coleções\n" -" (por exemplo, `mapa`, `filtro`, `redução`, etc). Este é o trait onde você pode encontrar toda a documentação\n" -" sobre eles. Em Rust, essas funções devem produzir o código tão eficiente quanto o imperativo equivalente\n" -" implementações.\n" +"* O _trait_ `Iterator` implementa muitas operações de programação funcional comuns sobre coleções\n" +" (por exemplo, `mapa`, `filtro`, `redução`, etc). Este é o _trait_ onde você pode encontrar toda a documentação\n" +" sobre eles. Em Rust, essas funções devem produzir o código tão eficiente quanto a implementação imperativa equivalente.\n" " \n" "" @@ -9232,6 +9598,11 @@ msgid "" " B: FromIterator,\n" " Self: Sized`" msgstr "" +"`Iterator` implementa\n" +"`fn collect(self) -> B\n" +"where\n" +" B: FromIterator,\n" +" Self: Sized`" #: src/traits/from-iterator.md:23 msgid "" @@ -9251,7 +9622,7 @@ msgstr "" #: src/traits/from-into.md:1 msgid "# `From` and `Into`" -msgstr "# `De` e `Into`" +msgstr "# `From` e `Into`" #: src/traits/from-into.md:3 msgid "Types implement [`From`][1] and [`Into`][2] to facilitate type conversions:" @@ -9269,11 +9640,19 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let s = String::from(\"Olá\");\n" +" let endereco_ipv4 = std::net::Ipv4Addr::from([127, 0, 0, 1]);\n" +" let um = i16::from(true);\n" +" let maior = i32::from(123i16);\n" +" println!(\"{s}, {endereco_ipv4}, {um}, {maior}\");\n" +"}\n" +"```" #: src/traits/from-into.md:15 -#, fuzzy msgid "[`Into`][2] is automatically implemented when [`From`][1] is implemented:" -msgstr "`Into` é implementado automaticamente quando `From` é implementado:" +msgstr "[`Into`][2] é implementado automaticamente quando [`From`][1] é implementado:" #: src/traits/from-into.md:17 msgid "" @@ -9287,6 +9666,15 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let s: String = \"Olá\".into();\n" +" let endereco_ipv4: std::net::Ipv4Addr = [127, 0, 0, 1].into();\n" +" let um: i16 = true.into();\n" +" let maior: i32 = 123i16.into();\n" +" println!(\"{s}, {endereco_ipv4}, {um}, {maior}\");\n" +"}\n" +"```" #: src/traits/from-into.md:27 msgid "" @@ -9301,7 +9689,7 @@ msgid "" msgstr "" "
\n" " \n" -"* É por isso que é comum implementar apenas `From`, já que seu tipo também receberá implementação `Into`.\n" +"* É por isso que é comum implementar apenas `From`, já que seu tipo também receberá a implementação de `Into`.\n" "* Ao declarar um tipo de entrada de argumento de função como \"qualquer coisa que possa ser convertida em `String`\", a " "regra é oposta, você deve usar `Into`.\n" " Sua função aceitará tipos que implementam `From` e aqueles que _apenas_ implementam `Into`.\n" @@ -9322,7 +9710,7 @@ msgstr "# `Read` e `Write`" #: src/traits/read-write.md:3 msgid "Using [`Read`][1] and [`BufRead`][2], you can abstract over `u8` sources:" -msgstr "Usando `Read` e `BufRead`, você pode abstrair as fontes `u8`:" +msgstr "Usando `Read` e `BufRead`, você pode abstrair a leitura de conteúdos do tipo `u8`:" #: src/traits/read-write.md:5 msgid "" @@ -9337,6 +9725,10 @@ msgid "" " buf_reader.lines().count()\n" "}" msgstr "" +"fn contar_linhas(reader: R) -> usize {\n" +" let buf_reader = BufReader::new(reader);\n" +" buf_reader.lines().count()\n" +"}" #: src/traits/read-write.md:13 msgid "" @@ -9346,7 +9738,7 @@ msgid "" msgstr "" "fn main() -> Result<()> {\n" " let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" -" println!(\"linhas na slice: {}\", count_lines(slice));" +" println!(\"linhas na slice: {}\", contar_linhas(slice));" #: src/traits/read-write.md:17 msgid "" @@ -9357,15 +9749,14 @@ msgid "" "```" msgstr "" " let file = std::fs::File::open(std::env::current_exe()?)?;\n" -" println!(\"linhas no arquivo: {}\", count_lines(file));\n" +" println!(\"linhas no arquivo: {}\", contar_linhas(file));\n" " Ok(())\n" "}\n" "```" #: src/traits/read-write.md:23 -#, fuzzy msgid "Similarly, [`Write`][3] lets you abstract over `u8` sinks:" -msgstr "Da mesma forma, `Write` permite abstrair sobre coletores `u8`:" +msgstr "Da mesma forma, `Write` permite abstrair a escrita de dados do tipo `u8`:" #: src/traits/read-write.md:25 msgid "" @@ -9384,7 +9775,6 @@ msgid "" msgstr "" #: src/traits/read-write.md:33 -#, fuzzy msgid "" "fn main() -> Result<()> {\n" " let mut buffer = Vec::new();\n" @@ -9397,8 +9787,8 @@ msgid "" msgstr "" "fn main() -> Result<()> {\n" " let mut buffer = Vec::new();\n" -" log(&mut buffer, \"Olá\"?);\n" -" log(&mut buffer, \"Mundo\"?);\n" +" log(&mut buffer, \"Olá\")?;\n" +" log(&mut buffer, \"Mundo\")?;\n" " println!(\"Logado: {:?}\", buffer);\n" " Ok(())\n" "}\n" @@ -9416,11 +9806,11 @@ msgstr "" #: src/traits/operators.md:1 msgid "# `Add`, `Mul`, ..." -msgstr "# `Adicionar`, `Mul`, ..." +msgstr "# `Add`, `Mul`, ..." #: src/traits/operators.md:3 msgid "Operator overloading is implemented via traits in [`std::ops`][1]:" -msgstr "A sobrecargo do operador é implementada por meio de características em `std::ops`:" +msgstr "A sobrecarga de operadores é implementada por meio do `trait` contido em [`std::ops`][1]:" #: src/traits/operators.md:5 msgid "" @@ -9428,12 +9818,17 @@ msgid "" "#[derive(Debug, Copy, Clone)]\n" "struct Point { x: i32, y: i32 }" msgstr "" +"```rust,editable\n" +"#[derive(Debug, Copy, Clone)]\n" +"struct Ponto { x: i32, y: i32 }" #: src/traits/operators.md:9 src/exercises/day-2/solutions-morning.md:46 msgid "" "impl std::ops::Add for Point {\n" " type Output = Self;" msgstr "" +"impl std::ops::Add for Ponto {\n" +" type Output = Self;" #: src/traits/operators.md:12 msgid "" @@ -9442,6 +9837,10 @@ msgid "" " }\n" "}" msgstr "" +" fn add(self, other: Self) -> Self {\n" +" Self {x: self.x + other.x, y: self.y + other.y}\n" +" }\n" +"}" #: src/traits/operators.md:17 msgid "" @@ -9453,15 +9852,15 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let p1 = Point { x: 10, y: 20 };\n" -" let p2 = Point { x: 100, y: 200 };\n" +" let p1 = Ponto { x: 10, y: 20 };\n" +" let p2 = Ponto { x: 100, y: 200 };\n" " println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" "}\n" "```" #: src/traits/operators.md:26 src/traits/drop.md:34 msgid "Discussion points:" -msgstr "Points de discussão:" +msgstr "Pontos de discussão:" #: src/traits/operators.md:28 msgid "" @@ -9475,27 +9874,27 @@ msgid "" " associated types (like `Output`) are controlled by the implementor of a\n" " trait." msgstr "" -"* Você pode implementar `Add` para `&Point`. Em quais situações isso é útil?\n" +"* Você pode implementar `Add` para `&Ponto`. Em quais situações isso é útil?\n" " * Resposta: `Add:add` consome `self`. Se digitar `T` para o qual você está\n" -" sobrecarregar o operador não é `Copy`, você deve considerar sobrecarregar\n" +" sobrecarregando o operador não implementa `Copy`, você deve considerar sobrecarregar\n" " o operador para `&T` também. Isso evita a clonagem desnecessária no\n" -" local de chamada.\n" +" local da chamada.\n" "* Por que `Output` é um tipo associado? Poderia ser feito um parâmetro de tipo?\n" " * Resposta curta: os parâmetros de tipo são controlados pelo chamador, mas\n" -" tipos associados (como `Output`) são controlados pelo implementador de um\n" -" característica." +" tipos associados (como `Output`) são controlados pelo implementador do\n" +" `trait`." #: src/traits/operators.md:40 msgid "[1]: https://doc.rust-lang.org/std/ops/index.html" -msgstr "" +msgstr "[1]: https://doc.rust-lang.org/std/ops/index.html" #: src/traits/drop.md:1 msgid "# The `Drop` Trait" -msgstr "# A característica 'Drop'" +msgstr "# O Trait `Drop`" #: src/traits/drop.md:3 msgid "Values which implement [`Drop`][1] can specify code to run when they go out of scope:" -msgstr "Valores que implementam `Drop` podem especificar o código a ser executado quando saem do escopo:" +msgstr "Valores que implementam [`Drop`][1] podem especificar o código a ser executado quando saem do escopo:" #: src/traits/drop.md:5 msgid "" @@ -9504,6 +9903,10 @@ msgid "" " name: &'static str,\n" "}" msgstr "" +"```rust,editable\n" +"struct Excluivel {\n" +" nome: &'static str,\n" +"}" #: src/traits/drop.md:10 msgid "" @@ -9513,9 +9916,13 @@ msgid "" " }\n" "}" msgstr "" +"impl Drop for Excluivel {\n" +" fn drop(&mut self) {\n" +" println!(\"Executando 'Drop' {}\", self.nome);\n" +" }\n" +"}" #: src/traits/drop.md:16 -#, fuzzy msgid "" "fn main() {\n" " let a = Droppable { name: \"a\" };\n" @@ -9534,17 +9941,17 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let a = Droppable { name: \"a\" };\n" +" let a = Excluivel { nome: \"a\" };\n" " {\n" -" let b = Droppable { name: \"b\" };\n" +" let b = Excluivel { nome: \"b\" };\n" " {\n" -" let c = Droppable { name: \"c\" };\n" -" let d = Droppable { name: \"d\" };\n" +" let c = Excluivel { nome: \"c\" };\n" +" let d = Excluivel { nome: \"d\" };\n" " println!(\"Saindo do bloco B\");\n" " }\n" " println!(\"Saindo do bloco A\");\n" " }\n" -" soltar(a);\n" +" drop(a);\n" " println!(\"Saindo do main\");\n" "}\n" "```" @@ -9557,10 +9964,9 @@ msgid "" " overflow!\n" "* Try replacing `drop(a)` with `a.drop()`." msgstr "" -"* Por que `Drop::drop` não leva `self`?\n" -" * Resposta curta: Se tivesse, `std::mem::drop` seria chamado no final de\n" -" o bloco, resultando em outra chamada para `Drop::drop`, e uma pilha\n" -" transbordar!\n" +"* Por que `Drop::drop` não recebe `self`?\n" +" * Resposta curta: Se recebesse, `std::mem::drop` seria chamado no final do\n" +" bloco, resultando em outra chamada para `Drop::drop` ocasionando um estouro de pilha.\n" "* Tente substituir `drop(a)` por `a.drop()`." #: src/traits/drop.md:44 @@ -9569,11 +9975,11 @@ msgstr "[1]: https://doc.rust-lang.org/std/ops/trait.Drop.html" #: src/traits/default.md:1 msgid "# The `Default` Trait" -msgstr "# A característica 'Drop'" +msgstr "# O Trait `Default`" #: src/traits/default.md:3 msgid "[`Default`][1] trait provides a default implementation of a trait." -msgstr "" +msgstr "O `trait` [`Default`][1] fornece uma implementação padrão para um `trait`." #: src/traits/default.md:5 msgid "" @@ -9587,10 +9993,10 @@ msgid "" msgstr "" "```rust,editable\n" "#[derive(Debug, Default)]\n" -"struct Derived {\n" +"struct Derivado {\n" " x: u32,\n" " y: String,\n" -" z: Implemented,\n" +" z: Implementado,\n" "}" #: src/traits/default.md:13 @@ -9598,6 +10004,8 @@ msgid "" "#[derive(Debug)]\n" "struct Implemented(String);" msgstr "" +"#[derive(Debug)]\n" +"struct Implementado(String);" #: src/traits/default.md:16 msgid "" @@ -9607,6 +10015,11 @@ msgid "" " }\n" "}" msgstr "" +"impl Default for Implementado {\n" +" fn default() -> Self {\n" +" Self(\"Fulano de tal\".into())\n" +" }\n" +"}" #: src/traits/default.md:22 msgid "" @@ -9614,6 +10027,9 @@ msgid "" " let default_struct: Derived = Default::default();\n" " println!(\"{default_struct:#?}\");" msgstr "" +"fn main() {\n" +" let estrutura_default: Derivado = Default::default();\n" +" println!(\"{estrutura_default:#?}\");" #: src/traits/default.md:26 msgid "" @@ -9623,6 +10039,11 @@ msgid "" " };\n" " println!(\"{almost_default_struct:#?}\");" msgstr "" +" let estrutura_quase_default = Derivado {\n" +" y: \"Y é atribuído!\".into(),\n" +" ..Default::default()\n" +" };\n" +" println!(\"{estrutura_quase_default:#?}\");" #: src/traits/default.md:32 msgid "" @@ -9630,6 +10051,9 @@ msgid "" " println!(\"{:#?}\", nothing.unwrap_or_default());\n" "}" msgstr "" +" let nada: Option = None;\n" +" println!(\"{:#?}\", nada.unwrap_or_default());\n" +"}" #: src/traits/default.md:40 msgid "" @@ -9640,6 +10064,14 @@ msgid "" " * The partial struct copy works nicely with default.\n" " * Rust standard library is aware that types can implement `Default` and provides convenience methods that use it." msgstr "" +" * Ele pode ser implementado diretamente ou derivado usando `#[derive(Default)]`.\n" +" * A implementação usando `derive` produz uma instância onde todos os campos são preenchidos\n" +" com seus valores padrão.\n" +" * Consequentemente, todos os tipos usados na estrutuda devem implementar `Default` também.\n" +" * Frequentemente, os tipos padrão do Rust implementam `Default` com valores razoáveis (ex: `0`, `\"\"`, etc).\n" +" * A cópia parcial de estrututas funciona bem em conjunto com _default_.\n" +" * A bilioteca padrão do Rust sabe que tipos podem implementar o `trait` `Default` e, convenientemente,\n" +" provê métodos para isso." #: src/traits/default.md:49 msgid "[1]: https://doc.rust-lang.org/std/default/trait.Default.html" @@ -9647,15 +10079,15 @@ msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" #: src/generics.md:1 msgid "# Generics" -msgstr "# Genéricos" +msgstr "# Generics (Genéricos)" #: src/generics.md:3 msgid "" "Rust support generics, which lets you abstract an algorithm (such as sorting)\n" "over the types used in the algorithm." msgstr "" -"Rust oferece suporte a genéricos, que permitem abstrair um algoritmo (como classificação)\n" -"sobre os tipos usados no algoritmo." +"Rust oferece suporte a tipos genéricos, que permitem a um algoritmo (como classificação, por exemplo),\n" +"abstrair os tipos de dados usados no algoritmo." #: src/generics/data-types.md:1 msgid "# Generic Data Types" @@ -9663,7 +10095,7 @@ msgstr "# Tipos de dados genéricos" #: src/generics/data-types.md:3 msgid "You can use generics to abstract over the concrete field type:" -msgstr "Você pode usar genéricos para abstrair sobre o tipo de campo concreto:" +msgstr "Você pode usar tipos genéricos para abstrair o tipo concreto do campo:" #: src/generics/data-types.md:5 msgid "" @@ -9676,7 +10108,7 @@ msgid "" msgstr "" "```rust,editable\n" "#[derive(Debug)]\n" -"struct Point {\n" +"struct Ponto {\n" " x: T,\n" " y: T,\n" "}" @@ -9691,9 +10123,9 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let integer = Point { x: 5, y: 10 };\n" -" let float = Point { x: 1.0, y: 4.0 };\n" -" println!(\"{integer:?} e {float:?}\");\n" +" let inteiro = Ponto { x: 5, y: 10 };\n" +" let real = Ponto { x: 1.0, y: 4.0 };\n" +" println!(\"{inteiro:?} e {real:?}\");\n" "}\n" "```" @@ -9713,7 +10145,7 @@ msgid "" msgstr "" "```rust, editable\n" "#[derive(Debug)]\n" -"struct Point(T, T);" +"struct Ponto(T, T);" #: src/generics/methods.md:9 msgid "" @@ -9722,7 +10154,7 @@ msgid "" " &self.0 // + 10\n" " }" msgstr "" -"impl Point {\n" +"impl Ponto {\n" " fn x(&self) -> &T {\n" " &self.0 // + 10\n" " }" @@ -9744,7 +10176,7 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let p = Point(5, 10);\n" +" let p = Ponto(5, 10);\n" " println!(\"p.x = {}\", p.x());\n" "}\n" "```" @@ -9758,13 +10190,13 @@ msgid "" " * `Point` is still generic and you can use `Point`, but methods in this block will only be available for " "`Point`." msgstr "" -"* *P:* Por que `T` é especificado duas vezes em `impl Point {}`? Isso não é redundante?\n" +"* *Pergunta:* Por que `T` é especificado duas vezes em `impl Ponto {}`? Isso não é redundante?\n" " * Isso ocorre porque é uma seção de implementação genérica para tipo genérico. Eles são genéricos de forma " "independente.\n" " * Significa que esses métodos são definidos para qualquer `T`.\n" -" * É possível escrever `Impl Point { .. }`.\n" -" * `Point` ainda é genérico e você pode usar `Point`, mas os métodos neste bloco só estarão disponíveis para " -"`Point`." +" * É possível escrever `Impl Ponto { .. }`.\n" +" * `Ponto` ainda é genérico e você pode usar `Ponto`, mas os métodos neste bloco só estarão disponíveis para " +"`Ponto`." #: src/generics/trait-bounds.md:1 msgid "# Trait Bounds" @@ -9775,15 +10207,14 @@ msgid "" "When working with generics, you often want to require the types to implement\n" "some trait, so that you can call this trait's methods." msgstr "" -"Ao trabalhar com genéricos, muitas vezes você deseja limitar os tipos. Você consegue fazer isso\n" -"com `T:Trait` ou `impl Trait`:" +"Ao trabalhar com genéricos, muitas vezes você exigir que os tipos implementem algum `trait`\n" +" para poder utilizar os métodos do `trait`." #: src/generics/trait-bounds.md:6 msgid "You can do this with `T: Trait` or `impl Trait`:" -msgstr "" +msgstr "Você consegue fazer isso com `T:Trait` ou `impl Trait`:" #: src/generics/trait-bounds.md:8 -#, fuzzy msgid "" "```rust,editable\n" "fn duplicate(a: T) -> (T, T) {\n" @@ -9791,26 +10222,29 @@ msgid "" "}" msgstr "" "```rust, editable\n" -"fn duplicado(a: T) -> (T, T) {\n" +"fn duplicar(a: T) -> (T, T) {\n" " (a.clone(), a.clone())\n" "}" -#~ #: src/generics/trait-bounds.md:13 -#~ msgid "" -#~ "// Syntactic sugar for:\n" -#~ "// fn add_42_millions>(x: T) -> i32 {\n" -#~ "fn add_42_millions(x: impl Into) -> i32 {\n" -#~ " x.into() + 42_000_000\n" -#~ "}" -#~ msgstr "" +#: src/generics/trait-bounds.md:13 +msgid "" +"// Syntactic sugar for:\n" +"// fn add_42_millions>(x: T) -> i32 {\n" +"fn add_42_millions(x: impl Into) -> i32 {\n" +" x.into() + 42_000_000\n" +"}" +msgstr "" +"// Açucar sintático para:\n" +"// fn somar_42_milhoes>(x: T) -> i32 {\n" +"fn somar_42_milhoes(x: impl Into) -> i32 {\n" +" x.into() + 42_000_000\n" +"}" #: src/generics/trait-bounds.md:19 -#, fuzzy msgid "// struct NotClonable;" -msgstr "// estrutura NotClonable;" +msgstr "// struct NotClonable;" #: src/generics/trait-bounds.md:21 -#, fuzzy msgid "" "fn main() {\n" " let foo = String::from(\"foo\");\n" @@ -9820,22 +10254,25 @@ msgstr "" "fn main() {\n" " let foo = String::from(\"foo\");\n" " let par = duplicar(foo);\n" -" println!(\"{par:?}\");\n" +" println!(\"{par:?}\");" + +#: src/generics/trait-bounds.md:26 +msgid "" +" let many = add_42_millions(42_i8);\n" +" println!(\"{many}\");\n" +" let many_more = add_42_millions(10_000_000);\n" +" println!(\"{many_more}\");\n" +"}\n" +"```" +msgstr "" +" let muito = somar_42_milhoes(42_i8);\n" +" println!(\"{muito}\");\n" +" let muito_mais = somar_42_milhoes(10_000_000);\n" +" println!(\"{muito_mais}\");\n" "}\n" "```" - -#~ #: src/generics/trait-bounds.md:26 -#~ msgid "" -#~ " let many = add_42_millions(42_i8);\n" -#~ " println!(\"{many}\");\n" -#~ " let many_more = add_42_millions(10_000_000);\n" -#~ " println!(\"{many_more}\");\n" -#~ "}\n" -#~ "```" -#~ msgstr "" #: src/generics/trait-bounds.md:35 -#, fuzzy msgid "" "Show a `where` clause, students will encounter it when reading code.\n" " \n" @@ -9851,8 +10288,8 @@ msgstr "" "Mostre uma cláusula `where`, os alunos a encontrarão ao ler o código.\n" " \n" "```rust, ignore\n" -"fn duplicado(a: T) -> (T, T)\n" -"Onde\n" +"fn duplicar(a: T) -> (T, T)\n" +"where\n" " T: Clone,\n" "{\n" " (a.clone(), a.clone())\n" @@ -9874,17 +10311,16 @@ msgstr "" "
" #: src/generics/impl-trait.md:1 -#, fuzzy msgid "# `impl Trait`" -msgstr "# `Impl Trait`" +msgstr "# Trait `impl`" #: src/generics/impl-trait.md:3 msgid "" "Similar to trait bounds, an `impl Trait` syntax can be used in function\n" "arguments and return values:" msgstr "" -"Semelhante aos limites do trait, uma sintaxe `impl Trait` pode ser usada na função\n" -"argumentos e valores de retorno:" +"Semelhante aos limites do _trait_, a sintaxe do _trait_ `impl` pode ser usada em argumentos de funções\n" +"e em valores de retorno:" #: src/generics/impl-trait.md:6 src/generics/trait-objects.md:5 src/generics/trait-objects.md:28 msgid "" @@ -9895,14 +10331,13 @@ msgstr "" "use std::fmt::Display;" #: src/generics/impl-trait.md:9 -#, fuzzy msgid "" "fn get_x(name: impl Display) -> impl Display {\n" " format!(\"Hello {name}\")\n" "}" msgstr "" -"fn get_x(name: display impl) -> display impl {\n" -" format!(\"Olá {name}\")\n" +"fn get_x(nome: impl Display) -> impl Display {\n" +" format!(\"Olá {nome}\")\n" "}" #: src/generics/impl-trait.md:13 @@ -9924,12 +10359,12 @@ msgid "" "* `impl Trait` cannot be used with the `::<>` turbo fish syntax.\n" "* `impl Trait` allows you to work with types which you cannot name." msgstr "" -"* `Impl Trait` não pode ser usado com a sintaxe `::<>` turbo fish.\n" -"* `Impl Trait` permite que você trabalhe com tipos que você não pode namear." +"* `impl Trait` não pode ser usado com a sintaxe turbo fish `::<>`.\n" +"* `impl Trait` permite que você trabalhe com tipos que você não pode nomear." #: src/generics/impl-trait.md:24 msgid "The meaning of `impl Trait` is a bit different in the different positions." -msgstr "O significado de 'impl Trait' é um pouco diferente nas diferentes posições." +msgstr "O significado do _trait_ `impl` é um pouco difere de acordo com sua posição." #: src/generics/impl-trait.md:26 msgid "" @@ -9938,9 +10373,9 @@ msgid "" " without naming the type. This can be useful when you don't want to expose the concrete type in a\n" " public API." msgstr "" -"* Para um parâmetro, `impl Trait` é como um parâmetro genérico anônimo com um limite de característica.\n" -"* Para um tipo de retorno, significa que o tipo de retorno é algum tipo concreto que implementa o trait,\n" -" sem namear o tipo. Isso pode ser útil quando você não deseja expor o tipo concreto em um\n" +"* Como parâmetro, o _trait_ `impl` é como um parâmetro genérico anônimo com um limitador de características (trait).\n" +"* Como tipo de retorno, significa que o tipo de retorno é algum tipo concreto que implementa o _trait_,\n" +" sem namear o tipo. Isso pode ser útil quando você não deseja expor o tipo concreto em uma\n" " API pública." #: src/generics/impl-trait.md:31 @@ -9955,9 +10390,9 @@ msgid "" "" msgstr "" "Este exemplo é ótimo, porque usa `impl Display` duas vezes. Isso ajuda a explicar\n" -"nada aqui impõe que seja _o mesmo_ tipo `impl Display`. Se usássemos um único\n" +"que nada impõe que, nos dois usos, `impl Display` seja _do mesmo_ tipo. Se usássemos um único\n" "`T: Display`, imporia a restrição de que o tipo `T` de entrada e o tipo `T` de retorno são do mesmo tipo.\n" -"Não funcionaria para esta função específica, pois o tipo que esperamos como entrada provavelmente não é\n" +"Isso não funcionaria para esta função específica, pois o tipo que esperamos como entrada provavelmente não é\n" "o que `format!` retorna. Se quiséssemos fazer o mesmo através da sintaxe `: Display`, precisaríamos de dois\n" "parâmetros genéricos independentes.\n" " \n" @@ -9965,7 +10400,7 @@ msgstr "" #: src/generics/closures.md:1 msgid "# Closures" -msgstr "# fechamentos" +msgstr "# Closures" #: src/generics/closures.md:3 msgid "" @@ -9974,10 +10409,10 @@ msgid "" "[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html), and\n" "[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) traits:" msgstr "" -"Closures ou expressões lambda têm tipos que não podem ser nameados. No entanto, eles\n" -"implementar especial [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" +"Closures ou expressões _lambda_ têm tipos que não podem ser nomeados. No entanto, eles\n" +"implementam os _traits_ especiais [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),\n" "[`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html) e\n" -"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) características:" +"[`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html):" #: src/generics/closures.md:8 msgid "" @@ -9988,9 +10423,9 @@ msgid "" "}" msgstr "" "```rust,editable\n" -"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" -" println!(\"Calling function on {input}\");\n" -" func(input)\n" +"fn aplicar_com_registro(funcao: impl FnOnce(i32) -> i32, entrada: i32) -> i32 {\n" +" println!(\"Chamando a função com {entrada}\");\n" +" funcao(entrada)\n" "}" #: src/generics/closures.md:14 @@ -10000,8 +10435,8 @@ msgid "" " let mul_5 = |x| x * 5;" msgstr "" "fn main() {\n" -" let add_3 = |x| x + 3;\n" -" let mul_5 = |x| x * 5;" +" let soma_3 = |x| x + 3;\n" +" let multiplica_5 = |x| x * 5;" #: src/generics/closures.md:18 msgid "" @@ -10010,14 +10445,14 @@ msgid "" "}\n" "```" msgstr "" -" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" -" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" +" println!(\"soma_3: {}\", aplicar_com_registro(soma_3, 10));\n" +" println!(\"multiplica_5: {}\", aplicar_com_registro(multiplica_5, 20));\n" "}\n" "```" #: src/generics/closures.md:25 msgid "If you have an `FnOnce`, you may only call it once. It might consume captured values." -msgstr "Se você tiver um `FnOnce`, poderá chamá-lo apenas uma vez. Pode consumir valores capturados." +msgstr "Se você tiver um `FnOnce`, poderá chamá-lo apenas uma vez. Pode consumir os valores capturados." #: src/generics/closures.md:27 msgid "An `FnMut` might mutate captured values, so you can call it multiple times but not concurrently." @@ -10028,7 +10463,7 @@ msgid "" "An `Fn` neither consumes nor mutates captured values, or perhaps captures nothing at all, so it can\n" "be called multiple times concurrently." msgstr "" -"Um `Fn` não consome nem muda os valores capturados, ou talvez não capture nada, então pode\n" +"Um `Fn` não consome nem muda os valores capturados ou talvez não capture nada, então, pode\n" "ser chamado várias vezes simultaneamente." #: src/generics/closures.md:32 @@ -10037,13 +10472,13 @@ msgid "" "`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever an `FnMut` or `FnOnce`\n" "is called for." msgstr "" -"`FnMut` é um subtipo de `FnOnce`. `Fn` é um subtipo de `FnMut` e `FnOnce`. ou seja você pode usar um\n" -"`FnMut` sempre que um `FnOnce` é chamado, e você pode usar um `Fn` sempre que um `FnMut` ou `FnOnce`\n" +"`FnMut` é um subtipo de `FnOnce`. `Fn` é um subtipo de `FnMut` e `FnOnce`. Ou seja você pode usar um\n" +"`FnMut` sempre que um `FnOnce` é chamado e você pode usar um `Fn` sempre que um `FnMut` ou um `FnOnce`\n" "é chamado." #: src/generics/closures.md:36 msgid "`move` closures only implement `FnOnce`." -msgstr "Fechamentos `move` implementam apenas `FnOnce`." +msgstr "_Closures_ `move` implementam apenas `FnOnce`." #: src/generics/monomorphization.md:1 msgid "# Monomorphization" @@ -10051,10 +10486,9 @@ msgstr "# Monomorfização" #: src/generics/monomorphization.md:3 msgid "Generic code is turned into non-generic code based on the call sites:" -msgstr "O código genérico é transformado em código não genérico com base nos sites de chamadas:" +msgstr "O código _genérico_ é transformado em código _não genérico_ de acordo com os tipos usados:" #: src/generics/monomorphization.md:5 -#, fuzzy msgid "" "```rust,editable\n" "fn main() {\n" @@ -10065,8 +10499,8 @@ msgid "" msgstr "" "```rust, editable\n" "fn main() {\n" -" let integer = Some(5);\n" -" let flutuar = Some(5.0);\n" +" let inteiro = Some(5);\n" +" let real = Some(5.0);\n" "}\n" "```" @@ -10109,8 +10543,8 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let integer = Option_i32::Some(5);\n" -" let float = Option_f64::Some(5.0);\n" +" let inteiro = Option_i32::Some(5);\n" +" let real = Option_f64::Some(5.0);\n" "}\n" "```" @@ -10120,15 +10554,15 @@ msgid "" "hand-coded the data structures without the abstraction." msgstr "" "Esta é uma abstração de custo zero: você obtém exatamente o mesmo resultado como se tivesse\n" -"codificou manualmente as Structs de dados sem a abstração." +"codificado manualmente as estruturas de dados sem utilizar a abstração." #: src/generics/trait-objects.md:1 msgid "# Trait Objects" -msgstr "# Objetos de característica" +msgstr "# Objetos `trait`" #: src/generics/trait-objects.md:3 msgid "We've seen how a function can take arguments which implement a trait:" -msgstr "Vimos como uma função pode receber argumentos que implementam uma característica:" +msgstr "Vimos como uma função pode receber argumentos que implementam um `trait` :" #: src/generics/trait-objects.md:8 msgid "" @@ -10141,7 +10575,6 @@ msgstr "" "}" #: src/generics/trait-objects.md:12 -#, fuzzy msgid "" "fn main() {\n" " print(123);\n" @@ -10150,8 +10583,8 @@ msgid "" "```" msgstr "" "fn main() {\n" -" imprimir(123);\n" -" imprima(\"Olá\");\n" +" print(123);\n" +" print(\"Olá\");\n" "}\n" "```" @@ -10175,7 +10608,7 @@ msgstr "" #: src/generics/trait-objects.md:26 msgid "For this, we need _trait objects_:" -msgstr "Para isso, precisamos de _trait objects_:" +msgstr "Para isso, precisamos de objetos de _traits_:" #: src/generics/trait-objects.md:31 msgid "" @@ -10188,7 +10621,7 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let xs: Vec> = vec![Box::new(123), Box::new(\"Hello\")];\n" +" let xs: Vec> = vec![Box::new(123), Box::new(\"Olá\")];\n" " for x in xs {\n" " println!(\"x: {x}\");\n" " }\n" @@ -10200,7 +10633,6 @@ msgid "Memory layout after allocating `xs`:" msgstr "Layout da memória após alocar `xs`:" #: src/generics/trait-objects.md:41 -#, fuzzy msgid "" "```bob\n" " Stack Heap\n" @@ -10215,7 +10647,7 @@ msgid "" ": : : | | | +----+----+----+----+----+ :\n" "`- - - - - - - - - - - - - -' : | | | :\n" " : | | | +-------------------------+ :\n" -" : | | '---->| \"::fmt\" | :\n" +" : | | '---->|\"::fmt\"| :\n" " : | | +-------------------------+ :\n" " : | | :\n" " : | | +----+----+----+----+ :\n" @@ -10223,7 +10655,7 @@ msgid "" " : | +----+----+----+----+ :\n" " : | :\n" " : | +-------------------------+ :\n" -" : '---->| \"::fmt\" | :\n" +" : '---->|\"::fmt\"| :\n" " : +-------------------------+ :\n" " : :\n" " : :\n" @@ -10231,30 +10663,30 @@ msgid "" "```" msgstr "" "```bob\n" -" Pilha\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.\n" -": : : :\n" -": xs : : :\n" -": +-----------+-------+ : : +-----+-----+ :\n" -": | ptr | o---+---+-----+-->| oo | oo | :\n" -": | len | 2 | : : +-|-|-+-|-|-+ :\n" -": | capacage | 2 | : : | | | | +----+----+----+----+----+ :\n" -": +-----------+-------+ : : | | | '-->| H | e | eu | eu | o | :\n" -": : : | | | +----+----+----+----+----+:\n" -"`- - - - - - - - - - - - - -' : | | | :\n" -" : | | | +-------------------------+ :\n" -" : | | '---->| \"::fmt\" | :\n" -" : | | +-------------------------+ :\n" -" : | | :\n" -" : | | +----+----+----+----+:\n" -" : | '-->| 7b | 00 | 00 | 00 | :\n" -" : | +----+----+----+----+ :\n" -" : | :\n" -" : | +-------------------------+ :\n" -" : '---->| \"::fmt\" | :\n" -" : +-------------------------+ :\n" -" : :\n" -" : :\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.\n" +": : : :\n" +": xs : : :\n" +": +------------+-------+ : : +-----+-----+ :\n" +": | ponteir | o---+--+-----+-->| o o | o o | :\n" +": | tamanho | 2 | : : +-|-|-+-|-|-+ :\n" +": | capacidade | 2 | : : | | | | +----+----+----+ :\n" +": +------------+-------+ : : | | | '-->| O | l | á | :\n" +": : : | | | +----+----+----+ :\n" +"`- - - - - - - - - - - - - -' : | | | :\n" +" : | | | +-------------------------+ :\n" +" : | | '---->|\"::fmt\"| :\n" +" : | | +-------------------------+ :\n" +" : | | :\n" +" : | | +----+----+----+----+ :\n" +" : | '-->| 7b | 00 | 00 | 00 | :\n" +" : | +----+----+----+----+ :\n" +" : | :\n" +" : | +-------------------------+ :\n" +" : '---->|\"::fmt\"| :\n" +" : +-------------------------+ :\n" +" : :\n" +" : :\n" " '- - - - - - - - - - - - - - - - - - - - - - - -'\n" "```" @@ -10263,8 +10695,8 @@ msgid "" "Similarly, you need a trait object if you want to return different types\n" "implementing a trait:" msgstr "" -"Da mesma forma, você precisa de um objeto de característica se quiser retornar valores diferentes\n" -"implementando uma característica:" +"Da mesma forma, você precisa de um objeto de _traits_ se quiser retornar valores diferentes\n" +"implementando um `trait`:" #: src/generics/trait-objects.md:72 msgid "" @@ -10278,7 +10710,7 @@ msgid "" "}" msgstr "" "```rust,editable\n" -"fn numbers(n: i32) -> Box> {\n" +"fn numeros(n: i32) -> Box> {\n" " if n > 0 {\n" " Box::new(0..n)\n" " } else {\n" @@ -10294,8 +10726,8 @@ msgid "" "}" msgstr "" "fn main() {\n" -" println!(\"{:?}\", numbers(-5).collect::>());\n" -" println!(\"{:?}\", numbers(5).collect::>());\n" +" println!(\"{:?}\", numeros(-5).collect::>());\n" +" println!(\"{:?}\", numeros(5).collect::>());\n" "}" #: src/exercises/day-3/morning.md:1 @@ -10304,7 +10736,7 @@ msgstr "# Dia 3: Exercícios matinais" #: src/exercises/day-3/morning.md:3 msgid "We will design a classical GUI library traits and trait objects." -msgstr "Vamos projetar uma biblioteca clássica de traits de GUI e objetos de trait." +msgstr "Vamos projetar uma biblioteca clássica de _traits_ de GUI e objetos de `trait`." #: src/exercises/day-3/simple-gui.md:1 msgid "# A Simple GUI Library" @@ -10315,12 +10747,12 @@ msgid "" "Let us design a classical GUI library using our new knowledge of traits and\n" "trait objects." msgstr "" -"Vamos projetar uma biblioteca GUI clássica usando nosso novo conhecimento de características e\n" -"objetos de traits." +"Vamos projetar uma biblioteca GUI clássica usando nosso novo conhecimento de _traits_ e\n" +"objetos de `trait`." #: src/exercises/day-3/simple-gui.md:6 msgid "We will have a number of widgets in our library:" -msgstr "Teremos vários widgets em nossa biblioteca:" +msgstr "Teremos vários _widgets_ em nossa biblioteca:" #: src/exercises/day-3/simple-gui.md:8 msgid "" @@ -10329,25 +10761,24 @@ msgid "" " button is pressed.\n" "* `Label`: has a `label`." msgstr "" -"* `Janela`: tem um `título` e contém outros widgets.\n" -"* `Button`: tem um `label` e uma função de callback que é invocada quando o\n" +"* `Window`: tem um `título` e contém outros _widgets_.\n" +"* `Button`: tem um `rótulo` e uma função de _callback_ que é invocada quando o\n" " botão é pressionado.\n" -"* `Label`: tem um `label`." +"* `Label`: tem um `rótulo`." #: src/exercises/day-3/simple-gui.md:13 msgid "The widgets will implement a `Widget` trait, see below." -msgstr "Os widgets irão implementar uma característica `Widget`, veja abaixo." +msgstr "Os _widgets_ irão implementar o `trait` `Widget`, veja abaixo." #: src/exercises/day-3/simple-gui.md:15 msgid "" "Copy the code below to , fill in the missing\n" "`draw_into` methods so that you implement the `Widget` trait:" msgstr "" -"Copie o código abaixo para , preencha os campos que faltam\n" -"métodos `draw_into` para que você implemente o trait `Widget`:" +"Copie o código abaixo para , codifique os\n" +"métodos `draw_into` para que você implemente o `trait` `Widget`:" #: src/exercises/day-3/simple-gui.md:18 src/exercises/day-3/safe-ffi-wrapper.md:25 -#, fuzzy msgid "" "```rust,should_panic\n" "// TODO: remove this when you're done with your implementation.\n" @@ -10355,7 +10786,7 @@ msgid "" msgstr "" "```rust,should_panic\n" "// TODO: remova isso quando terminar sua implementação.\n" -"#![allow(unused_imports, used_variables, dead_code)]" +"#![allow(unused_imports, unused_variables, dead_code)]" #: src/exercises/day-3/simple-gui.md:22 msgid "" @@ -10376,7 +10807,6 @@ msgstr "" " fn draw_into(&self, buffer: &mut dyn std::fmt::Write);" #: src/exercises/day-3/simple-gui.md:29 src/exercises/day-3/solutions-morning.md:30 -#, fuzzy msgid "" " /// Draw the widget on standard output.\n" " fn draw(&self) {\n" @@ -10387,8 +10817,8 @@ msgid "" "}" msgstr "" " /// Desenha o widget na saída padrão.\n" -" fn desenhar(&self) {\n" -" let buffer mudo = String::new();\n" +" fn draw(&self) {\n" +" let mut buffer = String::new();\n" " self.draw_into(&mut buffer);\n" " println!(\"{}\", &buffer);\n" " }\n" @@ -10545,7 +10975,6 @@ msgstr "" " }" #: src/exercises/day-3/simple-gui.md:112 -#, fuzzy msgid "" "fn main() {\n" " let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" @@ -10561,7 +10990,7 @@ msgstr "" "fn main() {\n" " let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" " window.add_widget(Box::new(Label::new(\"Esta é uma pequena demonstração de GUI de texto.\")));\n" -" window.add_widget(Caixa::new(Botão::new(\n" +" window.add_widget(Box::new(Button::new(\n" " \"Clique em mim!\",\n" " Box::new(|| println!(\"Você clicou no botão!\")),\n" " )));\n" @@ -10571,7 +11000,7 @@ msgstr "" #: src/exercises/day-3/simple-gui.md:123 msgid "The output of the above program can be something simple like this:" -msgstr "A saída do programa acima pode ser algo simples como isto:" +msgstr "A saída do programa acima pode ser algo simples como:" #: src/exercises/day-3/simple-gui.md:125 msgid "" @@ -10594,7 +11023,7 @@ msgid "" "| Click me! |\n" "```" msgstr "" -"| Clique em mim! |\n" +"| Clique-me! |\n" "```" #: src/exercises/day-3/simple-gui.md:135 @@ -10604,9 +11033,9 @@ msgid "" "formatting operators. In particular, notice how you can pad with different\n" "characters (here a `'/'`) and how you can control alignment:" msgstr "" -"Se você quiser desenhar texto alinhado, você pode usar o\n" -"[fill/alignment](https://doc.rust-lang.org/std/fmt/index.html#fillalignment)\n" -"operadores de formatação. Em particular, observe como você pode preencher com diferentes\n" +"Se você quiser desenhar texto alinhado, você pode usar os\n" +"operadores de formatação [fill/alignment](https://doc.rust-lang.org/std/fmt/index.html#fillalignment).\n" +"Em particular, observe como você pode preencher com diferentes\n" "caracteres (aqui um `'/'`) e como você pode controlar o alinhamento:" #: src/exercises/day-3/simple-gui.md:140 @@ -10622,10 +11051,10 @@ msgid "" msgstr "" "```rust, editable\n" "fn main() {\n" -" let width = 10;\n" -" println!(\"alinhado à esquerda: |{:/width$}|\", \"foo\");\n" +" let largura = 10;\n" +" println!(\"alinhado à esquerda: |{:/largura$}|\", \"foo\");\n" "}\n" "```" @@ -10647,14 +11076,14 @@ msgid "" "```" msgstr "" "```texto\n" -"+--------------------------------+\n" -"| Rust GUI Demonstração 1.23 |\n" -"+==================================+\n" +"+--------------------------------------------------+\n" +"| Rust GUI Demonstração 1.23 |\n" +"+==================================================+\n" "| Esta é uma pequena demonstração de GUI de texto. |\n" -"| +-----------+ |\n" -"| | Clique em mim! | |\n" -"| +-----------+ |\n" -"+--------------------------------+\n" +"| +----------------+ |\n" +"| | Clique-me! | |\n" +"| +----------------+ |\n" +"+--------------------------------------------------+\n" "```" #: src/error-handling.md:1 @@ -10663,23 +11092,23 @@ msgstr "# Manipulação de erros" #: src/error-handling.md:3 msgid "Error handling in Rust is done using explicit control flow:" -msgstr "O tratamento de erros no Rust é feito usando o fluxo de controle explícito:" +msgstr "O tratamento de erros em Rust é feito usando o fluxo de controle explícito:" #: src/error-handling.md:5 msgid "" "* Functions that can have errors list this in their return type,\n" "* There are no exceptions." msgstr "" -"* As funções que podem ter erros listam isso em seu tipo de retorno,\n" +"* As funções que podem ter erros mostram isso em seu tipo de retorno.\n" "* Não há exceções." #: src/error-handling/panics.md:1 msgid "# Panics" -msgstr "# Pânico" +msgstr "# Panics (Pânico)" #: src/error-handling/panics.md:3 msgid "Rust will trigger a panic if a fatal error happens at runtime:" -msgstr "O Rust acionará um pânico se um erro fatal ocorrer em tempo de execução:" +msgstr "O Rust disparará um _panic_ (pânico) se um erro fatal ocorrer em tempo de execução:" #: src/error-handling/panics.md:5 msgid "" @@ -10703,13 +11132,13 @@ msgid "" " * Panics are symptoms of bugs in the program.\n" "* Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." msgstr "" -"* Panics são para erros irrecuperáveis e inesperados.\n" +"* _Pânicos_ são para erros irrecuperáveis e inesperados.\n" " * Pânicos são sintomas de bugs no programa.\n" -"* Use APIs sem pânico (como `Vec::get`) se travar não for aceitável." +"* Use APIs que não disparam erros do tipo _pânico_ (como `Vec::get`) se travar o programa não for aceitável." #: src/error-handling/panic-unwind.md:1 msgid "# Catching the Stack Unwinding" -msgstr "# Pegando a pilha desenrolando" +msgstr "# Capturando o desenrolar da pilha" #: src/error-handling/panic-unwind.md:3 msgid "By default, a panic will cause the stack to unwind. The unwinding can be caught:" @@ -10736,7 +11165,6 @@ msgstr "" "assert!(result.is_ok());" #: src/error-handling/panic-unwind.md:13 -#, fuzzy msgid "" "let result = panic::catch_unwind(|| {\n" " panic!(\"oh no!\");\n" @@ -10745,7 +11173,7 @@ msgid "" "```" msgstr "" "let result = panic::catch_unwind(|| {\n" -" pânico!(\"oh não!\");\n" +" panic!(\"oh não!\");\n" "});\n" "assert!(result.is_err());\n" "```" @@ -10756,21 +11184,21 @@ msgid "" " request crashes.\n" "* This does not work if `panic = 'abort'` is set in your `Cargo.toml`." msgstr "" -"* Isso pode ser útil em servidores que devem continuar rodando mesmo se um único\n" -" pedido falha.\n" +"* Isso pode ser útil em servidores que devem continuar rodando mesmo se uma\n" +" requisição tenha falhado.\n" "* Isso não funciona se `panic = 'abort'` estiver definido em seu `Cargo.toml`." #: src/error-handling/result.md:1 msgid "# Structured Error Handling with `Result`" -msgstr "# Tratamento de erro estruturado com `Result`" +msgstr "# Tratamento estruturado de erros com `Result`" #: src/error-handling/result.md:3 msgid "" "We have already seen the `Result` enum. This is used pervasively when errors are\n" "expected as part of normal operation:" msgstr "" -"Já vimos a Enum `Result`. Isso é usado amplamente quando os erros são\n" -"esperado como parte da operação normal:" +"Já vimos o _Enum_ `Result`. Ele é usado amplamente quando os erros são\n" +"esperados como parte da operação normal:" #: src/error-handling/result.md:6 msgid "" @@ -10800,12 +11228,12 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let file = File::open(\"diary.txt\");\n" -" match file {\n" -" Ok(mut file) => {\n" -" let mut contents = String::new();\n" -" file.read_to_string(&mut contents);\n" -" println!(\"Querido diário: {contents}\");\n" +" let arquivo = File::open(\"diario.txt\");\n" +" match arquivo {\n" +" Ok(mut arquivo) => {\n" +" let mut conteudo = String::new();\n" +" arquivo.read_to_string(&mut conteudo);\n" +" println!(\"Querido diário: {conteudo}\");\n" " },\n" " Err(err) => {\n" " println!(\"Não foi possível abrir o diário: {err}\");\n" @@ -10826,9 +11254,9 @@ msgid "" msgstr "" " * Como em `Option`, o valor bem-sucedido fica dentro de `Result`, forçando o desenvolvedor a\n" " extraí-lo explicitamente. Isso encoraja a verificação de erros. No caso em que um erro nunca deve acontecer,\n" -" `unwrap()` ou `expect()` podem ser chamados, e isso também é um sinal da intenção do desenvolvedor.\n" -" * A documentação do `Resultado` é uma leitura recomendada. Não durante o curso, mas vale a pena mencionar.\n" -" Ele contém muitos métodos e funções de conveniência que ajudam na programação de estilo funcional.\n" +" `unwrap()` ou `expect()` podem ser chamados, e isso sinaliza a intenção do desenvolvedor.\n" +" * A documentação de `Result` é uma leitura recomendada. Não durante o curso, mas vale a pena mencioná-la.\n" +" Ele contém muitos métodos e funções de conveniência que ajudam na programação ao estilo funcional.\n" " \n" "" @@ -10841,8 +11269,8 @@ msgid "" "The try-operator `?` is used to return errors to the caller. It lets you turn\n" "the common" msgstr "" -"O operador try `?` é usado para retornar erros ao chamador. Ele permite que você vire\n" -"o comum" +"O operador _try_ `?` é usado para retornar erros ao chamador da função.\n" +"Se ocorrer um erro, este é retornado imediatamente ao chamador como retorno da função." #: src/error-handling/try-operator.md:6 msgid "" @@ -10854,15 +11282,15 @@ msgid "" "```" msgstr "" "```rust, ignore\n" -"match some_expression {\n" -" Ok(value) => value,\n" +"match alguma_expressao {\n" +" Ok(valor) => valor,\n" " Err(err) => return Err(err),\n" "}\n" "```" #: src/error-handling/try-operator.md:13 msgid "into the much simpler" -msgstr "no muito mais simples" +msgstr "Pode ser simplificado por:" #: src/error-handling/try-operator.md:15 msgid "" @@ -10871,7 +11299,7 @@ msgid "" "```" msgstr "" "```rust, ignore\n" -"some_expression?\n" +"alguma_expressao?\n" "```" #: src/error-handling/try-operator.md:19 @@ -10893,8 +11321,8 @@ msgid "" "fn read_username(path: &str) -> Result {\n" " let username_file_result = fs::File::open(path);" msgstr "" -"fn read_username(path: &str) -> Result {\n" -" let username_file_result = fs::File::open(path);" +"fn ler_nome_usuario(caminho: &str) -> Result {\n" +" let arquivo_nome_usuario_result = fs::File::open(caminho);" #: src/error-handling/try-operator.md:28 msgid "" @@ -10903,14 +11331,14 @@ msgid "" " Err(e) => return Err(e),\n" " };" msgstr "" -" let mut username_file = match username_file_result {\n" -" Ok(file) => file,\n" +" let mut arquivo_nome_usuario = match arquivo_nome_usuario_result {\n" +" Ok(arquivo) => arquivo,\n" " Err(e) => return Err(e),\n" " };" #: src/error-handling/try-operator.md:33 msgid " let mut username = String::new();" -msgstr "" +msgstr " let mut nome_usuario = String::new();" #: src/error-handling/try-operator.md:35 msgid "" @@ -10920,6 +11348,11 @@ msgid "" " }\n" "}" msgstr "" +" match arquivo_nome_usuario.read_to_string(&mut nome_usuario) {\n" +" Ok(_) => Ok(nome_usuario),\n" +" Err(e) => Err(e),\n" +" }\n" +"}" #: src/error-handling/try-operator.md:41 msgid "" @@ -10930,14 +11363,20 @@ msgid "" "}\n" "```" msgstr "" +"fn main() {\n" +" //fs::write(\"config.dat\", \"alice\").unwrap();\n" +" let nome_usuario = ler_nome_usuario(\"config.dat\");\n" +" println!(\"Nome de usuário ou erro: {nome_usuario:?}\");\n" +"}\n" +"```" #: src/error-handling/try-operator.md:52 src/error-handling/converting-error-types-example.md:52 msgid "" "* The `username` variable can be either `Ok(string)` or `Err(error)`.\n" "* Use the `fs::write` call to test out the different scenarios: no file, empty file, file with username." msgstr "" -"* A variável `username` pode ser `Ok(string)` ou `Err(error)`.\n" -"* Use a chamada `fs::write` para testar os diferentes cenários: nenhum arquivo, arquivo vazio, arquivo com name de usuário." +"* A variável `nome_usuario` pode ser `Ok(string)` ou `Err(error)`.\n" +"* Use a chamada `fs::write` para testar os diferentes cenários: nenhum arquivo, arquivo vazio e arquivo com name de usuário." #: src/error-handling/converting-error-types.md:1 src/error-handling/converting-error-types-example.md:1 msgid "# Converting Error Types" @@ -10945,7 +11384,7 @@ msgstr "# Convertendo Tipos de Erro" #: src/error-handling/converting-error-types.md:3 msgid "The effective expansion of `?` is a little more complicated than previously indicated:" -msgstr "A expansão efetiva de `?` é um pouco mais complicada do que indicado anteriormente:" +msgstr "A efetiva expansão do operador `?` é um pouco mais complicada do que indicado anteriormente:" #: src/error-handling/converting-error-types.md:5 msgid "" @@ -10954,7 +11393,7 @@ msgid "" "```" msgstr "" "```rust,ignore\n" -"expression?\n" +"expressao?\n" "```" #: src/error-handling/converting-error-types.md:9 @@ -10971,8 +11410,8 @@ msgid "" "```" msgstr "" "```rust,ignore\n" -"match expression {\n" -" Ok(value) => value,\n" +"match expressao {\n" +" Ok(valor) => valor,\n" " Err(err) => return Err(From::from(err)),\n" "}\n" "```" @@ -11008,17 +11447,16 @@ msgid "" "}" msgstr "" "#[derive(Debug)]\n" -"enum ReadUsernameError {\n" +"enum LerNomeUsuarioError {\n" " IoError(io::Error),\n" -" EmptyUsername(String),\n" +" NomeUsuarioVazio(String),\n" "}" #: src/error-handling/converting-error-types-example.md:15 msgid "impl Error for ReadUsernameError {}" -msgstr "impl Error for ReadUsernameError {}" +msgstr "impl Error for LerNomeUsuarioError {}" #: src/error-handling/converting-error-types-example.md:17 -#, fuzzy msgid "" "impl Display for ReadUsernameError {\n" " fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" @@ -11029,11 +11467,11 @@ msgid "" " }\n" "}" msgstr "" -"exibição impl para ReadUsernameError {\n" +"impl Display for LerNomeUsuarioError {\n" " fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" " match self {\n" -" Self::IoError(e) => write!(f, \"IO error: {}\", e),\n" -" Self::EmptyUsername(filename) => write!(f, \"Não foi encontrado name de usuário em {}\", filename),\n" +" Self::IoError(e) => write!(f, \"Erro de E/S: {}\", e),\n" +" Self::NomeUsuarioVazio(arquivo) => write!(f, \"Não foi encontrado nome de usuário em {}\", arquivo),\n" " }\n" " }\n" "}" @@ -11046,9 +11484,9 @@ msgid "" " }\n" "}" msgstr "" -"impl From for ReadUsernameError {\n" -" fn from(err: io::Error) -> ReadUsernameError {\n" -" ReadUsernameError::IoError(err)\n" +"impl From for LerNomeUsuarioError {\n" +" fn from(err: io::Error) -> LerNomeUsuarioError {\n" +" LerNomeUsuarioError::IoError(err)\n" " }\n" "}" @@ -11063,9 +11501,16 @@ msgid "" " Ok(username)\n" "}" msgstr "" +"fn ler_nome_usuario(caminho: &str) -> Result {\n" +" let mut nome_usuario = String::with_capacity(100);\n" +" File::open(caminho)?.read_to_string(&mut nome_usuario)?;\n" +" if nome_usuario.is_empty() {\n" +" return Err(LerNomeUsuarioError::NomeUsuarioVazio(String::from(caminho)));\n" +" }\n" +" Ok(nome_usuario)\n" +"}" #: src/error-handling/converting-error-types-example.md:41 -#, fuzzy msgid "" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" @@ -11076,8 +11521,8 @@ msgid "" msgstr "" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" -" let username = read_username(\"config.dat\");\n" -" println!(\"name de usuário ou erro: {name de usuário:?}\");\n" +" let nome_usuario = ler_nome_usuario(\"config.dat\");\n" +" println!(\"Nome de usuário ou erro: {nome_usuario:?}\");\n" "}\n" "```" @@ -11089,21 +11534,21 @@ msgid "" "`io::Error` doesn't implement them." msgstr "" "É uma boa prática para todos os tipos de erro implementar `std::error::Error`, que requer `Debug` e\n" -"`Mostrar`. Geralmente é útil para eles implementar `Clone` e `Eq` também quando possível, para fazer\n" -"vida mais fácil para testes e consumidores de sua biblioteca. Neste caso, não podemos fazê-lo facilmente, porque\n" +"`Display`. Geralmente é útil para eles implementar `Clone` e `Eq` também quando possível, para tornar\n" +"mais fácil a vida ao testar e consumidor sua biblioteca. Neste caso, não podemos fazê-lo facilmente, porque\n" "`io::Error` não os implementa." #: src/error-handling/deriving-error-enums.md:1 msgid "# Deriving Error Enums" -msgstr "# Derivando enumerações de erro" +msgstr "# Derivando _Enums_ de erro" #: src/error-handling/deriving-error-enums.md:3 msgid "" "The [thiserror](https://docs.rs/thiserror/) crate is a popular way to create an\n" "error enum like we did on the previous page:" msgstr "" -"A caixa [thiserror](https://docs.rs/thiserror/) é uma maneira popular de criar um\n" -"error enum como fizemos na página anterior:" +"O _crate_ [thiserror](https://docs.rs/thiserror/) é uma maneira popular de criar um\n" +"tipo enumerado (enum) de erro, como fizemos na página anterior:" #: src/error-handling/deriving-error-enums.md:6 msgid "" @@ -11118,7 +11563,6 @@ msgstr "" "use thiserror::Error;" #: src/error-handling/deriving-error-enums.md:11 -#, fuzzy msgid "" "#[derive(Debug, Error)]\n" "enum ReadUsernameError {\n" @@ -11129,11 +11573,11 @@ msgid "" "}" msgstr "" "#[derive(Debug, Error)]\n" -"enum ReadUsernameError {\n" +"enum LerNomeUsuarioError {\n" " #[error(\"Não foi possível ler: {0}\")]\n" " IoError(#[from] io::Error),\n" -" #[error(\"Não foi encontrado name de usuário em {0}\")]\n" -" name de usuário vazio(String),\n" +" #[error(\"Não foi encontrado o nome do usuário em {0}\")]\n" +" NomeUsuarioVazio(String),\n" "}" #: src/error-handling/deriving-error-enums.md:19 @@ -11147,13 +11591,13 @@ msgid "" " Ok(username)\n" "}" msgstr "" -"fn read_username(path: &str) -> Result {\n" -" let mut username = String::with_capacity(100);\n" -" fs::File::open(path)?.read_to_string(&mut username)?;\n" -" if username.is_empty() {\n" -" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +"fn ler_nome_usuario(caminho: &str) -> Result {\n" +" let mut nome_usuario = String::with_capacity(100);\n" +" fs::File::open(caminho)?.read_to_string(&mut nome_usuario)?;\n" +" if nome_usuario.is_empty() {\n" +" return Err(LerNomeUsuarioError::NomeUsuarioVazio(String::from(caminho)));\n" " }\n" -" Ok(username)\n" +" Ok(nome_usuario)\n" "}" #: src/error-handling/deriving-error-enums.md:28 src/error-handling/dynamic-errors.md:25 @@ -11169,8 +11613,8 @@ msgid "" msgstr "" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" -" match read_username(\"config.dat\") {\n" -" Ok(name de usuário) => println!(\"name de usuário: {name de usuário}\"),\n" +" match ler_nome_usuario(\"config.dat\") {\n" +" Ok(nome_usuario) => println!(\"Nome de usuário: {nome_usuario}\"),\n" " Err(err) => println!(\"Erro: {err}\"),\n" " }\n" "}\n" @@ -11182,9 +11626,9 @@ msgid "" "(if the `#[error(...)]` attributes are provided) and `From` (if the `#[from]` attribute is added).\n" "It also works for structs." msgstr "" -"A macro derivação do `thiserror` implementa automaticamente `std::error::Error`, e opcionalmente `Display`\n" +"A macro `thiserror` implementa automaticamente `std::error::Error`, e opcionalmente, `Display`\n" "(se os atributos `#[error(...)]` forem fornecidos) e `From` (se o atributo `#[from]` for adicionado).\n" -"Também funciona para structs." +"Também funciona para estruturas." #: src/error-handling/deriving-error-enums.md:43 msgid "It doesn't affect your public API, which makes it good for libraries." @@ -11199,8 +11643,8 @@ msgid "" "Sometimes we want to allow any type of error to be returned without writing our own enum covering\n" "all the different possibilities. `std::error::Error` makes this easy." msgstr "" -"Às vezes, queremos permitir que qualquer tipo de erro seja retornado sem escrever nossa própria cobertura de Enum\n" -"todas as diferentes possibilages. `std::error::Error` torna isso fácil." +"Às vezes, queremos permitir que qualquer tipo de erro seja retornado sem escrever nosso próprio `Enum`\n" +"abrangendo todas as diferentes possibilidades. `std::error::Error` torna isso fácil." #: src/error-handling/dynamic-errors.md:6 msgid "" @@ -11223,11 +11667,10 @@ msgid "" "struct EmptyUsernameError(String);" msgstr "" "#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" -"#[error(\"Found no username in {0}\")]\n" -"struct EmptyUsernameError(String);" +"#[error(\"Nome de usuário não encontrado em {0}\")]\n" +"struct NomeUsuarioVazioError(String);" #: src/error-handling/dynamic-errors.md:16 -#, fuzzy msgid "" "fn read_username(path: &str) -> Result> {\n" " let mut username = String::with_capacity(100);\n" @@ -11238,13 +11681,13 @@ msgid "" " Ok(username)\n" "}" msgstr "" -"fn read_username(path: &str) -> Result> {\n" -" let mut username = String::with_capacity(100);\n" -" File::open(path)?.read_to_string(&mut name de usuário)?;\n" -" if name de usuário.is_empty() {\n" -" return Err(EmptyUsernameError(String::from(path)).into());\n" +"fn ler_nome_usuario(caminho: &str) -> Result> {\n" +" let mut nome_usuario = String::with_capacity(100);\n" +" File::open(caminho)?.read_to_string(&mut nome_usuario)?;\n" +" if nome_usuario.is_empty() {\n" +" return Err(NomeUsuarioVazioError(String::from(caminho)).into());\n" " }\n" -" Ok (name de usuário)\n" +" Ok (nome_usuario)\n" "}" #: src/error-handling/dynamic-errors.md:36 @@ -11254,10 +11697,10 @@ msgid "" "library, but it can be a good option in a program where you just want to display the error message\n" "somewhere." msgstr "" -"Isso economiza código, mas abre mão da capacage de lidar com diferentes casos de erro de maneira diferente em\n" -"o programa. Como tal, geralmente não é uma boa ideia usar `Box` na API pública de um\n" -"biblioteca, mas pode ser uma boa Option em um programa onde você deseja apenas exibir a mensagem de erro\n" -"algum lugar." +"Isso economiza código, mas abre mão da capacidade de lidar com diferentes casos de erro de maneira diferenciada no\n" +"programa. Como tal, geralmente não é uma boa ideia usar `Box` na API pública de uma\n" +"biblioteca, mas pode ser uma boa opção em um programa onde você deseja apenas exibir a mensagem de erro\n" +"em algum lugar." #: src/error-handling/error-contexts.md:1 msgid "# Adding Context to Errors" @@ -11269,9 +11712,9 @@ msgid "" "contextual information to your errors and allows you to have fewer\n" "custom error types:" msgstr "" -"A caixa de [anyhow](https://docs.rs/anyhow/) amplamente usada pode ajudá-lo a adicionar\n" -"informações contextuais aos seus erros e permite que você tenha menos\n" -"tipos de erro personalizados:" +"O `crate` [anyhow](https://docs.rs/anyhow/) é amplamente usado pode ajudá-lo a adicionar\n" +"informações contextuais aos seus erros permitindo que você tenha menos\n" +"tipos de erros personalizados:" #: src/error-handling/error-contexts.md:7 msgid "" @@ -11281,7 +11724,7 @@ msgid "" "use anyhow::{Context, Result, bail};" msgstr "" "```rust,editable,compile_fail\n" -"use std::{fs, io};\n" +"use std::{fs};\n" "use std::io::Read;\n" "use anyhow::{Context, Result, bail};" @@ -11299,20 +11742,19 @@ msgid "" " Ok(username)\n" "}" msgstr "" -"fn read_username(path: &str) -> Result {\n" -" let mut username = String::with_capacity(100);\n" -" fs::File::open(path)\n" -" .context(format!(\"Falha ao abrir {path}\"))?\n" -" .read_to_string(&mut username)\n" -" .context(\"Falha ao ler\"?);\n" -" if username.is_empty() {\n" -" bail!(\"Não foi encontrado nenhum name de usuário em {path}\");\n" +"fn ler_nome_usuario(caminho: &str) -> Result {\n" +" let mut nome_usuario = String::with_capacity(100);\n" +" fs::File::open(caminho)\n" +" .context(format!(\"Falha ao abrir {caminho}\"))?\n" +" .read_to_string(&mut nome_usuario)\n" +" .context(\"Falha ao ler\")?;\n" +" if nome_usuario.is_empty() {\n" +" bail!(\"Não foi encontrado nenhum nome de usuário em {caminho}\");\n" " }\n" -" Ok (username)\n" +" Ok (nome_usuario)\n" "}" #: src/error-handling/error-contexts.md:24 -#, fuzzy msgid "" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" @@ -11325,8 +11767,8 @@ msgid "" msgstr "" "fn main() {\n" " //fs::write(\"config.dat\", \"\").unwrap();\n" -" match read_username(\"config.dat\") {\n" -" Ok(name de usuário) => println!(\"name de usuário: {name de usuário}\"),\n" +" match ler_nome_usuario(\"config.dat\") {\n" +" Ok(nome_usuario) => println!(\"Nome de usuário: {nome_usuario}\"),\n" " Err(err) => println!(\"Erro: {err:?}\"),\n" " }\n" "}\n" @@ -11343,10 +11785,10 @@ msgid "" msgstr "" "* `anyhow::Result` é um apelido de tipo para `Result`.\n" "* `anyhow::Error` é essencialmente um wrapper em torno de `Box`. Como tal, geralmente não é\n" -" uma boa escolha para a API pública de uma biblioteca, mas é amplamente utilizada em aplicações.\n" +" uma boa escolha para a API pública de uma biblioteca, mas é amplamente utilizado em aplicações.\n" "* O tipo de erro real dentro dele pode ser extraído para exame, se necessário.\n" -"* A funcionalage fornecida por `anyhow::Result` pode ser familiar para desenvolvedores Go, pois fornece\n" -" padrões de uso e ergonomia semelhantes a `(T, error)` do Go." +"* A funcionalidade fornecida por `anyhow::Result` pode ser familiar para desenvolvedores Go, pois fornece\n" +" padrões de uso e ergonomia semelhantes a `(T, error)` de Go." #: src/testing.md:1 msgid "# Testing" @@ -11354,11 +11796,11 @@ msgstr "# Teste" #: src/testing.md:3 msgid "Rust and Cargo come with a simple unit test framework:" -msgstr "Rust e Cargo vêm com uma estrutura de teste de unage simples:" +msgstr "Rust e Cargo vêm com uma estrutura de testes unitários simples:" #: src/testing.md:5 msgid "* Unit tests are supported throughout your code." -msgstr "* Os testes de unage são suportados em todo o seu código." +msgstr "* Os testes unitários são suportados em todo o seu código." #: src/testing.md:7 msgid "* Integration tests are supported via the `tests/` directory." @@ -11366,11 +11808,11 @@ msgstr "* Testes de integração são suportados através do diretório `tests/` #: src/testing/unit-tests.md:1 msgid "# Unit Tests" -msgstr "# Testes de unage" +msgstr "# Testes unitários" #: src/testing/unit-tests.md:3 msgid "Mark unit tests with `#[test]`:" -msgstr "Marque os testes de unage com `#[test]`:" +msgstr "Marque os testes unitários com `#[test]`:" #: src/testing/unit-tests.md:5 msgid "" @@ -11383,7 +11825,7 @@ msgid "" "}" msgstr "" "```rust,editable\n" -"fn first_word(text: &str) -> &str {\n" +"fn primeira_palavra(text: &str) -> &str {\n" " match text.find(' ') {\n" " Some(idx) => &text[..idx],\n" " None => &text,\n" @@ -11399,7 +11841,7 @@ msgid "" msgstr "" "#[test]\n" "fn teste_vazio() {\n" -" assert_eq!(first_word(\"\"), \"\");\n" +" assert_eq!(primeira_palavra(\"\"), \"\");\n" "}" #: src/testing/unit-tests.md:18 @@ -11410,8 +11852,8 @@ msgid "" "}" msgstr "" "#[test]\n" -"fn test_single_word() {\n" -" assert_eq!(first_word(\"Olá\"), \"Olá\");\n" +"fn test_uma_palavra() {\n" +" assert_eq!(primeira_palavra(\"Olá\"), \"Olá\");\n" "}" #: src/testing/unit-tests.md:23 @@ -11423,14 +11865,14 @@ msgid "" "```" msgstr "" "#[test]\n" -"fn test_multiple_words() {\n" -" assert_eq!(first_word(\"Olá Mundo\"), \"Olá\");\n" +"fn test_multiplas_palavras() {\n" +" assert_eq!(primeira_palavra(\"Olá Mundo\"), \"Olá\");\n" "}\n" "```" #: src/testing/unit-tests.md:29 msgid "Use `cargo test` to find and run the unit tests." -msgstr "Use `cargo test` para encontrar e executar os testes de unage." +msgstr "Use `cargo test` para encontrar e executar os testes unitários." #: src/testing/test-modules.md:1 msgid "# Test Modules" @@ -11441,7 +11883,7 @@ msgid "" "Unit tests are often put in a nested module (run tests on the\n" "[Playground](https://play.rust-lang.org/)):" msgstr "" -"Os testes de unage geralmente são colocados em um módulo aninhado (executar testes no\n" +"Os testes unitários geralmente são colocados em um módulo aninhado (executar testes no\n" "[Playground](https://play.rust-lang.org/)):" #: src/testing/test-modules.md:6 @@ -11487,7 +11929,7 @@ msgid "" "* This lets you unit test private helpers.\n" "* The `#[cfg(test)]` attribute is only active when you run `cargo test`." msgstr "" -"* Isso permite que você teste unages auxiliares privadas.\n" +"* Isso permite que você tenha testes unitários auxiliares e privados.\n" "* O atributo `#[cfg(test)]` só fica ativo quando você executa `cargo test`." #: src/testing/doc-tests.md:1 @@ -11534,7 +11976,7 @@ msgid "" "version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." msgstr "" "* Blocos de código em comentários `///` são vistos automaticamente como código Rust.\n" -"* O código será compilado e executado como parte do `teste de cargo`.\n" +"* O código será compilado e executado como parte do `cargo test`.\n" "* Teste o código acima no [Rust Playground](https://play.rust-lang.org/?" "version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." @@ -11574,11 +12016,11 @@ msgstr "" #: src/testing/integration-tests.md:16 msgid "These tests only have access to the public API of your crate." -msgstr "Esses testes só têm acesso à API pública da sua caixa." +msgstr "Esses testes só têm acesso à API pública do seu `crate`." #: src/unsafe.md:1 msgid "# Unsafe Rust" -msgstr "# rust insegura" +msgstr "# Rust inseguro (unsafe)" #: src/unsafe.md:3 msgid "The Rust language has two parts:" @@ -11598,7 +12040,7 @@ msgid "" "what Unsafe Rust is." msgstr "" "Veremos principalmente Rust seguro neste curso, mas é importante saber\n" -"o que é rust insegura." +"o que é Rust inseguro (_unsafe_)." #: src/unsafe.md:11 msgid "" @@ -11606,11 +12048,11 @@ msgid "" "documented. It is usually wrapped in a safe abstraction layer." msgstr "" "Código inseguro é geralmente pequeno e isolado, e sua correção deve ser cuidadosamente\n" -"documentado. Geralmente é envolto em uma camada de abstração segura." +"documentada. Geralmente é envolto em uma camada de abstração segura." #: src/unsafe.md:14 msgid "Unsafe Rust gives you access to five new capabilities:" -msgstr "O Unsafe Rust oferece acesso a cinco novos recursos:" +msgstr "O código inseguro do Rust oferece acesso a cinco novos recursos:" #: src/unsafe.md:16 msgid "" @@ -11620,11 +12062,11 @@ msgid "" "* Call `unsafe` functions, including `extern` functions.\n" "* Implement `unsafe` traits." msgstr "" -"* Dereference ponteiros brutos.\n" -"* Acesse ou modifique variáveis estáticas mutáveis.\n" -"* Acesse os campos `união`.\n" -"* Chamar funções `inseguras`, incluindo funções `externas`.\n" -"* Implementar traits `inseguros`." +"* Desreferenciar ponteiros brutos.\n" +"* Acessar ou modificar variáveis estáticas mutáveis.\n" +"* Acessar os campos de uma `union`.\n" +"* Chamar funções inseguras (`unsafe`), incluindo funções `externas`.\n" +"* Implementar traits inseguros (`unsafe`)." #: src/unsafe.md:22 msgid "" @@ -11632,7 +12074,7 @@ msgid "" "[Chapter 19.1 in the Rust Book](https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html)\n" "and the [Rustonomicon](https://doc.rust-lang.org/nomicon/)." msgstr "" -"A seguir, abordaremos brevemente os recursos inseguros. Para detalhes completos, consulte\n" +"A seguir, abordaremos brevemente os recursos inseguros. Para detalhes completos, consulte o\n" "[Capítulo 19.1 no Rust Book](https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html)\n" "e o [Rustonomicon](https://doc.rust-lang.org/nomicon/)." @@ -11642,9 +12084,9 @@ msgid "" "turned off the compiler safety features and have to write correct code by\n" "themselves. It means the compiler no longer enforces Rust's memory-safety rules." msgstr "" -"Rust inseguro não significa que o código está incorreto. Isso significa que os desenvolvedores têm\n" -"desligou os recursos de segurança do compilador e tem que escrever o código correto\n" -"eles mesmos. Isso significa que o compilador não impõe mais as regras de segurança de memória do Rust." +"Rust inseguro não significa que o código está incorreto. Significa que os desenvolvedores\n" +"desligaram os recursos de segurança do compilador e tem que escrever o código corretamente\n" +"eles mesmos. Significa também que o compilador não impõe mais as regras de segurança de memória do Rust." #: src/unsafe/raw-pointers.md:1 msgid "# Dereferencing Raw Pointers" @@ -11687,8 +12129,8 @@ msgid "" "```" msgstr "" " // Seguro porque r1 e r2 foram obtidos de referências e, portanto, são garantidos como não nulos e\n" -" // devidamente alinhados, os objetos subjacentes às referências das quais foram obtidos são\n" -" // vivem em todo o bloco inseguro e não são acessados nem por meio do\n" +" // devidamente alinhados, os objetos subjacentes às referências das quais foram obtidos\n" +" // vivem em todo o bloco inseguro e não são acessados nem por meio de\n" " // referências ou simultaneamente por meio de quaisquer outros ponteiros.\n" " unsafe {\n" " println!(\"r1 é: {}\", *r1);\n" @@ -11705,16 +12147,16 @@ msgid "" "operations it is doing." msgstr "" "É uma boa prática (e exigida pelo guia de estilo do Android Rust) escrever um comentário para cada\n" -"Bloco `inseguro` explicando como o código dentro dele satisfaz os requisitos de segurança do inseguro\n" -"operações que está fazendo." +"bloco `unsafe` explicando como o código dentro dele satisfaz os requisitos de segurança para a\n" +"operação insegura que está fazendo." #: src/unsafe/raw-pointers.md:30 msgid "" "In the case of pointer dereferences, this means that the pointers must be\n" "[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), i.e.:" msgstr "" -"No caso de desreferência de ponteiro, isso significa que os ponteiros devem ser\n" -"[_valid_](https://doc.rust-lang.org/std/ptr/index.html#safety), ou seja:" +"No caso de desreferência de ponteiros, isso significa que os ponteiros devem ser\n" +"[_válidos_](https://doc.rust-lang.org/std/ptr/index.html#safety), ou seja:" #: src/unsafe/raw-pointers.md:33 msgid "" @@ -11729,7 +12171,7 @@ msgstr "" " * O ponteiro deve ser _desreferenciável_ (dentro dos limites de um único objeto alocado).\n" " * O objeto não deve ter sido desalocado.\n" " * Não deve haver acessos simultâneos ao mesmo local.\n" -" * Se o ponteiro foi obtido lançando uma referência, o objeto subjacente deve estar ativo e não\n" +" * Se o ponteiro foi obtido lançando uma referência, o objeto subjacente deve estar ativo e nenhuma\n" " referência pode ser usada para acessar a memória." #: src/unsafe/raw-pointers.md:40 @@ -11765,8 +12207,8 @@ msgid "" "However, since data races can occur, it is unsafe to read and write mutable\n" "static variables:" msgstr "" -"No entanto, como podem ocorrer corridas de dados, não é seguro ler e gravar dados mutáveis\n" -"variáveis estáticas:" +"No entanto, como podem ocorrer corridas de dados, não é seguro ler e gravar dados em\n" +"variáveis estáticas mutáveis:" #: src/unsafe/mutable-static-variables.md:16 msgid "" @@ -11809,16 +12251,16 @@ msgid "" "Using a mutable static is generally a bad idea, but there are some cases where it might make sense\n" "in low-level `no_std` code, such as implementing a heap allocator or working with some C APIs." msgstr "" -"Usar uma estática mutável geralmente é uma má ideia, mas há alguns casos em que pode fazer sentido\n" +"Usar uma variável estática mutável geralmente é uma má ideia, mas há alguns casos em que pode fazer sentido,\n" "em código `no_std` de baixo nível, como implementar um alocador de heap ou trabalhar com algumas APIs C." #: src/unsafe/unions.md:1 msgid "# Unions" -msgstr "# Sindicatos" +msgstr "# Unions (Uniões)" #: src/unsafe/unions.md:3 msgid "Unions are like enums, but you need to track the active field yourself:" -msgstr "As uniões são como enums, mas você mesmo precisa rastrear o campo ativo:" +msgstr "As uniões `union` são como enums, mas você mesmo precisa rastrear o campo ativo:" #: src/unsafe/unions.md:5 msgid "" @@ -11831,7 +12273,7 @@ msgid "" msgstr "" "```rust,editable\n" "#[repr(C)]\n" -"union MyUnion {\n" +"union MinhaUnion {\n" " i: u8,\n" " b: bool,\n" "}" @@ -11846,9 +12288,9 @@ msgid "" "```" msgstr "" "fn main() {\n" -" let u = MyUnion { i: 42 };\n" +" let u = MinhaUnion { i: 42 };\n" " println!(\"int: {}\", unsafe { u.i });\n" -" println!(\"bool: {}\", unsafe { u.b }); // Undefined behavior!\n" +" println!(\"bool: {}\", unsafe { u.b }); // Comportamento indefinido!\n" "}\n" "```" @@ -11857,7 +12299,7 @@ msgid "" "Unions are very rarely needed in Rust as you can usually use an enum. They are occasionally needed\n" "for interacting with C library APIs." msgstr "" -"As uniões raramente são necessárias no Rust, pois geralmente você pode usar um enum. Eles são ocasionalmente necessários\n" +"As uniões raramente são necessárias no Rust, pois geralmente você pode usar um `enum`. Elas são ocasionalmente necessários\n" "para interagir com as APIs da biblioteca C." #: src/unsafe/unions.md:24 @@ -11866,9 +12308,9 @@ msgid "" "[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn.transmute.html) or a safe\n" "wrapper such as the [`zerocopy`](https://crates.io/crates/zerocopy) crate." msgstr "" -"Se você deseja apenas reinterpretar os bytes como um tipo diferente, provavelmente deseja\n" -"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn.transmute.html) ou um cofre\n" -"wrapper como a caixa [`zerocopy`](https://crates.io/crates/zerocopy)." +"Se você deseja apenas reinterpretar os bytes como um tipo diferente, provavelmente usaria\n" +"[`std::mem::transmute`](https://doc.rust-lang.org/stable/std/mem/fn.transmute.html) ou um\n" +"wrapper seguro como o `crate` [`zerocopy`](https://crates.io/crates/zerocopy)." #: src/unsafe/calling-unsafe-functions.md:1 msgid "# Calling Unsafe Functions" @@ -11879,7 +12321,7 @@ msgid "" "A function or method can be marked `unsafe` if it has extra preconditions you\n" "must uphold to avoid undefined behaviour:" msgstr "" -"Uma função ou método pode ser marcado como 'inseguro' se tiver pré-condições extras que você\n" +"Uma função ou método pode ser marcado como 'unsafe' se tiver pré-condições extras que você\n" "deve respeitar para evitar comportamentos indefinidos:" #: src/unsafe/calling-unsafe-functions.md:6 @@ -11904,8 +12346,8 @@ msgid "" "}\n" "```" msgstr "" -" // Seguro porque os índices estão na ordem correta, dentro dos limites de\n" -" // a slice da string e fica nos limites da sequência UTF-8.\n" +" // Seguro porque os índices estão na ordem correta, dentro dos limites da\n" +" // slice da string e fica nos limites da sequência UTF-8.\n" " unsafe {\n" " println!(\"{}\", emojis.get_unchecked(0..4));\n" " println!(\"{}\", emojis.get_unchecked(4..7));\n" @@ -11916,15 +12358,15 @@ msgstr "" #: src/unsafe/writing-unsafe-functions.md:1 msgid "# Writing Unsafe Functions" -msgstr "# Escrevendo Funções Inseguras" +msgstr "# Escrevendo funções inseguras" #: src/unsafe/writing-unsafe-functions.md:3 msgid "" "You can mark your own functions as `unsafe` if they require particular conditions to avoid undefined\n" "behaviour." msgstr "" -"Você pode marcar suas próprias funções como `inseguras` se elas exigirem condições específicas para evitar\n" -"comportamento." +"Você pode marcar suas próprias funções como _inseguras_ se elas exigirem condições específicas para evitar\n" +"comportamentos indefinidos." #: src/unsafe/writing-unsafe-functions.md:6 msgid "" @@ -11941,12 +12383,12 @@ msgid "" "}" msgstr "" "```rust,editable\n" -"/// Swaps the values pointed to by the given pointers.\n" +"/// Trocando os valores dos parâmetros pode referência usando ponteiros\n" "///\n" "/// # Safety\n" "///\n" -"/// The pointers must be valid and properly aligned.\n" -"unsafe fn swap(a: *mut u8, b: *mut u8) {\n" +"/// Os ponteiros precisam ser válidos e corretamente alinhados.\n" +"unsafe fn troca(a: *mut u8, b: *mut u8) {\n" " let temp = *a;\n" " *a = *b;\n" " *b = temp;\n" @@ -11969,9 +12411,9 @@ msgid "" " swap(&mut a, &mut b);\n" " }" msgstr "" -" // Safe because ...\n" +" // Seguro porque...\n" " unsafe {\n" -" swap(&mut a, &mut b);\n" +" troca(&mut a, &mut b);\n" " }" #: src/unsafe/writing-unsafe-functions.md:27 @@ -11986,27 +12428,27 @@ msgstr "" #: src/unsafe/writing-unsafe-functions.md:33 msgid "We wouldn't actually use pointers for this because it can be done safely with references." -msgstr "Na verdade, não usaríamos ponteiros para isso porque isso pode ser feito com segurança com referências." +msgstr "Na verdade, não usaríamos ponteiros para isso porque isso pode ser feito com segurança usando referências." #: src/unsafe/writing-unsafe-functions.md:35 msgid "" "Note that unsafe code is allowed within an unsafe function without an `unsafe` block. We can\n" "prohibit this with `#[deny(unsafe_op_in_unsafe_fn)]`. Try adding it and see what happens." msgstr "" -"Observe que o código inseguro é permitido dentro de uma função insegura sem um bloco `unsafe`. Pudermos\n" +"Observe que o código _inseguro_ é permitido dentro de uma função _insegura_ sem o uso de um bloco `unsafe`. Podemos\n" "proibir isso com `#[deny(unsafe_op_in_unsafe_fn)]`. Tente adicioná-lo e veja o que acontece." #: src/unsafe/extern-functions.md:1 msgid "# Calling External Code" -msgstr "# Chamando Código Externo" +msgstr "# Chamando código externo" #: src/unsafe/extern-functions.md:3 msgid "" "Functions from other languages might violate the guarantees of Rust. Calling\n" "them is thus unsafe:" msgstr "" -"Funções de outras linguagens podem violar as garantias do Rust. Chamando\n" -"eles é, portanto, inseguro:" +"Funções de outras linguagens podem violar as garantias do Rust. Chamar\n" +"elas é, portanto, inseguro:" #: src/unsafe/extern-functions.md:6 msgid "" @@ -12041,7 +12483,7 @@ msgid "" "arbitrary circumstances." msgstr "" "Isso geralmente é apenas um problema para funções externas que fazem coisas com ponteiros que podem\n" -"violam o modelo de memória do Rust, mas em geral qualquer função C pode ter comportamento indefinido sob qualquer\n" +"violar o modelo de memória do Rust, mas em geral qualquer função C pode ter comportamento indefinido sob quaisquer\n" "circunstâncias arbitrárias." #: src/unsafe/extern-functions.md:25 @@ -12054,14 +12496,14 @@ msgstr "" #: src/unsafe/unsafe-traits.md:1 msgid "# Implementing Unsafe Traits" -msgstr "# Implementando traits Inseguros" +msgstr "# Implementando traits inseguros" #: src/unsafe/unsafe-traits.md:3 msgid "" "Like with functions, you can mark a trait as `unsafe` if the implementation must guarantee\n" "particular conditions to avoid undefined behaviour." msgstr "" -"Assim como nas funções, você pode marcar uma característica como `insegura` se a implementação deve garantir\n" +"Assim como nas funções, você pode marcar um `trait` como `unsafe` se a implementação deve garantir\n" "condições particulares para evitar comportamento indefinido." #: src/unsafe/unsafe-traits.md:6 @@ -12069,7 +12511,7 @@ msgid "" "For example, the `zerocopy` crate has an unsafe trait that looks\n" "[something like this](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" msgstr "" -"Por exemplo, a caixa `zerocopy` tem uma característica insegura que parece\n" +"Por exemplo, o `crate` `zerocopy` tem uma característica insegura que parece\n" "[algo assim](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" #: src/unsafe/unsafe-traits.md:9 @@ -12083,7 +12525,6 @@ msgstr "" "use std::slice;" #: src/unsafe/unsafe-traits.md:13 -#, fuzzy msgid "" "/// ...\n" "/// # Safety\n" @@ -12097,9 +12538,9 @@ msgid "" "}" msgstr "" "/// ...\n" -"/// # Segurança\n" +"/// # Safety\n" "/// O tipo deve ter uma representação definida e nenhum preenchimento.\n" -"Pub trait unsafe AsBytes {\n" +"pub unsafe trait AsBytes {\n" " fn as_bytes(&self) -> &[u8] {\n" " unsafe {\n" " slice::from_raw_parts(self as *const Self as *const u8, size_of_val(self))\n" @@ -12108,14 +12549,13 @@ msgstr "" "}" #: src/unsafe/unsafe-traits.md:24 -#, fuzzy msgid "" "// Safe because u32 has a defined representation and no padding.\n" "unsafe impl AsBytes for u32 {}\n" "```" msgstr "" "// Seguro porque u32 tem uma representação definida e nenhum preenchimento.\n" -"impl unsafe AsBytes para u32 {}\n" +"unsafe impl AsBytes for u32 {}\n" "```" #: src/unsafe/unsafe-traits.md:30 @@ -12123,16 +12563,16 @@ msgid "" "There should be a `# Safety` section on the Rustdoc for the trait explaining the requirements for\n" "the trait to be safely implemented." msgstr "" -"Deve haver uma seção `# Safety` no Rustdoc para a característica explicando os requisitos para\n" -"a característica a ser implementada com segurança." +"Deve haver uma seção `# Safety` no Rustdoc para o `trait` explicando os requisitos para\n" +"o `trait` ser implementado com segurança." #: src/unsafe/unsafe-traits.md:33 msgid "The actual safety section for `AsBytes` is rather longer and more complicated." -msgstr "A seção de segurança real para `AsBytes` é bem mais longa e complicada." +msgstr "A seção de segurança atual para `AsBytes` é bem mais longa e complicada." #: src/unsafe/unsafe-traits.md:35 msgid "The built-in `Send` and `Sync` traits are unsafe." -msgstr "As características incorporadas `Send` e `Sync` não são seguras." +msgstr "Os _traits_ incorporadas `Send` e `Sync` não são seguros." #: src/exercises/day-3/afternoon.md:1 msgid "# Day 3: Afternoon Exercises" @@ -12144,15 +12584,15 @@ msgstr "Vamos construir um wrapper seguro para ler o conteúdo do diretório!" #: src/exercises/day-3/afternoon.md:7 msgid "After looking at the exercise, you can look at the [solution] provided." -msgstr "Depois de ver o exercício, você pode ver a [Solution] fornecida." +msgstr "Depois de ver o exercício, você pode ver a [solução] fornecida." #: src/exercises/day-3/afternoon.md:9 msgid "[solution]: solutions-afternoon.md" -msgstr "" +msgstr "[solução]: solutions-afternoon.md" #: src/exercises/day-3/safe-ffi-wrapper.md:1 msgid "# Safe FFI Wrapper" -msgstr "# Invólucro FFI seguro" +msgstr "# _Wrapper_ FFI seguro" #: src/exercises/day-3/safe-ffi-wrapper.md:3 msgid "" @@ -12160,13 +12600,13 @@ msgid "" "interface_ (FFI). We will use this to build a safe wrapper for the `libc`\n" "functions you would use from C to read the filenames of a directory." msgstr "" -"Rust tem ótimo suporte para chamar funções por meio de uma função _foreign\n" -"interface_ (FFI). Usaremos isso para construir um wrapper seguro para a `libc`\n" -"funções que você usaria de C para ler os names de arquivo de um diretório." +"Rust tem ótimo suporte para chamar funções por meio de uma interface para funções externas (_function foreign\n" +"interface_ FFI). Usaremos isso para construir um invólucro seguro para as funções da `libc`\n" +"de C que você usaria para ler os nomes dos arquivos de um diretório." #: src/exercises/day-3/safe-ffi-wrapper.md:7 msgid "You will want to consult the manual pages:" -msgstr "Você vai querer consultar as páginas de manual:" +msgstr "Você vai querer consultar as páginas do manual:" #: src/exercises/day-3/safe-ffi-wrapper.md:9 msgid "" @@ -12185,7 +12625,7 @@ msgid "" "C. The [Nomicon] also has a very useful chapter about FFI." msgstr "" "Você também deve procurar o módulo [`std::ffi`], especialmente para [`CStr`]\n" -"e tipos [`CString`] que são usados para armazenar strings terminadas em NUL vindas de\n" +"e tipos [`CString`] que são usados para armazenar strings terminadas com NULL vindas do\n" "C. O [Nomicon] também tem um capítulo muito útil sobre FFI." #: src/exercises/day-3/safe-ffi-wrapper.md:17 @@ -12205,8 +12645,8 @@ msgid "" "Copy the code below to and fill in the missing\n" "functions and methods:" msgstr "" -"Copie o código abaixo para e preencha os campos que faltam\n" -"funções e métodos:" +"Copie o código abaixo para e implemente as\n" +"funções e métodos que faltam:" #: src/exercises/day-3/safe-ffi-wrapper.md:29 msgid "" @@ -12228,7 +12668,7 @@ msgstr "" " // Tipo opaco. Consulte https://doc.rust-lang.org/nomicon/ffi.html.\n" " #[repr(C)]\n" " pub struct DIR {\n" -" _dados: [u8; 0],\n" +" _data: [u8; 0],\n" " _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,\n" " }" @@ -12244,7 +12684,7 @@ msgid "" " pub d_name: [c_char; 256],\n" " }" msgstr "" -" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu.\n" +" // Layout para readdir(3) e definições em /usr/include/x86_64-linux-gnu.\n" " #[repr(C)]\n" " pub struct dirent {\n" " pub d_ino: c_long,\n" @@ -12293,7 +12733,6 @@ msgstr "" "}" #: src/exercises/day-3/safe-ffi-wrapper.md:65 -#, fuzzy msgid "" "impl DirectoryIterator {\n" " fn new(path: &str) -> Result {\n" @@ -12305,14 +12744,13 @@ msgid "" msgstr "" "impl DirectoryIterator {\n" " fn new(path: &str) -> Result {\n" -" // Chame opendir e retorne um valor Ok se funcionou,\n" +" // Chama opendir e retorna um valor Ok se funcionou,\n" " // caso contrário, retorna Err com uma mensagem.\n" -" não implementado!()\n" +" unimplemented!()\n" " }\n" "}" #: src/exercises/day-3/safe-ffi-wrapper.md:73 -#, fuzzy msgid "" "impl Iterator for DirectoryIterator {\n" " type Item = OsString;\n" @@ -12322,11 +12760,11 @@ msgid "" " }\n" "}" msgstr "" -"impl Iterator para DirectoryIterator {\n" -" tipo Item = OsString;\n" +"impl Iterator for DirectoryIterator {\n" +" type Item = OsString;\n" " fn next(&mut self) -> Option {\n" -" // Continue chamando readdir até obtermos um ponteiro NULL de volta.\n" -" não implementado!()\n" +" // Continue chamando readdir até obter um ponteiro NULL de volta.\n" +" unimplemented!()\n" " }\n" "}" @@ -12349,6 +12787,12 @@ msgid "" "}\n" "```" msgstr "" +"fn main() -> Result<(), String> {\n" +" let iter = DirectoryIterator::new(\".\")?;\n" +" println!(\"arquivos: {:#?}\", iter.collect::>());\n" +" Ok(())\n" +"}\n" +"```" #: src/welcome-day-4.md:1 msgid "# Welcome to Day 4" @@ -12360,7 +12804,7 @@ msgstr "Hoje veremos dois tópicos principais:" #: src/welcome-day-4.md:5 msgid "* Concurrency: threads, channels, shared state, `Send` and `Sync`." -msgstr "* Simultaneage: threads, canais, estado compartilhado, `Send` e `Sync`." +msgstr "* Concorrência: _threads_, _channels_, estado compartilhado, `Send` e `Sync`." #: src/welcome-day-4.md:7 msgid "" @@ -12368,7 +12812,7 @@ msgid "" " interoperability with C, C++, and Java." msgstr "" "* Android: construindo binários e bibliotecas, usando AIDL, log e\n" -" interoperabilage com C, C++ e Java." +" interoperabilidade com C, C++ e Java." #: src/welcome-day-4.md:10 msgid "" @@ -12378,21 +12822,21 @@ msgid "" "> parses some raw bytes would be ideal." msgstr "" "> Tentaremos chamar Rust de um de seus próprios projetos hoje. Então tente\n" -"> encontre um pequeno canto da sua base de código onde podemos mover algumas linhas de código para\n" -"> rust. Quanto menos dependências e tipos \"exóticos\", melhor. Algo que\n" -"> analisa alguns bytes brutos seria o ideal." +"> encontrar um pequeno canto da sua base de código onde podemos mover algumas linhas de código para\n" +"> Rust. Quanto menos dependências e tipos \"exóticos\", melhor. Algo que\n" +"> analise alguns bytes brutos seria o ideal." #: src/concurrency.md:1 msgid "# Fearless Concurrency" -msgstr "# Simultaneage sem medo" +msgstr "# Concorrência sem medo" #: src/concurrency.md:3 msgid "" "Rust has full support for concurrency using OS threads with mutexes and\n" "channels." msgstr "" -"Rust tem suporte total para simultaneage usando threads do SO com mutexes e\n" -"canais." +"Rust tem suporte total para concorrência usando _threads_ do SO com _mutexes_ e\n" +"_channels_ (canais)." #: src/concurrency.md:6 msgid "" @@ -12400,17 +12844,17 @@ msgid "" "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 "" -"O sistema de tipo Rust desempenha um papel importante na criação de muitos bugs de simultaneage\n" -"erros de tempo de compilação. Isso geralmente é chamado de _simultaneage sem medo_, pois você\n" +"O sistema de tipos do Rust desempenha um papel importante na conversão de muitos erros de concorrência\n" +"em erros de tempo de compilação. Isso geralmente é chamado de _concorrência sem medo_, pois você\n" "pode confiar no compilador para garantir a exatidão no tempo de execução." #: src/concurrency/threads.md:1 msgid "# Threads" -msgstr "# Tópicos" +msgstr "# Threads" #: src/concurrency/threads.md:3 msgid "Rust threads work similarly to threads in other languages:" -msgstr "Os encadeamentos Rust funcionam de maneira semelhante aos encadeamentos em outras linguagens:" +msgstr "_Threads_ em Rust funcionam de maneira semelhante às _threads_ em outras linguagens:" #: src/concurrency/threads.md:5 msgid "" @@ -12432,6 +12876,13 @@ msgid "" " }\n" " });" msgstr "" +"fn main() {\n" +" thread::spawn(|| {\n" +" for i in 1..10 {\n" +" println!(\"Contador na thread: {i}!\");\n" +" thread::sleep(Duration::from_millis(5));\n" +" }\n" +" });" #: src/concurrency/threads.md:17 msgid "" @@ -12442,6 +12893,12 @@ msgid "" "}\n" "```" msgstr "" +" for i in 1..5 {\n" +" println!(\"Thread principal: {i}\");\n" +" thread::sleep(Duration::from_millis(5));\n" +" }\n" +"}\n" +"```" #: src/concurrency/threads.md:24 msgid "" @@ -12449,17 +12906,17 @@ msgid "" "* Thread panics are independent of each other.\n" " * Panics can carry a payload, which can be unpacked with `downcast_ref`." msgstr "" -"* Threads são todos threads daemon, o thread principal não espera por eles.\n" -"* Thread panics são independentes uns dos outros.\n" -" * Os pânicos podem carregar uma cargo útil, que pode ser descompactada com `downcast_ref`." +"* _Threads_ são todas \"_daemon threads_\", o _thread_ principal não espera por elas.\n" +"* \"_Panics_\" em _threads_ são independentes uns dos outros.\n" +" * \"_Panics_\" podem carregar um _payload_ (carga útil), que pode ser descompactado com `downcast_ref`." #: src/concurrency/threads.md:32 msgid "" "* Notice that the thread is stopped before it reaches 10 — the main thread is\n" " not waiting." msgstr "" -"* Observe que o thread é interrompido antes de atingir 10 — o thread principal é\n" -" não esperando." +"* Observe que o _thread_ é interrompido antes de atingir 10 — o _thread_ principal não\n" +" o espera." #: src/concurrency/threads.md:35 msgid "" @@ -12467,19 +12924,19 @@ msgid "" " the thread to finish." msgstr "" "* Use `let handle = thread::spawn(...)` e posteriormente `handle.join()` para aguardar\n" -" o fio para terminar." +" a `thread` terminar." #: src/concurrency/threads.md:38 msgid "* Trigger a panic in the thread, notice how this doesn't affect `main`." -msgstr "* Acionar um pânico no tópico, observe como isso não afeta `main`." +msgstr "* Acione um pânico (`panic`) na _thread_ e observe como isso não afeta a _thread_ `main`." #: src/concurrency/threads.md:40 msgid "" "* 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 "" -"* Use o valor de retorno `Result` de `handle.join()` para obter acesso ao pânico\n" -" payload. Este é um bom momento para falar sobre [`Any`]." +"* Use o valor de retorno `Result` de `handle.join()` para obter acesso ao\n" +" _payload_ do `panic` gerado. Este é um bom momento para falar sobre [`Any`]." #: src/concurrency/threads.md:43 msgid "[`Any`]: https://doc.rust-lang.org/std/any/index.html" @@ -12487,11 +12944,11 @@ msgstr "[`Qualquer`]: https://doc.rust-lang.org/std/any/index.html" #: src/concurrency/scoped-threads.md:1 msgid "# Scoped Threads" -msgstr "# Tópicos com Escopo" +msgstr "# Threads com Escopo" #: src/concurrency/scoped-threads.md:3 msgid "Normal threads cannot borrow from their environment:" -msgstr "Threads normais não podem pedir emprestado de seu ambiente:" +msgstr "_Threads_ normais não podem emprestar de seu ambiente:" #: src/concurrency/scoped-threads.md:5 msgid "" @@ -12517,10 +12974,15 @@ msgid "" "}\n" "```" msgstr "" +" thread::spawn(|| {\n" +" println!(\"Comprimento: {}\", s.len());\n" +" });\n" +"}\n" +"```" #: src/concurrency/scoped-threads.md:17 msgid "However, you can use a [scoped thread][1] for this:" -msgstr "No entanto, você pode usar um [tópico com escopo] [1] para isso:" +msgstr "No entanto, você pode usar uma [_thread_ com escopo][1] para isso:" #: src/concurrency/scoped-threads.md:19 msgid "" @@ -12542,7 +13004,7 @@ msgid "" msgstr "" " thread::scope(|scope| {\n" " scope.spawn(|| {\n" -" println!(\"Length: {}\", s.len());\n" +" println!(\"Comprimento: {}\", s.len());\n" " });\n" " });\n" "}\n" @@ -12564,24 +13026,24 @@ msgid "" msgstr "" "
\n" " \n" -"* A razão para isso é que, quando a função `thread::scope` for concluída, todas as threads serão unidas, para que possam " +"* A razão para isso é que, quando a função `thread::scope` for concluída, todas as _threads_ serão unidas, para que possam " "retornar dados emprestados.\n" -"* Aplicam-se as regras normais de empréstimo do Rust: você pode emprestar mutável por um encadeamento ou imutavelmente por " -"qualquer número de encadeamentos.\n" +"* Aplicam-se as regras normais de empréstimo do Rust: o empréstimo pode ser mutável, para uma `thread` ou imutável para\n" +"qualquer número de _threads_.\n" " \n" "
" #: src/concurrency/channels.md:1 msgid "# Channels" -msgstr "# Canais" +msgstr "# Channels (Canais)" #: src/concurrency/channels.md:3 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 "" -"Os canais Rust têm duas partes: um `Sender` e um `Receiver`. as duas partes\n" -"estão conectados através do canal, mas você só vê os Points finais." +"Os _channels_ (canais) em Rust têm duas partes: um `Sender` e um `Receiver`. As duas partes\n" +"estão conectadas através do _channel_, mas você só vê os _end-points_." #: src/concurrency/channels.md:6 msgid "" @@ -12612,6 +13074,8 @@ msgid "" " println!(\"Received: {:?}\", rx.recv());\n" " println!(\"Received: {:?}\", rx.recv());" msgstr "" +" println!(\"Recebido: {:?}\", rx.recv());\n" +" println!(\"Recebido: {:?}\", rx.recv());" #: src/concurrency/channels.md:19 msgid "" @@ -12621,6 +13085,11 @@ msgid "" "}\n" "```" msgstr "" +" let tx2 = tx.clone();\n" +" tx2.send(30).unwrap();\n" +" println!(\"Recebido: {:?}\", rx.recv());\n" +"}\n" +"```" #: src/concurrency/channels.md:27 msgid "" @@ -12630,13 +13099,13 @@ msgid "" " `Receiver` is dropped and the channel is closed." msgstr "" "* `mpsc` significa Multi-Produtor, Único-Consumidor. `Sender` e `SyncSender` implementam `Clone` (então\n" -" você pode criar vários produtores), mas `Receiver` não.\n" -"* `send()` e `recv()` retornam `Result`. Se retornarem `Err`, significa a contraparte `Sender` ou\n" -" `Receiver` é descartado e o canal é fechado." +" você pode criar vários produtores), mas `Receiver` (consumidores) não.\n" +"* `send()` e `recv()` retornam `Result`. Se retornarem `Err`, significa que a contraparte `Sender` ou\n" +" `Receiver` é descartada e o canal é fechado." #: src/concurrency/channels/unbounded.md:1 msgid "# Unbounded Channels" -msgstr "# canais ilimitados" +msgstr "# Canais ilimitados" #: src/concurrency/channels/unbounded.md:3 msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" @@ -12666,6 +13135,15 @@ msgid "" " });\n" " thread::sleep(Duration::from_millis(100));" msgstr "" +" thread::spawn(move || {\n" +" let thread_id = thread::current().id();\n" +" for i in 1..10 {\n" +" tx.send(format!(\"Mensagem {i}\")).unwrap();\n" +" println!(\"{thread_id:?}: enviando a mensagem: {i}\");\n" +" }\n" +" println!(\"{thread_id:?}: feito\");\n" +" });\n" +" thread::sleep(Duration::from_millis(100));" #: src/concurrency/channels/unbounded.md:23 msgid "" @@ -12675,6 +13153,11 @@ msgid "" "}\n" "```" msgstr "" +" for msg in rx.iter() {\n" +" println!(\"Main: obteve {msg}\");\n" +" }\n" +"}\n" +"```" #: src/concurrency/channels/bounded.md:1 msgid "# Bounded Channels" @@ -12682,7 +13165,7 @@ msgstr "# Canais Delimitados" #: src/concurrency/channels/bounded.md:3 msgid "Bounded and synchronous channels make `send` block the current thread:" -msgstr "Canais limitados e síncronos fazem `send` bloquear o thread atual:" +msgstr "Canais limitados e síncronos fazem `send` bloquear o _thread_ atual:" #: src/concurrency/channels/bounded.md:10 msgid "" @@ -12693,7 +13176,6 @@ msgstr "" " let (tx, rx) = mpsc::sync_channel(3);" #: src/concurrency/channels/bounded.md:23 -#, fuzzy msgid "" " for msg in rx.iter() {\n" " println!(\"Main: got {msg}\");\n" @@ -12701,8 +13183,8 @@ msgid "" "}\n" "```" msgstr "" -" for msg em rx.iter() {\n" -" println!(\"Main: obteve {}\", msg);\n" +" for msg in rx.iter() {\n" +" println!(\"Main: obteve {msg}\");\n" " }\n" "}\n" "```" @@ -12725,7 +13207,7 @@ msgid "" " 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], referência atômica contada `T`: manipula o compartilhamento entre threads e\n" +"* [`Arc`][1], referência atômica contada `T`: manipula o compartilhamento entre _threads_ e\n" " toma o cuidado de desalocar `T` quando a última referência é descartada,\n" "* [`Mutex`][2]: garante acesso mutuamente exclusivo ao valor `T`." @@ -12806,11 +13288,10 @@ msgid "" "* Beware of reference cycles, `Arc` does not use a garbage collector to detect them.\n" " * `std::sync::Weak` can help." msgstr "" -"* `Arc` significa \"Atomic Reference Counted\", uma versão thread-safe de `Rc` que usa dados atômicos\n" -" operações.\n" -"* `Arc` implementa `Clone` quer `T` o faça ou não. Ele implementa `Send` e `Sync` iff `T`\n" +"* `Arc` significa \"Atomic Reference Counted\", uma versão _thread-safe_ de `Rc` que usa operações atômicas.\n" +"* `Arc` implementa `Clone` quer `T` o faça ou não. Ele implementa `Send` e `Sync` se `T`\n" " implementa os dois.\n" -"* `Arc::clone()` tem o custo de operações atômicas que são executadas, mas depois disso o uso do\n" +"* `Arc::clone()` tem o custo das operações atômicas que são executadas, mas depois disso o uso do\n" " `T` é gratuito.\n" "* Cuidado com os ciclos de referência, `Arc` não usa um coletor de lixo para detectá-los.\n" " * `std::sync::Weak` pode ajudar." @@ -12855,8 +13336,8 @@ msgid "" msgstr "" " {\n" " let v: &Mutex> = &v;\n" -" let mut guard = v.lock().unwrap();\n" -" guard.push(40);\n" +" let mut guarda= v.lock().unwrap();\n" +" guarda.push(40);\n" " }" #: src/concurrency/shared_state/mutex.md:19 @@ -12874,8 +13355,8 @@ msgid "" "Notice how we have a [`impl Sync for Mutex`][2] blanket\n" "implementation." msgstr "" -"Observe como temos um cobertor [`impl Sync for Mutex`][2]\n" -"implementação." +"Observe como temos uma implementação [`impl Sync for Mutex`][2]\n" +"encoberta." #: src/concurrency/shared_state/mutex.md:26 msgid "" @@ -12907,14 +13388,14 @@ msgstr "" " \n" "* `Mutex` em Rust parece uma coleção com apenas um elemento - os dados protegidos.\n" " * Não é possível esquecer de adquirir o mutex antes de acessar os dados protegidos.\n" -"* Você pode obter um `&mut T` de um `&Mutex` pegando o bloqueio. O `MutexGuard` garante que o\n" -" `&mut T` não sobrevive ao bloqueio sendo mantido.\n" +"* Você pode obter um `&mut T` de um `&Mutex` obtendo um bloqueio (_lock_). O `MutexGuard` garante que o\n" +" `&mut T` não sobrevive além do bloqueio (_lock_).\n" "* `Mutex` implementa `Send` e `Sync` se `T` implementa `Send`.\n" -"* Uma contraparte de bloqueio de leitura e gravação - `RwLock`.\n" +"* O bloqueio para leitura e gravação - `RwLock`.\n" "* Por que `lock()` retorna um `Result`?\n" " * Se o thread que manteve o `Mutex` entrou em pânico, o `Mutex` torna-se \"envenenado\" para sinalizar que\n" -" os dados protegidos podem estar em um estado inconsistente. Chamando `lock ()` em um mutex envenenado\n" -" falha com um [`PoisonError`]. Você pode chamar `into_inner()` no erro para recuperar os dados\n" +" os dados protegidos podem estar em um estado inconsistente. Ao chamar `lock()` em um mutex envenenado\n" +" o retorno é uma falha com um [`PoisonError`]. Você pode chamar `into_inner()` no erro para recuperar os dados\n" " independentemente." #: src/concurrency/shared_state/mutex.md:44 @@ -12939,7 +13420,7 @@ msgid "" msgstr "" "```rust,editable,compile_fail\n" "use std::thread;\n" -"// usa std::sync::{Arc, Mutex};" +"// use std::sync::{Arc, Mutex};" #: src/concurrency/shared_state/example.md:9 msgid "" @@ -13039,7 +13520,7 @@ msgstr "" "}\n" "```\n" " \n" -"Partes notáveis:" +"Partes importantes:" #: src/concurrency/shared_state/example.md:54 msgid "" @@ -13052,14 +13533,14 @@ msgid "" msgstr "" "* `v` é agrupado em ambos `Arc` e `Mutex`, porque seus interesses são ortogonais.\n" " * Envolver um `Mutex` em um `Arc` é um padrão comum para compartilhar o estado mutável entre threads.\n" -"* `v: Arc<_>` precisa ser clonado como `v2` antes que possa ser movido para outro thread. A nota `move` foi adicionada à " +"* `v: Arc<_>` precisa ser clonado como `v2` antes que possa ser movido para outro thread. Note que `move` foi adicionado à " "assinatura lambda.\n" "* Os blocos são introduzidos para restringir o escopo do `LockGuard` tanto quanto possível.\n" "* Ainda precisamos adquirir o `Mutex` para imprimir nosso `Vec`." #: src/concurrency/send-sync.md:1 msgid "# `Send` and `Sync`" -msgstr "# `Enviar` e `Sincronizar`" +msgstr "# `Send` e `Sync`" #: src/concurrency/send-sync.md:3 msgid "How does Rust know to forbid shared access across thread? The answer is in two traits:" @@ -13072,10 +13553,8 @@ msgid "" "* [`Sync`][2]: a type `T` is `Sync` if it is safe to move a `&T` across a thread\n" " boundary." msgstr "" -"* [`Send`][1]: um tipo `T` é `Send` se for seguro mover um `T` através de um thread\n" -" fronteira.\n" -"* [`Sync`][2]: um tipo `T` é `Sync` se for seguro mover um `&T` através de um thread\n" -" fronteira." +"* [`Send`][1]: um tipo `T` é `Send` se for seguro mover um `T` entre _threads_\n" +"* [`Sync`][2]: um tipo `T` é `Sync` se for seguro mover um `&T` entre _threads_" #: src/concurrency/send-sync.md:10 msgid "" @@ -13083,9 +13562,9 @@ msgid "" "as long as they only contain `Send` and `Sync` types. You can also implement them manually when you\n" "know it is valid." msgstr "" -"`Send` e `Sync` são [características inseguras][3]. O compilador os derivará automaticamente para seus tipos\n" +"`Send` e `Sync` são [`unsafe traits`][3]. O compilador os derivará automaticamente para seus tipos\n" "desde que contenham apenas os tipos `Send` e `Sync`. Você também pode implementá-los manualmente quando\n" -"saiba que é válido." +"souber que são válidos." #: src/concurrency/send-sync.md:14 msgid "" @@ -13104,19 +13583,19 @@ msgid "" " \n" "" msgstr "" -"* Pode-se pensar nessas características como marcadores de que o tipo possui certas ownerships de segurança de " -"encadeamento.\n" -"* Eles podem ser usados nas restrições genéricas como características normais.\n" +"* Pode-se pensar nesses _traits_ como marcadores de que o tipo possui certas propriedades de segurança de " +"_threads_.\n" +"* Eles podem ser usados nas restrições genéricas como _traits_ normais.\n" " \n" "" #: src/concurrency/send-sync/send.md:1 msgid "# `Send`" -msgstr "# `Enviar`" +msgstr "# `Send`" #: src/concurrency/send-sync/send.md:3 msgid "> A type `T` is [`Send`][1] if it is safe to move a `T` value to another thread." -msgstr "> Um tipo `T` é [`Send`][1] se for seguro mover um valor `T` para outro thread." +msgstr "> Um tipo `T` é [`Send`][1] se for seguro mover um valor `T` para outro _thread_." #: src/concurrency/send-sync/send.md:5 msgid "" @@ -13124,9 +13603,9 @@ msgid "" "in that thread. So the question is when you can allocate a value in one thread\n" "and deallocate it in another." msgstr "" -"O efeito de mover a ownership para outro thread é que os _destructors_ serão executados\n" -"nesse fio. Então a questão é quando você pode alocar um valor em um thread\n" -"e desalocá-lo em outro." +"O efeito de mover a propriedade (ownership) para outro _thread_ é que os _destructors_ serão executados\n" +"nessa _thread_. Então a questão é: quando você pode alocar um valor em um _thread_\n" +"e desalocá-lo em outro?" #: src/concurrency/send-sync/send.md:9 msgid "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" @@ -13134,15 +13613,15 @@ msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html" #: src/concurrency/send-sync/sync.md:1 msgid "# `Sync`" -msgstr "# `Sincronizar`" +msgstr "# `Sync`" #: src/concurrency/send-sync/sync.md:3 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 "" -"> Um tipo `T` é [`Sync`][1] se for seguro acessar um valor `T` de vários\n" -"> tópicos ao mesmo tempo." +"> Um tipo `T` é [`Sync`][1] se for seguro acessar um valor `T` de várias\n" +"> threads ao mesmo tempo." #: src/concurrency/send-sync/sync.md:6 msgid "More precisely, the definition is:" @@ -13161,8 +13640,8 @@ 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 "" -"Essa instrução é essencialmente uma maneira abreviada de dizer que, se um tipo é thread-safe para uso compartilhado, também " -"é thread-safe passar referências a ele entre threads." +"Essa instrução é essencialmente uma maneira abreviada de dizer que, se um tipo é _thread-safe_ para uso compartilhado, também " +"é _thread-safe_ passar referências a ele entre _threads_." #: src/concurrency/send-sync/sync.md:16 msgid "" @@ -13170,10 +13649,10 @@ msgid "" "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 "" -"Isso ocorre porque, se um tipo for Sync, significa que ele pode ser compartilhado entre vários encadeamentos sem o risco de " -"corridas de dados ou outros problemas de sincronização, portanto, é seguro movê-lo para outro encadeamento. Uma referência " -"ao tipo também é segura para mover para outro thread, porque os dados a que ele faz referência podem ser acessados de " -"qualquer thread com segurança." +"Isso ocorre porque, se um tipo for `Sync`, significa que ele pode ser compartilhado entre vários _threads_ sem o risco de " +"corridas de dados ou outros problemas de sincronização, portanto, é seguro movê-lo para outro _thread_. Uma referência " +"ao tipo também é segura para mover para outro _thread_, porque os dados a que ela faz referência podem ser acessados de " +"qualquer _thread_ com segurança." #: src/concurrency/send-sync/examples.md:1 msgid "# Examples" @@ -13181,11 +13660,11 @@ msgstr "# Exemplos" #: src/concurrency/send-sync/examples.md:3 msgid "## `Send + Sync`" -msgstr "## `Enviar + Sincronizar`" +msgstr "## `Send + Sync`" #: src/concurrency/send-sync/examples.md:5 msgid "Most types you come across are `Send + Sync`:" -msgstr "A maioria dos tipos que você encontra são `Enviar + Sincronizar`:" +msgstr "A maioria dos tipos que você encontra são `Send + Sync`:" #: src/concurrency/send-sync/examples.md:7 msgid "" @@ -13199,8 +13678,8 @@ msgstr "" "* `i8`, `f32`, `bool`, `char`, `&str`, ...\n" "* `(T1, T2)`, `[T; N]`, `&[T]`, `struct { x: T }`, ...\n" "* `String`, `Option`, `Vec`, `Box`, ...\n" -"* `Arc`: Explicitamente thread-safe via contagem de referência atômica.\n" -"* `Mutex`: Explicitamente thread-safe via bloqueio interno.\n" +"* `Arc`: Explicitamente _thread-safe_ via contagem de referência atômica.\n" +"* `Mutex`: Explicitamente _thread-safe_ via bloqueio interno.\n" "* `AtomicBool`, `AtomicU8`, ...: Usa instruções atômicas especiais." #: src/concurrency/send-sync/examples.md:14 @@ -13209,19 +13688,19 @@ msgid "" "`Send + Sync`." msgstr "" "Os tipos genéricos são tipicamente `Send + Sync` quando os parâmetros de tipo são\n" -"`Enviar + Sincronizar`." +"`Send + Sync`." #: src/concurrency/send-sync/examples.md:17 msgid "## `Send + !Sync`" -msgstr "## `Enviar + !Sync`" +msgstr "## `Send + !Sync`" #: src/concurrency/send-sync/examples.md:19 msgid "" "These types can be moved to other threads, but they're not thread-safe.\n" "Typically because of interior mutability:" msgstr "" -"Esses tipos podem ser movidos para outros encadeamentos, mas não são seguros para encadeamentos.\n" -"Normalmente por causa da mutabilage interior:" +"Esses tipos podem ser movidos para outras _threads_, mas não são seguros para _threads_.\n" +"Normalmente por causa da mutabilidade interior:" #: src/concurrency/send-sync/examples.md:22 msgid "" @@ -13231,33 +13710,33 @@ msgid "" "* `RefCell`" msgstr "" "* `mpsc::Sender`\n" -"* `mpsc::Receptor`\n" -"* `Célula`\n" +"* `mpsc::Receiver`\n" +"* `Cell`\n" "* `RefCell`" #: src/concurrency/send-sync/examples.md:27 msgid "## `!Send + Sync`" -msgstr "## `!Enviar + Sincronizar`" +msgstr "## `!Send + Sync`" #: src/concurrency/send-sync/examples.md:29 msgid "These types are thread-safe, but they cannot be moved to another thread:" -msgstr "Esses tipos são thread-safe, mas não podem ser movidos para outro thread:" +msgstr "Esses tipos são _thread-safe_, mas não podem ser movidos para outro _thread_:" #: src/concurrency/send-sync/examples.md:31 msgid "" "* `MutexGuard`: Uses OS level primitives which must be deallocated on the\n" " thread which created them." msgstr "" -"* `MutexGuard`: Usa primitivas de nível de sistema operacional que devem ser desalocadas no\n" -" discussão que os criou." +"* `MutexGuard`: Usa primitivas a nível de sistema operacional que devem ser desalocadas no\n" +" _thread_ que as criou." #: src/concurrency/send-sync/examples.md:34 msgid "## `!Send + !Sync`" -msgstr "## `!Enviar + !Sincronizar`" +msgstr "## `!Send + !Sync`" #: src/concurrency/send-sync/examples.md:36 msgid "These types are not thread-safe and cannot be moved to other threads:" -msgstr "Esses tipos não são thread-safe e não podem ser movidos para outros threads:" +msgstr "Esses tipos não são _thread-safe_ e não podem ser movidos para outros _threads_:" #: src/concurrency/send-sync/examples.md:38 msgid "" @@ -13266,10 +13745,10 @@ msgid "" "* `*const T`, `*mut T`: Rust assumes raw pointers may have special\n" " concurrency considerations." msgstr "" -"* `Rc`: cada `Rc` tem uma referência a um `RcBox`, que contém um\n" +"* `Rc`: cada `Rc` tem uma referência a um `RcBox`, que contém uma\n" " contagem de referência não atômica.\n" "* `*const T`, `*mut T`: Rust assume que ponteiros brutos podem ter\n" -" considerações de simultaneage." +" considerações de especiais de concorrência." #: src/exercises/day-4/morning.md:1 src/exercises/day-4/afternoon.md:1 msgid "# Exercises" @@ -13277,27 +13756,27 @@ msgstr "# Exercícios" #: src/exercises/day-4/morning.md:3 msgid "Let us practice our new concurrency skills with" -msgstr "Vamos praticar nossas novas habilages de simultaneage com" +msgstr "Vamos praticar nossas novas habilidades de concorrência com:" #: src/exercises/day-4/morning.md:5 msgid "* Dining philosophers: a classic problem in concurrency." -msgstr "* Dining philosophers: um problema clássico em concorrência." +msgstr "* _Dining philosophers_: um problema clássico em concorrência." #: src/exercises/day-4/morning.md:7 msgid "" "* Multi-threaded link checker: a larger project where you'll use Cargo to\n" " download dependencies and then check links in parallel." msgstr "" -"* Verificador de link multiencadeado: um projeto maior em que você usará o Cargo para\n" -" baixe as dependências e verifique os links em paralelo." +"* Verificador de link _multi-threads_: um projeto maior no qual você usará o Cargo para\n" +" baixar as dependências e também verificar os links em paralelo." #: src/exercises/day-4/dining-philosophers.md:1 msgid "# Dining Philosophers" -msgstr "# Dining Philosophers" +msgstr "# Filósofos jantando" #: src/exercises/day-4/dining-philosophers.md:3 msgid "The dining philosophers problem is a classic problem in concurrency:" -msgstr "O problema dos philosophers jantando é um problema clássico em concorrência:" +msgstr "O problema dos filósofos jantando é um problema clássico em concorrência:" #: src/exercises/day-4/dining-philosophers.md:5 msgid "" @@ -13309,21 +13788,21 @@ msgid "" "> 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 "" -"> Cinco philosophers jantam juntos na mesma mesa. Cada philosopher tem sua\n" +"> Cinco filósofos jantam juntos na mesma mesa. Cada folósofo tem seu\n" "> próprio lugar à mesa. Há um garfo entre cada prato. O prato servido é\n" -"> uma espécie de esparguete que se come com dois garfos. Cada philosopher pode\n" -"> só pensa e come alternadamente. Além disso, um philosopher só pode comer sua\n" -"> espaguete quando eles têm garfo esquerdo e direito. Assim, dois garfos só\n" -"> estar disponível quando seus dois vizinhos mais próximos estiverem pensando, não comendo. Depois de\n" -"> um philosopher individual termina de comer, eles abaixam os dois garfos." +"> uma espécie de espaguete que se come com dois garfos. Cada filósofo pode\n" +"> somente pensar ou comer, alternadamente. Além disso, um filósofo só pode comer seu\n" +"> espaguete quando ele têm garfo esquerdo e direito. Assim, dois garfos só\n" +"> estarão disponíveis quando seus dois vizinhos mais próximos estiverem pensando, não comendo. Depois de\n" +"> um filósofo individual termina de comer, ele abaixa os dois garfos." #: src/exercises/day-4/dining-philosophers.md:13 msgid "" -"You will need a local [Cargo installation](../../cargo/running-locally.md) for\n" +"You will need a local [Cargo installation][../../cargo/running-locally.md] for\n" "this exercise. Copy the code below to `src/main.rs` file, fill out the blanks,\n" "and test that `cargo run` does not deadlock:" msgstr "" -"Você precisará de uma [instalação do Cargo] local (../../cargo/running-locally.md) para\n" +"Você precisará de uma [instalação do Cargo][../../cargo/running-locally.md] local para\n" "esse exercício. Copie o código abaixo para o arquivo `src/main.rs`, preencha os espaços em branco,\n" "e teste se `cargo run` não trava:" @@ -13343,7 +13822,7 @@ msgstr "" #: src/exercises/day-4/dining-philosophers.md:23 src/exercises/day-4/solutions-morning.md:28 msgid "struct Fork;" -msgstr "struct Fork;" +msgstr "struct Garfo;" #: src/exercises/day-4/dining-philosophers.md:25 msgid "" @@ -13354,11 +13833,11 @@ msgid "" " // thoughts: ...\n" "}" msgstr "" -"struct Philosopher {\n" -" name: String,\n" -" // left_fork: ...\n" -" // right_fork: ...\n" -" // thoughts: ...\n" +"struct Filosofo {\n" +" nome: String,\n" +" // garfo_esquerda: ...\n" +" // garfo_direita: ...\n" +" // pensamentos: ...\n" "}" #: src/exercises/day-4/dining-philosophers.md:32 @@ -13370,11 +13849,11 @@ msgid "" " .unwrap();\n" " }" msgstr "" -"impl Philosopher {\n" -" fn pense(&self) {\n" -" auto.thoughts\n" -" .send(format!(\"Eureka! {} tem uma nova ideia!\", &self.name))\n" -" .desembrulhar();\n" +"impl Filosofo {\n" +" fn pensa(&self) {\n" +" self.pensamento\n" +" .send(format!(\"Eureka! {} tem uma nova ideia!\", &self.nome))\n" +" .unwrap();\n" " }" #: src/exercises/day-4/dining-philosophers.md:39 @@ -13388,19 +13867,18 @@ msgid "" msgstr "" " fn come(&self) {\n" " // Pegar garfos...\n" -" println!(\"{} está comendo...\", &self.name);\n" -" thread::sleep(Duração::from_millis(10));\n" +" println!(\"{} está comendo...\", &self.nome);\n" +" thread::sleep(Duration::from_millis(10));\n" " }\n" "}" #: src/exercises/day-4/dining-philosophers.md:46 src/exercises/day-4/solutions-morning.md:60 -#, fuzzy msgid "" "static PHILOSOPHERS: &[&str] =\n" " &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];" msgstr "" -"PHILOSOPHERS statics: &[&str] =\n" -" &[\"Sócrates\", \"Platão\", \"Aristóteles\", \"Tales\", \"Pitágoras\"];" +"static FILOSOFOS: &[&str] =\n" +"&[\"Sócrates\", \"Platão\", \"Aristóteles\", \"Tales\", \"Pitágoras\"];" #: src/exercises/day-4/dining-philosophers.md:49 msgid "" @@ -13408,11 +13886,11 @@ msgid "" " // Create forks" msgstr "" "fn main() {\n" -" // Cria bifurcações" +" // Criar garfos" #: src/exercises/day-4/dining-philosophers.md:52 msgid " // Create philosophers" -msgstr " // Criar philosophers" +msgstr " // Criar filosofos" #: src/exercises/day-4/dining-philosophers.md:54 msgid " // Make them think and eat" @@ -13424,13 +13902,13 @@ msgid "" "}\n" "```" msgstr "" -" // Saída de seus thoughts\n" +" // Mostrar seus pensamentos\n" "}\n" "```" #: src/exercises/day-4/link-checker.md:1 msgid "# Multi-threaded Link Checker" -msgstr "# Verificador de links multiencadeados" +msgstr "# Verificador de links _multi-threads_" #: src/exercises/day-4/link-checker.md:3 msgid "" @@ -13439,10 +13917,10 @@ msgid "" "recursively check other pages on the same domain and keep doing this until all\n" "pages have been validated." msgstr "" -"Vamos usar nosso novo conhecimento para criar um verificador de links multiencadeados. Deveria\n" -"comece em uma página da web e verifique se os links na página são válidos. Deveria\n" -"verifique recursivamente outras páginas no mesmo domínio e continue fazendo isso até que todas\n" -"as páginas foram validadas." +"Vamos usar nosso novo conhecimento para criar um verificador de links _multi-threads_. \n" +"Comece em uma página da web e verifique se os links na página são válidos. \n" +"Verifique recursivamente outras páginas no mesmo domínio e continue fazendo isso até que todas\n" +"as páginas tenham sido validadas." #: src/exercises/day-4/link-checker.md:8 msgid "" @@ -13450,7 +13928,7 @@ msgid "" "Cargo project and `reqwest` it as a dependency with:" msgstr "" "Para isso, você precisará de um cliente HTTP como [`reqwest`][1]. Crie um novo\n" -"Cargo project e `reqwest` como uma dependência com:" +"Project com o Cargo e adicione `reqwest` como uma dependência:" #: src/exercises/day-4/link-checker.md:11 msgid "" @@ -13461,7 +13939,7 @@ msgid "" "```" msgstr "" "```shell\n" -"$ cargo new verificador de link\n" +"$ cargo new link-checker\n" "$ cd link-checker\n" "$ cargo add --features blocking,rustls-tls reqwest\n" "```" @@ -13472,7 +13950,7 @@ msgid "" "> `Cargo.toml` file by hand. Add the dependencies listed below." msgstr "" "> Se `cargo add` falhar com `error: no such subcommand`, edite o\n" -"> Arquivo `Cargo.toml` à mão. Adicione as dependências listadas abaixo." +"> arquivo `Cargo.toml` à mão. Adicione as dependências listadas abaixo." #: src/exercises/day-4/link-checker.md:20 msgid "You will also need a way to find links. We can use [`scraper`][2] for that:" @@ -13485,7 +13963,7 @@ msgid "" "```" msgstr "" "```shell\n" -"$ cargo adicionar raspador\n" +"$ cargo add scraper\n" "```" #: src/exercises/day-4/link-checker.md:26 @@ -13494,7 +13972,7 @@ msgid "" "that:" msgstr "" "Por fim, precisaremos de alguma forma de lidar com os erros. Usamos [`thiserror`][3] para\n" -"que:" +"isso:" #: src/exercises/day-4/link-checker.md:29 msgid "" @@ -13503,7 +13981,7 @@ msgid "" "```" msgstr "" "```shell\n" -"$ cargo adicionar este erro\n" +"$ cargo add thiserror\n" "```" #: src/exercises/day-4/link-checker.md:33 @@ -13522,8 +14000,8 @@ msgstr "" "```toml\n" "[dependências]\n" "reqwest = { version = \"0.11.12\", features = [\"blocking\", \"rustls-tls\"] }\n" -"raspador = \"0.13.0\"\n" -"este erro = \"1.0.37\"\n" +"scraper = \"0.13.0\"\n" +"thiserror = \"1.0.37\"\n" "```" #: src/exercises/day-4/link-checker.md:42 @@ -13549,8 +14027,8 @@ msgstr "" "```rust,compile_fail\n" "use reqwest::blocking::{get, Response};\n" "use reqwest::Url;\n" -"use raspador::{Html, Seletor};\n" -"use este erro::Erro;" +"use scraper::{Html, Selector};\n" +"use thiserror::Error;" #: src/exercises/day-4/link-checker.md:53 msgid "" @@ -13560,8 +14038,8 @@ msgid "" " ReqwestError(#[from] reqwest::Error),\n" "}" msgstr "" -"#[derive(erro, depuração)]\n" -"Erro de Enum {\n" +"#[derive(Error, Debug)]\n" +"enum Error{\n" " #[error(\"erro de solicitação: {0}\")]\n" " ReqwestError(#[from] reqwest::Error),\n" "}" @@ -13574,7 +14052,7 @@ msgid "" " let html = Html::parse_document(&document);\n" " let selector = Selector::parse(\"a\").unwrap();" msgstr "" -"fn extract_links(resposta: Resposta) -> Result, Erro> {\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" @@ -13595,7 +14073,7 @@ msgid "" " }" msgstr "" " let mut valid_urls = Vec::new();\n" -" for elemento em html.select(&seletor) {\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" @@ -13629,9 +14107,9 @@ msgstr "" "fn main() {\n" " let start_url = Url::parse(\"https://www.google.org\").unwrap();\n" " let response = get(start_url).unwrap();\n" -" match extract_links(resposta) {\n" +" match extract_links(response) {\n" " Ok(links) => println!(\"Links: {links:#?}\"),\n" -" Err(err) => println!(\"Não foi possível extrair links: {err:#}\"),\n" +" Err(err) => println!(\"Não foi possível extrair os links: {err:#}\"),\n" " }\n" "}\n" "```" @@ -13647,7 +14125,7 @@ msgid "" "```" msgstr "" "```shell\n" -"corrida de cargo $\n" +"$ cargo run\n" "```" #: src/exercises/day-4/link-checker.md:96 @@ -13662,10 +14140,10 @@ msgid "" " `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 "" -"* Use threads para verificar os links em paralelo: envie as URLs a serem verificadas para um\n" -" channel e deixe alguns threads verificarem as URLs em paralelo.\n" +"* Use _threads_ para verificar os links em paralelo: envie as URLs a serem verificadas para um\n" +" _channel_ e deixe alguns _threads_ verificarem as URLs em paralelo.\n" "* Estenda isso para extrair recursivamente links de todas as páginas no\n" -" domínio `www.google.org`. Coloque um limite máximo de 100 páginas ou mais para que você\n" +" domínio `www.google.org`. Coloque um limite máximo de 100 páginas ou menos para que você\n" " não acabe sendo bloqueado pelo site." #: src/exercises/day-4/link-checker.md:104 @@ -13680,7 +14158,7 @@ msgstr "" #: src/android.md:1 msgid "# Android" -msgstr "#Android" +msgstr "# Android" #: src/android.md:3 msgid "" @@ -13714,8 +14192,8 @@ msgid "" msgstr "" "```shell\n" "$ source build/envsetup.sh\n" -"$ almoço aosp_cf_x86_64_phone-userdebug\n" -"$ acloud criar\n" +"$ launch aosp_cf_x86_64_phone-userdebug\n" +"$ acloud create\n" "```" #: src/android/setup.md:12 @@ -13723,8 +14201,8 @@ msgid "" "Please see the [Android Developer\n" "Codelab](https://source.android.com/docs/setup/start) for details." msgstr "" -"Consulte o [Desenvolvedor Android\n" -"Codelab](https://source.android.com/docs/setup/start) para obter detalhes." +"Consulte o [Codelab para Desenvolvedor Android]\n" +"[https://source.android.com/docs/setup/start] para obter detalhes." #: src/android/build-rules.md:1 msgid "# Build Rules" @@ -13748,17 +14226,15 @@ msgid "" "| `rust_bindgen` | Generates source and produces a Rust library containing Rust bindings to C libraries. |" msgstr "" "| Tipo de módulo | Descrição |\n" -"|-------------------|---------------------------- -------------------------------------------------- " -"---------------------|\n" -"| `rust_binary` | Produz um binário Rust. |\n" -"| `rust_library` | Produz uma biblioteca Rust e fornece as variantes `rlib` e `dylib`. |\n" -"| `rust_ffi` | Produz uma biblioteca Rust C utilizável por módulos `cc` e fornece variantes estáticas e compartilhadas. |\n" -"| `rust_proc_macro` | Produz uma biblioteca Rust `proc-macro`. Estes são análogos aos plugins do compilador. |\n" -"| `rust_test` | Produz um binário de teste Rust que usa o equipamento de teste Rust padrão. |\n" -"| `rust_fuzz` | Produz um binário Rust fuzz aproveitando `libfuzzer`. |\n" -"| `rust_protobuf` | Gera o código-fonte e produz uma biblioteca Rust que fornece uma interface para um protobuf específico. " -"|\n" -"| `rust_bindgen` | Gera fonte e produz uma biblioteca Rust contendo ligações Rust para bibliotecas C. |" +"|-------------------|----------------------------------------------------------------------------------------------------------|\n" +"| `rust_binary` | Produz um binário Rust. |\n" +"| `rust_library` | Produz uma biblioteca Rust e fornece as variantes `rlib` e `dylib`. |\n" +"| `rust_ffi` | Produz uma biblioteca Rust C utilizável por módulos `cc` e fornece variantes estáticas e compartilhadas. |\n" +"| `rust_proc_macro` | Produz uma biblioteca Rust `proc-macro`. Estes são análogos aos plugins do compilador. |\n" +"| `rust_test` | Produz um binário de teste Rust que usa o equipamento de teste Rust padrão. |\n" +"| `rust_fuzz` | Produz um binário Rust fuzz aproveitando `libfuzzer`. |\n" +"| `rust_protobuf` | Gera o código-fonte e produz uma biblioteca Rust que fornece uma interface para um _protobuf_ específico.|\n" +"| `rust_bindgen` | Gera fonte e produz uma biblioteca Rust contendo ligações Rust para bibliotecas C. |" #: src/android/build-rules.md:16 msgid "We will look at `rust_binary` and `rust_library` next." @@ -13791,7 +14267,7 @@ msgid "" "```" msgstr "" "```javascript\n" -"rust_binário {\n" +"rust_binary{\n" " name: \"olá_rust\",\n" " crate_name: \"hello_rust\",\n" " srcs: [\"src/main.rs\"],\n" @@ -13808,7 +14284,7 @@ msgid "" "//! Rust demo." msgstr "" "```rust\n" -"//! Demonstração de rust." +"//! Demonstração de Rust." #: src/android/build-rules/binary.md:21 msgid "" @@ -13838,7 +14314,7 @@ msgid "" "```" msgstr "" "```shell\n" -"$ m olá_rust\n" +"$ m hello_rust\n" "$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\n" "$ adb shell /data/local/tmp/hello_rust\n" "Saudações da Rust!\n" @@ -13846,7 +14322,7 @@ msgstr "" #: src/android/build-rules/library.md:1 msgid "# Rust Libraries" -msgstr "# Bibliotecas de rust" +msgstr "# Bibliotecas de Rust" #: src/android/build-rules/library.md:3 msgid "You use `rust_library` to create a new Rust library for Android." @@ -13857,23 +14333,20 @@ msgid "Here we declare a dependency on two libraries:" msgstr "Aqui declaramos uma dependência em duas bibliotecas:" #: src/android/build-rules/library.md:7 -#, fuzzy msgid "" "* `libgreeting`, which we define below,\n" "* `libtextwrap`, which is a crate already vendored in\n" " [`external/rust/crates/`][crates]." msgstr "" "* `libgreeting`, que definimos abaixo,\n" -"* `libtextwrap`, que é uma caixa já vendida em\n" -" [`externo/rust/caixas/`][caixas]." +"* `libtextwrap`, que é um `crate` já vendida em\n" +" [`external/rust/crates/`][crates]." #: src/android/build-rules/library.md:11 -#, fuzzy msgid "[crates]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/" -msgstr "[caixas]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/" +msgstr "[crates]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/" #: src/android/build-rules/library.md:15 -#, fuzzy msgid "" "```javascript\n" "rust_binary {\n" @@ -13955,7 +14428,7 @@ msgid "" "//! Greeting library." msgstr "" "```rust, ignore\n" -"//! Saudação biblioteca." +"//! Biblioteca de Saudação." #: src/android/build-rules/library.md:53 msgid "" @@ -13965,8 +14438,8 @@ msgid "" "}\n" "```" msgstr "" -"/// Saudação `name`.\n" -"pub fn saudação(name: &str) -> String {\n" +"/// Saudação `nome`.\n" +"pub fn greeting(name: &str) -> String {\n" " format!(\"Olá {name}, prazer em conhecê-lo!\")\n" "}\n" "```" @@ -13989,13 +14462,12 @@ msgstr "" "$ m hello_rust_with_dep\n" "$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/tmp\n" "$ adb shell /data/local/tmp/hello_rust_with_dep\n" -"Olá Bob, é muito\n" -"prazer em conhecê-lo!\n" +"Olá Bob, prazer em conhecê-lo!\n" "```" #: src/android/aidl.md:1 msgid "# AIDL" -msgstr "#AIDL" +msgstr "# AIDL" #: src/android/aidl.md:3 msgid "" @@ -14045,13 +14517,13 @@ msgstr "" "/** Interface de serviço de aniversário. */\n" "interface IBirthdayService {\n" " /** Gera uma mensagem de feliz aniversário. */\n" -" String desejoFelizAniversário(String name, int anos);\n" +" String wishHappyBirthday(String name, int years);\n" "}\n" "```" #: src/android/aidl/interface.md:17 msgid "*birthday_service/aidl/Android.bp*:" -msgstr "*aniversário_service/aidl/Android.bp*:" +msgstr "*birthday_service/aidl/Android.bp*:" #: src/android/aidl/interface.md:19 msgid "" @@ -14072,10 +14544,10 @@ msgstr "" "aidl_interface {\n" " name: \"com.example.birthdayservice\",\n" " srcs: [\"com/example/birthdayservice/*.aidl\"],\n" -" instável: true,\n" -" Processo interno: {\n" +" unstable: true,\n" +" backend: {\n" " rust: { // Rust não está ativado por padrão\n" -" ativado: true,\n" +" enabled: true,\n" " },\n" " },\n" "}\n" @@ -14086,8 +14558,7 @@ msgid "" "Add `vendor_available: true` if your AIDL file is used by a binary in the vendor\n" "partition." msgstr "" -"Adicione `vendor_available: true` se seu arquivo AIDL for usado por um binário no fornecedor\n" -"partição." +"Adicione `vendor_available: true` se seu arquivo AIDL for usado por um binário na partição _vendor_." #: src/android/aidl/implementation.md:1 msgid "# Service Implementation" @@ -14099,7 +14570,7 @@ msgstr "Agora podemos implementar o serviço AIDL:" #: src/android/aidl/implementation.md:5 msgid "*birthday_service/src/lib.rs*:" -msgstr "*aniversário_serviço/src/lib.rs*:" +msgstr "*birthday_service/src/lib.rs*:" #: src/android/aidl/implementation.md:7 msgid "" @@ -14123,7 +14594,7 @@ msgstr "" #: src/android/aidl/implementation.md:15 msgid "impl binder::Interface for BirthdayService {}" -msgstr "impl binder::Interface para BirthdayService {}" +msgstr "impl binder::Interface for BirthdayService {}" #: src/android/aidl/implementation.md:17 msgid "" @@ -14147,7 +14618,7 @@ msgstr "" #: src/android/aidl/implementation.md:26 src/android/aidl/server.md:28 src/android/aidl/client.md:37 msgid "*birthday_service/Android.bp*:" -msgstr "*aniversário_serviço/Android.bp*:" +msgstr "*birthday_service/Android.bp*:" #: src/android/aidl/implementation.md:28 msgid "" @@ -14167,7 +14638,7 @@ msgstr "" "rust_library {\n" " name: \"libbirthdayservice\",\n" " srcs: [\"src/lib.rs\"],\n" -" crate_name: \"aniversário\",\n" +" crate_name: \"birthdayservice\",\n" " rustlibs: [\n" " \"com.example.birthdayservice-rust\",\n" " \"libbinder_rs\",\n" @@ -14181,11 +14652,11 @@ msgstr "# Servidor AIDL" #: src/android/aidl/server.md:3 msgid "Finally, we can create a server which exposes the service:" -msgstr "Finalmente, podemos criar um servidor que exponha o serviço:" +msgstr "Finalmente, podemos criar um servidor que expõe o serviço:" #: src/android/aidl/server.md:5 msgid "*birthday_service/src/server.rs*:" -msgstr "*aniversário_serviço/src/servidor.rs*:" +msgstr "*birthday_service/src/server.rs*:" #: src/android/aidl/server.md:7 msgid "" @@ -14203,7 +14674,7 @@ msgstr "" #: src/android/aidl/server.md:13 src/android/aidl/client.md:12 msgid "const SERVICE_IDENTIFIER: &str = \"birthdayservice\";" -msgstr "const SERVICE_IDENTIFIER: &str = \"aniversário\";" +msgstr "const SERVICE_IDENTIFIER: &str = \"birthdayservice\";" #: src/android/aidl/server.md:15 msgid "" @@ -14222,9 +14693,9 @@ msgid "" msgstr "" "/// Point de entrada para serviço de aniversário.\n" "fn main() {\n" -" let serviço_aniversário = ServiçoAniversário;\n" +" let birthday_service = BirthdayService;\n" " let birthday_service_binder = BnBirthdayService::new_binder(\n" -" aniversário_serviço,\n" +" birthday_server,\n" " binder::BinderFeatures::default(),\n" " );\n" " binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder.as_binder())\n" @@ -14250,10 +14721,10 @@ msgid "" "```" msgstr "" "```javascript\n" -"rust_binário {\n" -" name: \"aniversário_servidor\",\n" -" crate_name: \"aniversário_servidor\",\n" -" srcs: [\"src/servidor.rs\"],\n" +"rust_binary {\n" +" name: \"birthday_server\",\n" +" crate_name: \"birthday_server\",\n" +" srcs: [\"src/server.rs\"],\n" " rustlibs: [\n" " \"com.example.birthdayservice-rust\",\n" " \"libbinder_rs\",\n" @@ -14280,7 +14751,7 @@ msgid "" "```" msgstr "" "```shell\n" -"$ m aniversário_servidor\n" +"$ m birthday_server\n" "$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp\n" "$ adb shell /data/local/tmp/birthday_server\n" "```" @@ -14325,7 +14796,7 @@ msgstr "" "Result: Parcel(\n" " 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" " 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" -" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .Prumo.,. .'\n" +" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'\n" " 0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'\n" " 0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'\n" " 0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .a.'\n" @@ -14343,7 +14814,7 @@ msgstr "Por fim, podemos criar um cliente Rust para nosso novo serviço." #: src/android/aidl/client.md:5 msgid "*birthday_service/src/client.rs*:" -msgstr "*aniversário_service/src/client.rs*:" +msgstr "*birthday_server/src/client.rs*:" #: src/android/aidl/client.md:7 msgid "" @@ -14381,7 +14852,7 @@ msgid "" " .and_then(|arg| arg.parse::().ok())\n" " .unwrap_or(42);" msgstr "" -"/// Ligue para o serviço de aniversário.\n" +"/// Chamada ao serviço de aniversário.\n" "fn main() -> Result<(), binder::Status> {\n" " let name = std::env::args()\n" " .nth(1)\n" @@ -14425,9 +14896,9 @@ msgid "" "```" msgstr "" "```javascript\n" -"rust_binário {\n" -" name: \"aniversario_cliente\",\n" -" crate_name: \"aniversário_cliente\",\n" +"rust_binary {\n" +" name: \"birthday_client\",\n" +" crate_name: \"birthday_client\",\n" " srcs: [\"src/client.rs\"],\n" " rustlibs: [\n" " \"com.example.birthdayservice-rust\",\n" @@ -14455,7 +14926,7 @@ msgid "" "```" msgstr "" "```shell\n" -"$ m aniversário_cliente\n" +"$ m birthday_client\n" "$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp\n" "$ adb shell /data/local/tmp/birthday_client Charlie 60\n" "Parabéns Charlie, parabéns pelos 60 anos!\n" @@ -14470,7 +14941,7 @@ msgid "" "Let us extend the API with more functionality: we want to let clients specify a\n" "list of lines for the birthday card:" msgstr "" -"Vamos estender a API com mais funcionalage: queremos permitir que os clientes especifiquem um\n" +"Vamos estender a API com mais funcionalidades: queremos permitir que os clientes especifiquem uma\n" "lista de linhas para o cartão de aniversário:" #: src/android/aidl/changing.md:9 @@ -14491,15 +14962,15 @@ msgstr "" #: src/android/logging.md:1 msgid "# Logging" -msgstr "# Exploração madeireira" +msgstr "# Gerando registros (Log)" #: src/android/logging.md:3 msgid "" "You should use the `log` crate to automatically log to `logcat` (on-device) or\n" "`stdout` (on-host):" msgstr "" -"Você deve usar a caixa `log` para logar automaticamente no `logcat` (on-device dispositivo) ou\n" -"`stdout` (on-host):" +"Você deve usar o `crate` `log` para logar automaticamente no `logcat` (no dispositivo) ou\n" +"`stdout` (no hospedeiro):" #: src/android/logging.md:6 msgid "_hello_rust_logs/Android.bp_:" @@ -14522,13 +14993,13 @@ msgid "" "```" msgstr "" "```javascript\n" -"rust_binário {\n" +"rust_binary {\n" " name: \"hello_rust_logs\",\n" " crate_name: \"hello_rust_logs\",\n" " srcs: [\"src/main.rs\"],\n" " rustlibs: [\n" " \"liblog_rust\",\n" -" \"blogueiro\",\n" +" \"liblogger\",\n" " ],\n" " prefere_rlib: true,\n" " host_supported: true,\n" @@ -14575,7 +15046,7 @@ msgstr "" " );\n" " debug!(\"Iniciando programa.\");\n" " info!(\"As coisas estão indo bem.\");\n" -" erro!(\"Algo deu errado!\");\n" +" error!(\"Algo deu errado!\");\n" "}\n" "```" @@ -14619,43 +15090,43 @@ msgstr "" #: src/android/interoperability.md:1 msgid "# Interoperability" -msgstr "# Interoperabilage" +msgstr "# Interoperabilidade" #: src/android/interoperability.md:3 msgid "" "Rust has excellent support for interoperability with other languages. This means\n" "that you can:" msgstr "" -"Rust tem excelente suporte para interoperabilage com outras linguagens. Isso significa\n" -"isso você pode:" +"Rust tem excelente suporte para interoperabilidade com outras linguagens. Isso significa\n" +"que você pode:" #: src/android/interoperability.md:6 msgid "" "* Call Rust functions from other languages.\n" "* Call functions written in other languages from Rust." msgstr "" -"* Chame funções Rust de outros idiomas.\n" -"* Chama funções escritas em outras linguagens do Rust." +"* Chamar funções _Rust_ em outras linguagens.\n" +"* Chamar funções escritas em outras linguagens no _Rust_." #: src/android/interoperability.md:9 msgid "" "When you call functions in a foreign language we say that you're using a\n" "_foreign function interface_, also known as FFI." msgstr "" -"Quando você chama funções em um idioma estrangeiro, dizemos que você está usando um\n" +"Quando você chama funções em outra linguagem, dizemos que você está usando uma\n" "_interface de função externa_, também conhecida como FFI." #: src/android/interoperability/with-c.md:1 msgid "# Interoperability with C" -msgstr "# Interoperabilage com C" +msgstr "# Interoperabilidade com C" #: src/android/interoperability/with-c.md:3 msgid "" "Rust has full support for linking object files with a C calling convention.\n" "Similarly, you can export Rust functions and call them from C." msgstr "" -"Rust tem suporte completo para vincular arquivos de objeto com uma convenção de chamada C.\n" -"Da mesma forma, você pode exportar funções Rust e chamá-las de C." +"_Rust_ tem suporte completo para vincular arquivos de objeto com uma convenção de chamada C.\n" +"Da mesma forma, você pode exportar funções Rust e chamá-las em C." #: src/android/interoperability/with-c.md:6 msgid "You can do it by hand if you want:" @@ -14690,13 +15161,12 @@ msgstr "" "```" #: src/android/interoperability/with-c.md:20 -#, fuzzy msgid "" "We already saw this in the [Safe FFI Wrapper\n" "exercise](../../exercises/day-3/safe-ffi-wrapper.md)." msgstr "" -"Já vimos isso no [Safe FFI Wrapper\n" -"exercício](../../exercises/day-3/safe-ffi-wrapper.md)." +"Já vimos isso no exercício [Safe FFI Wrapper\n" +"](../../exercises/day-3/safe-ffi-wrapper.md)." #: src/android/interoperability/with-c.md:23 msgid "" @@ -14728,7 +15198,7 @@ msgstr "Primeiro crie uma pequena biblioteca C:" #: src/android/interoperability/with-c/bindgen.md:8 msgid "_interoperability/bindgen/libbirthday.h_:" -msgstr "_interoperabilage/bindgen/libbirthday.h_:" +msgstr "_interoperability/bindgen/libbirthday.h_:" #: src/android/interoperability/with-c/bindgen.md:10 msgid "" @@ -14754,7 +15224,7 @@ msgstr "" #: src/android/interoperability/with-c/bindgen.md:19 msgid "_interoperability/bindgen/libbirthday.c_:" -msgstr "_interoperabilage/bindgen/libbirthday.c_:" +msgstr "_interoperability/bindgen/libbirthday.c_:" #: src/android/interoperability/with-c/bindgen.md:21 msgid "" @@ -14764,7 +15234,7 @@ msgid "" msgstr "" "```c\n" "#include \n" -"#include \"libaniversário.h\"" + "#include \"libbirthday.h\"" #: src/android/interoperability/with-c/bindgen.md:25 msgid "" @@ -14778,7 +15248,7 @@ msgid "" msgstr "" "void print_card(const card* card) {\n" " printf(\"+--------------\\n\");\n" -" printf(\"| Feliz Aniversário %s!\\n\", cartão->name);\n" +" printf(\"| Feliz Aniversário %s!\\n\", card->name);\n" " printf(\"| Parabéns pelos %i anos!\\n\", card->years);\n" " printf(\"+--------------\\n\");\n" "}\n" @@ -14791,7 +15261,7 @@ msgstr "Adicione isto ao seu arquivo `Android.bp`:" #: src/android/interoperability/with-c/bindgen.md:35 src/android/interoperability/with-c/bindgen.md:55 #: src/android/interoperability/with-c/bindgen.md:69 src/android/interoperability/with-c/bindgen.md:108 msgid "_interoperability/bindgen/Android.bp_:" -msgstr "_interoperabilage/bindgen/Android.bp_:" +msgstr "_interoperability/bindgen/Android.bp_:" #: src/android/interoperability/with-c/bindgen.md:37 msgid "" @@ -14804,7 +15274,7 @@ msgid "" msgstr "" "```javascript\n" "cc_library {\n" -" name: \"libaniversário\",\n" +" name: \"libbirthday\",\n" " srcs: [\"libbirthday.c\"],\n" "}\n" "```" @@ -14819,7 +15289,7 @@ msgstr "" #: src/android/interoperability/with-c/bindgen.md:47 msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" -msgstr "_interoperabilage/bindgen/libbirthday_wrapper.h_:" +msgstr "_interoperability/bindgen/libbirthday_wrapper.h_:" #: src/android/interoperability/with-c/bindgen.md:49 msgid "" @@ -14828,7 +15298,7 @@ msgid "" "```" msgstr "" "```c\n" -"#include \"libaniversário.h\"\n" +"#include \"libbirthday.h\"\n" "```" #: src/android/interoperability/with-c/bindgen.md:53 @@ -14850,10 +15320,10 @@ msgstr "" "```javascript\n" "rust_bindgen {\n" " name: \"libbirthday_bindgen\",\n" -" crate_name: \"aniversário_bindgen\",\n" +" crate_name: \"birthday_bindgen\",\n" " wrapper_src: \"libbirthday_wrapper.h\",\n" -" source_stem: \"vinculações\",\n" -" static_libs: [\"libaniversário\"],\n" +" source_stem: \"bindings\",\n" +" static_libs: [\"libbirthday\"],\n" "}\n" "```" @@ -14872,7 +15342,7 @@ msgid "" "```" msgstr "" "```javascript\n" -"rust_binário {\n" +"rust_binary{\n" " name: \"print_birthday_card\",\n" " srcs: [\"main.rs\"],\n" " rustlibs: [\"libbirthday_bindgen\"],\n" @@ -14881,7 +15351,7 @@ msgstr "" #: src/android/interoperability/with-c/bindgen.md:79 msgid "_interoperability/bindgen/main.rs_:" -msgstr "_interoperabilage/bindgen/main.rs_:" +msgstr "_interoperability/bindgen/main.rs_:" #: src/android/interoperability/with-c/bindgen.md:81 msgid "" @@ -14985,25 +15455,23 @@ msgstr "Exportar funções e tipos do Rust para C é fácil:" #: src/android/interoperability/with-c/rust.md:5 msgid "_interoperability/rust/libanalyze/analyze.rs_" -msgstr "_interoperabilage/rust/libanalyze/analyze.rs_" +msgstr "_interoperability/rust/libanalyze/analyze.rs_" #: src/android/interoperability/with-c/rust.md:7 -#, fuzzy msgid "" "```rust,editable\n" "//! Rust FFI demo.\n" "#![deny(improper_ctypes_definitions)]" msgstr "" "```rust, editable\n" -"//! Rust FFI demonstração.\n" -"#![negar(improper_ctypes_definitions)]" +"//! Demonstração de uso do FFI com Rust.\n" +"#![deny(improper_ctypes_definitions)]" #: src/android/interoperability/with-c/rust.md:11 msgid "use std::os::raw::c_int;" msgstr "use std::os::raw::c_int;" #: src/android/interoperability/with-c/rust.md:13 -#, fuzzy msgid "" "/// Analyze the numbers.\n" "#[no_mangle]\n" @@ -15018,7 +15486,7 @@ msgid "" msgstr "" "/// Analisar os números.\n" "#[no_mangle]\n" -"pub extern \"C\" fn analise_números(x: c_int, y: c_int) {\n" +"pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" " if x < y {\n" " println!(\"x ({x}) é o menor!\");\n" " } else {\n" @@ -15029,7 +15497,7 @@ msgstr "" #: src/android/interoperability/with-c/rust.md:24 msgid "_interoperability/rust/libanalyze/analyze.h_" -msgstr "_interoperabilage/rust/libanalyze/analyze.h_" +msgstr "_interoperability/rust/libanalyze/analyze.h_" #: src/android/interoperability/with-c/rust.md:26 msgid "" @@ -15047,8 +15515,8 @@ msgid "" "void analyze_numbers(int x, int y);\n" "}" msgstr "" -"externo \"C\" {\n" -"void analizar_números(int x, int y);\n" +"extern \"C\" {\n" +"void analyze_numbers(int x, int y);\n" "}" #: src/android/interoperability/with-c/rust.md:34 @@ -15056,12 +15524,12 @@ msgid "" "#endif\n" "```" msgstr "" -"#fim se\n" +"#endif\n" "```" #: src/android/interoperability/with-c/rust.md:37 msgid "_interoperability/rust/libanalyze/Android.bp_" -msgstr "_interoperabilage/rust/libanalyze/Android.bp_" +msgstr "_interoperability/rust/libanalyze/Android.bp_" #: src/android/interoperability/with-c/rust.md:39 msgid "" @@ -15078,7 +15546,7 @@ msgstr "" "rust_ffi {\n" " name: \"libanalyze_ffi\",\n" " crate_name: \"analyze_ffi\",\n" -" srcs: [\"analisar.rs\"],\n" +" srcs: [\"analyze.rs\"],\n" " include_dirs: [\".\"],\n" "}\n" "```" @@ -15089,7 +15557,7 @@ msgstr "Agora podemos chamar isso de um binário C:" #: src/android/interoperability/with-c/rust.md:50 msgid "_interoperability/rust/analyze/main.c_" -msgstr "_interoperabilage/rust/analisar/main.c_" +msgstr "_interoperability/rust/analisar/main.c_" #: src/android/interoperability/with-c/rust.md:52 msgid "" @@ -15097,7 +15565,7 @@ msgid "" "#include \"analyze.h\"" msgstr "" "```c\n" -"#include \"analisar.h\"" +"#include \"analyze.h\"" #: src/android/interoperability/with-c/rust.md:55 msgid "" @@ -15117,7 +15585,7 @@ msgstr "" #: src/android/interoperability/with-c/rust.md:62 msgid "_interoperability/rust/analyze/Android.bp_" -msgstr "_interoperabilage/rust/analyze/Android.bp_" +msgstr "_interoperability/rust/analyze/Android.bp_" #: src/android/interoperability/with-c/rust.md:64 msgid "" @@ -15131,7 +15599,7 @@ msgid "" msgstr "" "```javascript\n" "cc_binary {\n" -" name: \"analisar_números\",\n" +" name: \"analyze_numbers\",\n" " srcs: [\"main.c\"],\n" " static_libs: [\"libanalyze_ffi\"],\n" "}\n" @@ -15146,7 +15614,7 @@ msgid "" "```" msgstr "" "```shell\n" -"$ m analizar_números\n" +"$ m analyze_numbers\n" "$ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp\n" "$ adb shell /data/local/tmp/analyze_numbers\n" "```" @@ -15156,8 +15624,8 @@ msgid "" "`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol will just be the name of\n" "the function. You can also use `#[export_name = \"some_name\"]` to specify whatever name you want." msgstr "" -"`#[no_mangle]` desativa a alteração de name usual do Rust, então o símbolo exportado será apenas o name de\n" -"a função. Você também pode usar `#[export_name = \"some_name\"]` para especificar qualquer name que desejar." +"`#[no_mangle]` desativa a alteração de name usual do Rust, então o símbolo exportado será apenas o nome da\n" +"função. Você também pode usar `#[export_name = \"some_name\"]` para especificar qualquer nome que desejar." #: src/android/interoperability/cpp.md:1 msgid "# With C++" @@ -15168,7 +15636,7 @@ msgid "" "The [CXX crate][1] makes it possible to do safe interoperability between Rust\n" "and C++." msgstr "" -"A [caixa CXX] [1] possibilita a interoperabilage segura entre Rust\n" +"O [crate CXX][1] possibilita a interoperabilidade segura entre Rust\n" "e C++." #: src/android/interoperability/cpp.md:6 @@ -15181,7 +15649,7 @@ msgstr "" #: src/android/interoperability/cpp.md:10 msgid "See the [CXX tutorial][2] for an full example of using this." -msgstr "Veja o [tutorial CXX][2] para um exemplo completo de como usar isso." +msgstr "Veja o [tutorial CXX][2] para um exemplo completo de como usá-lo." #: src/android/interoperability/cpp.md:12 msgid "" @@ -15193,7 +15661,7 @@ msgstr "" #: src/android/interoperability/java.md:1 msgid "# Interoperability with Java" -msgstr "# Interoperabilage com Java" +msgstr "# Interoperabilidade com Java" #: src/android/interoperability/java.md:3 msgid "" @@ -15202,8 +15670,8 @@ msgid "" "crate](https://docs.rs/jni/) allows you to create a compatible library." msgstr "" "Java pode carregar objetos compartilhados via [Java Native Interface\n" -"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). O [`jni`\n" -"crate](https://docs.rs/jni/) permite que você crie uma biblioteca compatível." +"(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface).\n" +"O [crate `jni`](https://docs.rs/jni/) permite que você crie uma biblioteca compatível." #: src/android/interoperability/java.md:7 msgid "First, we create a Rust function to export to Java:" @@ -15211,7 +15679,7 @@ msgstr "Primeiro, criamos uma função Rust para exportar para Java:" #: src/android/interoperability/java.md:9 msgid "_interoperability/java/src/lib.rs_:" -msgstr "_interoperabilage/java/src/lib.rs_:" +msgstr "_interoperability/java/src/lib.rs_:" #: src/android/interoperability/java.md:11 msgid "" @@ -15219,7 +15687,7 @@ msgid "" "//! Rust <-> Java FFI demo." msgstr "" "```rust,compile_fail\n" -"//! Rust <-> Demonstração Java FFI." +"//! Demonstração FFI Rust <-> Java." #: src/android/interoperability/java.md:14 msgid "" @@ -15249,13 +15717,13 @@ msgid "" msgstr "" "/// Implementação do método HelloWorld::hello.\n" "#[no_mangle]\n" -"pub extern \"sistema\" fn Java_HelloWorld_hello(\n" +"pub extern \"system\" fn Java_HelloWorld_hello(\n" " env: JNIEnv,\n" " _class: JClass,\n" " name: JString,\n" ") -> jstring {\n" " let input: String = env.get_string(name).unwrap().into();\n" -" let saudação = format!(\"Olá, {input}!\");\n" +" let greeting = format!(\"Olá, {input}!\");\n" " let output = env.new_string(greeting).unwrap();\n" " output.into_inner()\n" "}\n" @@ -15263,7 +15731,7 @@ msgstr "" #: src/android/interoperability/java.md:32 src/android/interoperability/java.md:62 msgid "_interoperability/java/Android.bp_:" -msgstr "_interoperabilage/java/Android.bp_:" +msgstr "_interoperability/java/Android.bp_:" #: src/android/interoperability/java.md:34 msgid "" @@ -15291,7 +15759,7 @@ msgstr "Finalmente, podemos chamar esta função do Java:" #: src/android/interoperability/java.md:45 msgid "_interoperability/java/HelloWorld.java_:" -msgstr "_interoperabilage/java/HelloWorld.java_:" +msgstr "_interoperability/java/HelloWorld.java_:" #: src/android/interoperability/java.md:47 msgid "" @@ -15300,8 +15768,8 @@ msgid "" " private static native String hello(String name);" msgstr "" "```java\n" -"classe AlôMundo {\n" -" private static nativo String hello(String name);" +"classe HelloWorld{\n" +" private static native String hello(String name);" #: src/android/interoperability/java.md:51 msgid "" @@ -15324,7 +15792,7 @@ msgid "" msgstr "" " public static void main(String[] args) {\n" " String output = HelloWorld.hello(\"Alice\");\n" -" System.out.println(saída);\n" +" System.out.println(output);\n" " }\n" "}\n" "```" @@ -15344,7 +15812,7 @@ msgstr "" "java_binary {\n" " name: \"helloworld_jni\",\n" " srcs: [\"HelloWorld.java\"],\n" -" main_class: \"OláMundo\",\n" +" main_class: \"HelloWorld\",\n" " necessário: [\"libhello_jni\"],\n" "}\n" "```" @@ -15372,8 +15840,8 @@ 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:" msgstr "" -"No último exercício, veremos um dos projetos com os quais você trabalha. let-nos\n" -"agrupe-se e faça isso juntos. Algumas sugestões:" +"No último exercício, veremos um dos projetos com os quais você trabalha. Chamem-nos\n" +"agrupem-se e façam isso juntos. Algumas sugestões:" #: src/exercises/day-4/afternoon.md:6 msgid "* Call your AIDL service with a client written in Rust." @@ -15388,8 +15856,8 @@ msgid "" "No solution is provided here since this is open-ended: it relies on someone in\n" "the class having a piece of code which you can turn in to Rust on the fly." msgstr "" -"Nenhuma solução é fornecida aqui, pois isso é aberto: depende de alguém em\n" -"a classe tendo um pedaço de código que você pode transformar em Rust em tempo real." +"Nenhuma solução é fornecida aqui, pois isso é aberto: depende de você ter\n" +"uma classe tendo um pedaço de código que você pode transformar em Rust em tempo real." #: src/thanks.md:1 msgid "# Thanks!" @@ -15401,7 +15869,7 @@ msgid "" "was useful." msgstr "" "_Obrigado por fazer o Comprehensive Rust 🦀!_ Esperamos que tenha gostado e que\n" -"foi útil." +"tenha sido útil." #: src/thanks.md:6 msgid "" @@ -15414,19 +15882,19 @@ msgstr "" "Nós nos divertimos muito montando o curso. O curso não é perfeito,\n" "portanto, se você identificou algum erro ou tem ideias para melhorias, entre em\n" "[entre em contato conosco em\n" -"GitHub](https://github.com/google/comprehensive-rust/discussions). nós adoraríamos\n" -"ouvir de você." +"GitHub](https://github.com/google/comprehensive-rust/discussions). Nós adoraríamos\n" +"ouvir você." #: src/other-resources.md:1 msgid "# Other Rust Resources" -msgstr "# Outros recursos de rust" +msgstr "# Outros recursos de Rust" #: src/other-resources.md:3 msgid "" "The Rust community has created a wealth of high-quality and free resources\n" "online." msgstr "" -"A comunage Rust criou uma riqueza de recursos gratuitos e de alta qualage\n" +"A comunidade Rust tem abundância de recursos gratuitos e de alta qualidade\n" "on-line." #: src/other-resources.md:6 @@ -15452,14 +15920,14 @@ msgid "" " which describes the Rust grammar and memory model." msgstr "" "* [A Linguagem de Programação Rust](https://doc.rust-lang.org/book/): o\n" -" livro gratuito canônico sobre Rust. Abrange o idioma em detalhes e inclui um\n" -" poucos projetos para as Persons construírem.\n" -"* [Rust By Example](https://doc.rust-lang.org/rust-by-example/): abrange o Rust\n" -" sintaxe por meio de uma série de exemplos que mostram diferentes construções. As vezes\n" -" inclui pequenos exercícios onde você é solicitado a expandir o código no\n" +" livro gratuito canônico sobre Rust. Abrange o idioma em detalhes e inclui alguns\n" +" projetos para as pessoas construírem.\n" +"* [Rust By Example](https://doc.rust-lang.org/rust-by-example/): abrange a sintaxe de Rust\n" +" por meio de uma série de exemplos que mostram diferentes construções. As vezes\n" +" inclui pequenos exercícios onde você é solicitado a expandir o código dos\n" " exemplos.\n" -"* [Rust Standard Library](https://doc.rust-lang.org/std/): documentação completa de\n" -" a biblioteca padrão para Rust.\n" +"* [Rust Standard Library](https://doc.rust-lang.org/std/): documentação completa da\n" +" biblioteca padrão para Rust.\n" "* [The Rust Reference](https://doc.rust-lang.org/reference/): um livro incompleto\n" " que descreve a gramática Rust e o modelo de memória." @@ -15479,12 +15947,12 @@ msgid "" " introduction to using Rust on embedded devices without an operating system." msgstr "" "* [O Rustonomicon](https://doc.rust-lang.org/nomicon/): cobre Rust inseguro,\n" -" incluindo trabalhar com ponteiros brutos e fazer interface com outros idiomas\n" +" incluindo trabalhar com ponteiros brutos e fazer interface com outras linguagens\n" " (FFI).\n" "* [Programação assíncrona em Rust](https://rust-lang.github.io/async-book/):\n" " abrange o novo modelo de programação assíncrona que foi introduzido após o\n" -" Rust Book foi escrito.\n" -"* [The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/): um\n" +" Rust Book ser escrito.\n" +"* [The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/): uma\n" " introdução ao uso do Rust em dispositivos embarcados sem um sistema operacional." #: src/other-resources.md:33 @@ -15521,24 +15989,23 @@ msgid "" msgstr "" "* [Aprenda Rust da maneira perigosa](http://cliffle.com/p/dangerust/): cobre Rust\n" " da perspectiva de programadores C de baixo nível.\n" -"* [Rust for Embedded C\n" -" Programadores](https://docs.opentitan.org/doc/ug/rust_for_c/): cobre Rust de\n" -" a perspectiva dos desenvolvedores que escrevem firmware em C.\n" +"* [Rust para Programadores Embedded C](https://docs.opentitan.org/doc/ug/rust_for_c/):\n" +" cobre Rust da perspectiva dos desenvolvedores que escrevem firmware em C.\n" "* [Rust para profissionais](https://overexact.com/rust-for-professionals/):\n" " cobre a sintaxe do Rust usando comparações lado a lado com outras linguagens\n" " como C, C++, Java, JavaScript e Python.\n" "* [Rust on Exercism](https://exercism.org/tracks/rust): mais de 100 exercícios para ajudar\n" " você aprende Rust.\n" "* [Ensino Ferroso\n" -" Material](https://ferrous-systems.github.io/teaching-material/index.html): a\n" -" série de pequenas apresentações abrangendo tanto a parte básica quanto a avançada do\n" -" Linguagem de rust. Outros tópicos como WebAssembly e async/await também são\n" -" abordado.\n" +" Material](https://ferrous-systems.github.io/teaching-material/index.html): uma\n" +" série de pequenas apresentações abrangendo tanto a parte básica quanto a avançada da\n" +" Linguagem Rust. Outros tópicos como WebAssembly e async/await também são\n" +" abordados.\n" "* [Série Iniciante a\n" " Rust](https://docs.microsoft.com/en-us/shows/beginners-series-to-rust/) e\n" " [Dê seus primeiros passos com\n" " Rust](https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/): dois\n" -" Rust guias voltados para novos desenvolvedores. O primeiro é um conjunto de 35 vídeos e o\n" +" guias Rust voltados para novos desenvolvedores. O primeiro é um conjunto de 35 vídeos e o\n" " o segundo é um conjunto de 11 módulos que cobrem a sintaxe Rust e as construções básicas." #: src/other-resources.md:59 @@ -15560,16 +16027,16 @@ msgid "" "resources." msgstr "" "O material aqui se baseia em muitas fontes excelentes de documentação do Rust.\n" -"Consulte a página em [outros recursos](outros-recursos.md) para obter uma lista completa de recursos úteis\n" -"Recursos." +"Consulte a página em [outros recursos](other-resources.md) para obter uma lista completa de recursos úteis\n" +"." #: src/credits.md:7 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 "" -"O material do Comprehensive Rust é licenciado sob os termos do Apache 2.0\n" -"licença, consulte [`LICENSE`](../LICENSE) para obter detalhes." +"O material do Comprehensive Rust é licenciado sob os termos da licença Apache 2.0\n" +", consulte [`LICENSE`](../LICENSE) para obter detalhes." #: src/credits.md:10 msgid "## Rust by Example" @@ -15584,8 +16051,8 @@ msgid "" msgstr "" "Alguns exemplos e exercícios foram copiados e adaptados de [Rust by\n" "Exemplo](https://doc.rust-lang.org/rust-by-example/). por favor veja o\n" -"diretório `third_party/rust-by-example/` para detalhes, incluindo a licença\n" -"termos." +"diretório `third_party/rust-by-example/` para detalhes, incluindo os termos de\n" +"licença." #: src/credits.md:17 msgid "## Rust on Exercism" @@ -15600,8 +16067,8 @@ msgid "" msgstr "" "Alguns exercícios foram copiados e adaptados de [Rust on\n" "Exercism](https://exercism.org/tracks/rust). por favor veja o\n" -"diretório `third_party/rust-on-exercism/` para obter detalhes, incluindo a licença\n" -"termos." +"diretório `third_party/rust-on-exercism/` para obter detalhes, incluindo os termos\n" +"licença." #: src/credits.md:24 msgid "## CXX" @@ -15613,7 +16080,7 @@ msgid "" "image from [CXX](https://cxx.rs/). Please see the `third_party/cxx/` directory\n" "for details, including the license terms." msgstr "" -"A seção [Interoperability with C++](android/interoperability/cpp.md) usa um\n" +"A seção [Interoperability with C++](android/interoperability/cpp.md) usa uma\n" "imagem de [CXX](https://cxx.rs/). Consulte o diretório `third_party/cxx/`\n" "para obter detalhes, incluindo os termos da licença." @@ -15641,8 +16108,8 @@ msgid "" "> comments you see in the solutions. They are there to make it possible to\n" "> re-use parts of the solutions as the exercises." msgstr "" -"> **Nota:** Ignore `// ANCHOR: label` e `// ANCHOR_END: label`\n" -"> comentários que você vê nas soluções. Eles estão lá para tornar possível\n" +"> **Nota:** Ignore os comentários `// ANCHOR: label` e `// ANCHOR_END: label`\n" +"> que você vê nas soluções. Eles estão lá para tornar possível\n" "> reutilizar partes das soluções como exercícios." #: src/exercises/day-1/solutions-morning.md:1 @@ -15651,7 +16118,7 @@ msgstr "# Dia 1 Exercícios matinais" #: src/exercises/day-1/solutions-morning.md:3 msgid "## Arrays and `for` Loops" -msgstr "## Arrays e loops `for`" +msgstr "## Vetores e laços `for`" #: src/exercises/day-1/solutions-morning.md:5 msgid "([back to exercise](for-loops.md))" @@ -15707,15 +16174,15 @@ msgid "" "}" msgstr "" "// ANCHOR: transpose\n" -"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" +"fn transposta(matriz: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" " // ANCHOR_END: transpose\n" -" let mut result = [[0; 3]; 3];\n" +" let mut resultado = [[0; 3]; 3];\n" " for i in 0..3 {\n" " for j in 0..3 {\n" -" result[j][i] = matrix[i][j];\n" +" resultado[j][i] = matriz[i][j];\n" " }\n" " }\n" -" return result;\n" +" return resultado;\n" "}" #: src/exercises/day-1/solutions-morning.md:34 @@ -15729,10 +16196,10 @@ msgid "" "}" msgstr "" "// ANCHOR: pretty_print\n" -"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" +"fn impressao_formatada(matriz: &[[i32; 3]; 3]) {\n" " // ANCHOR_END: pretty_print\n" -" for row in matrix {\n" -" println!(\"{row:?}\");\n" +" for linha in matriz {\n" +" println!(\"{linha:?}\");\n" " }\n" "}" @@ -15760,15 +16227,15 @@ msgid "" msgstr "" "// ANCHOR: tests\n" "#[test]\n" -"fn test_transpose() {\n" -" let matrix = [\n" +"fn test_transposta() {\n" +" let matriz = [\n" " [101, 102, 103], //\n" " [201, 202, 203],\n" " [301, 302, 303],\n" " ];\n" -" let transposed = transpose(matrix);\n" +" let matriz_transposta = transposta(matriz);\n" " assert_eq!(\n" -" transposed,\n" +" matriz_transposta,\n" " [\n" " [101, 201, 301], //\n" " [102, 202, 302],\n" @@ -15779,7 +16246,6 @@ msgstr "" "// ANCHOR_END: tests" #: src/exercises/day-1/solutions-morning.md:62 -#, fuzzy msgid "" "// ANCHOR: main\n" "fn main() {\n" @@ -15791,14 +16257,13 @@ msgid "" msgstr "" "// ANCHOR: main\n" "fn main() {\n" -" let array = [\n" +" let matriz = [\n" " [101, 102, 103], // <-- o comentário faz com que o rustfmt adicione uma nova linha\n" " [201, 202, 203],\n" " [301, 302, 303],\n" " ];" #: src/exercises/day-1/solutions-morning.md:73 -#, fuzzy msgid "" " let transposed = transpose(matrix);\n" " println!(\"transposed:\");\n" @@ -15807,9 +16272,9 @@ msgid "" "```\n" "### Bonus question" msgstr "" -" let transposed = transpose(array);\n" -" println!(\"transposto:\");\n" -" pretty_print(&transposed);\n" +" let matriz_transposta = transposta(matriz);\n" +" println!(\"Transposta:\");\n" +" impressao_formatada(&matriz_transposta);\n" "}\n" "```\n" "### Pergunta bônus" @@ -15820,8 +16285,8 @@ msgid "" "transpose and thus make our function handle any size of matrix. However, this quickly breaks down: the return type cannot " "be `&[&[i32]]` since it needs to own the data you return." msgstr "" -"Sinceramente não funciona tão bem. Pode parecer que poderíamos usar uma slice de slices (`&[&[i32]]`) como o tipo de " -"entrada para transpose e, assim, fazer nossa função lidar com qualquer tamanho de array. No entanto, isso falha " +"Isso necessita a utilização de conceitos mais avançados. Pode parecer que poderíamos usar uma slice de slices (`&[&[i32]]`) como o tipo de " +"entrada para `transposta` e, assim, fazer nossa função lidar com qualquer tamanho de matriz. No entanto, isso falha " "rapidamente: o tipo de retorno não pode ser `&[&[i32]]`, pois ele precisa possuir os dados que você retorna." #: src/exercises/day-1/solutions-morning.md:82 @@ -15830,13 +16295,15 @@ msgid "" "from `Vec>` to `&[&[i32]]` so now you cannot easily use `pretty_print` either." msgstr "" "Você pode tentar usar algo como `Vec>`, mas isso também não funciona muito bem: é difícil converter de " -"`Vec>` para `&[&[i32]] ` então agora você também não pode usar `pretty_print` facilmente." +"`Vec>` para `&[&[i32]] ` então agora você também não pode usar `impressao_formatada` facilmente." #: src/exercises/day-1/solutions-morning.md:84 msgid "" "Once we get to traits and generics, we'll be able to use the [`std::convert::AsRef`][1] trait to abstract over anything " "that can be referenced as a slice." msgstr "" +"Assim que chegarmos aos _traits_ and _generics_, podemos usar o _trait_ [`std::convert::AsRef`][1] para abstrair qualquer coisa\n" +"que pode ser referenciada como um _slice_." #: src/exercises/day-1/solutions-morning.md:86 msgid "" @@ -15863,16 +16330,16 @@ msgid "" " }\n" "}" msgstr "" -"fn pretty_print(matrix: Matrix)\n" +"fn impressao_formatada(matriz: Matriz)\n" "where\n" " T: Debug,\n" -" // A line references a slice of items\n" -" Line: AsRef<[T]>,\n" -" // A matrix references a slice of lines\n" -" Matrix: AsRef<[Line]>\n" +" // Linha referencia uma slice de itens\n" +" Linha: AsRef<[T]>,\n" +" // Matriz referencia uma slice de linhas\n" +" Matriz: AsRef<[Linha]>\n" "{\n" -" for row in matrix.as_ref() {\n" -" println!(\"{:?}\", row.as_ref());\n" +" for linha in matriz.as_ref() {\n" +" println!(\"{:?}\", linha.as_ref());\n" " }\n" "}" @@ -15890,11 +16357,11 @@ msgid "" msgstr "" "fn main() {\n" " // &[&[i32]]\n" -" pretty_print(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" +" impressao_formatada(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" " // [[&str; 2]; 2]\n" -" pretty_print([[\"a\", \"b\"], [\"c\", \"d\"]]);\n" +" impressao_formatada([[\"a\", \"b\"], [\"c\", \"d\"]]);\n" " // Vec>\n" -" pretty_print(vec![vec![1, 2], vec![3, 4]]);\n" +" impressao_formatada(vec![vec![1, 2], vec![3, 4]]);\n" "}\n" "```" @@ -15904,7 +16371,7 @@ msgid "" "an invalid matrix." msgstr "" "Além disso, o próprio tipo não imporia que as slices filhas tenham o mesmo comprimento, portanto, tal variável poderia " -"conter uma array inválida." +"conter uma matriz inválida." #: src/exercises/day-1/solutions-morning.md:115 msgid "[1]: https://doc.rust-lang.org/std/convert/trait.AsRef.html" @@ -15930,8 +16397,8 @@ msgid "" "}" msgstr "" "// ANCHOR: configuração\n" -"struct Library {\n" -" books: Vec,\n" +"struct Biblioteca {\n" +" livros: Vec,\n" "}" #: src/exercises/day-1/solutions-afternoon.md:42 @@ -15945,12 +16412,12 @@ msgid "" "// ANCHOR_END: setup" msgstr "" "// Isso torna possível imprimir valores de livros com {}.\n" -"impl std::fmt::Display for Book {\n" +"impl std::fmt::Display for Livro {\n" " fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n" -" write!(f, \"{} ({})\", self.title, self.year)\n" +" write!(f, \"{} ({})\", self.titulo, self.ano)\n" " }\n" "}\n" -"// ANCHOR_END: setup" +"// ANCHOR_END: Configuração" #: src/exercises/day-1/solutions-afternoon.md:50 msgid "" @@ -15961,15 +16428,14 @@ msgid "" " Library { books: Vec::new() }\n" " }" msgstr "" -"// ANCHOR: Library_new\n" -"impl Library {\n" -" fn new() -> Library {\n" +"impl Biblioteca {\n" +" // ANCHOR: Library_new\n" +" fn new() -> Biblioteca {\n" " // ANCHOR_END: Library_new\n" -" Library { books: Vec::new() }\n" +" Biblioteca { livros: Vec::new() }\n" " }" #: src/exercises/day-1/solutions-afternoon.md:57 -#, fuzzy msgid "" " // ANCHOR: Library_len\n" " //fn len(self) -> usize {\n" @@ -15982,15 +16448,14 @@ msgid "" msgstr "" " // ANCHOR: Library_len\n" " //fn len(self) -> usize {\n" -" // não implementado!()\n" +" // unimplemented!()\n" " ///}\n" " // ANCHOR_END: Library_len\n" -" fn len(&self) -> usize {\n" -" self.books.len()\n" +" fn tamanho(&self) -> usize {\n" +" self.livros.len()\n" " }" #: src/exercises/day-1/solutions-afternoon.md:66 -#, fuzzy msgid "" " // ANCHOR: Library_is_empty\n" " //fn is_empty(self) -> bool {\n" @@ -16003,15 +16468,14 @@ msgid "" msgstr "" " // ANCHOR: Library_is_empty\n" " //fn is_empty(self) -> bool {\n" -" // não implementado!()\n" -" ///}\n" +" // unimplemented!()\n" +" //}\n" " // ANCHOR_END: Library_is_empty\n" -" fn is_empty(&self) -> bool {\n" -" self.books.is_empty()\n" +" fn esta_vazia(&self) -> bool {\n" +" self.livros.is_empty()\n" " }" #: src/exercises/day-1/solutions-afternoon.md:75 -#, fuzzy msgid "" " // ANCHOR: Library_add_book\n" " //fn add_book(self, book: Book) {\n" @@ -16024,15 +16488,14 @@ msgid "" msgstr "" " // ANCHOR: Library_add_book\n" " //fn add_book(self, book: Book) {\n" -" // não implementado!()\n" +" // unimplemented!()\n" " ///}\n" " // ANCHOR_END: Library_add_book\n" -" fn add_book(&mut self, book: Book) {\n" -" self.books.push(book)\n" +" fn adiciona_livro(&mut self, livro: Livro) {\n" +" self.livros.push(livro)\n" " }" #: src/exercises/day-1/solutions-afternoon.md:84 -#, fuzzy msgid "" " // ANCHOR: Library_print_books\n" " //fn print_books(self) {\n" @@ -16047,17 +16510,16 @@ msgid "" msgstr "" " // ANCHOR: Library_print_books\n" " //fn print_books(self) {\n" -" // não implementado!()\n" +" // unimplemented!()\n" " ///}\n" " // ANCHOR_END: Library_print_books\n" -" fn print_books(&self) {\n" -" for book in &self.books {\n" -" println!(\"{}\", book);\n" +" fn imprime_livros(&self) {\n" +" for livro in &self.livros {\n" +" println!(\"{}\", livro);\n" " }\n" " }" #: src/exercises/day-1/solutions-afternoon.md:95 -#, fuzzy msgid "" " // ANCHOR: Library_oldest_book\n" " //fn oldest_book(self) -> Option<&Book> {\n" @@ -16074,8 +16536,8 @@ msgstr "" " // não implementado!()\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" +" fn livro_mais_antigo(&self) -> Option<&Livro> {\n" +" self.livros.iter().min_by_key(|livro| livro.ano)\n" " }\n" "}" @@ -16095,10 +16557,9 @@ msgstr "" "// assinaturas de método, incluindo o parâmetro \"self\"! Você pode\n" "// também precisa atualizar as ligações de variáveis dentro de main.\n" "fn main() {\n" -" let library = Library::new();" +" let mut biblioteca = Biblioteca::new();" #: src/exercises/day-1/solutions-afternoon.md:113 -#, fuzzy msgid "" " //println!(\"Our library is empty: {}\", library.is_empty());\n" " //\n" @@ -16116,19 +16577,19 @@ msgid "" "}\n" "// ANCHOR_END: main" msgstr "" -" //println!(\"Nossa biblioteca está vazia: {}\", library.is_empty());\n" +" //println!(\"Nossa biblioteca está vazia: {}\", biblioteca.esta_vazia());\n" " //\n" -" //library.add_book(Book::new(\"O Senhor dos Anéis\", 1954));\n" -" //library.add_book(Book::new(\"As Aventuras de Alice no País das Maravilhas\", 1865));\n" +" //biblioteca.adiciona_livro(Livro::new(\"O Senhor dos Anéis\", 1954));\n" +" //biblioteca.adiciona_livro(Livro::new(\"As Aventuras de Alice no País das Maravilhas\", 1865));\n" " //\n" -" //library.print_books();\n" +" //biblioteca.imprime_livros();\n" " //\n" -" //corresponde à library.oldest_book() {\n" -" // Some(book) => println!(\"Meu livro mais antigo é {book}\"),\n" +" //match biblioteca.livro_mais_antigo() {\n" +" // Some(livro) => println!(\"Meu livro mais antigo é {livro}\"),\n" " // None => println!(\"Minha biblioteca está vazia!\"),\n" -" ///}\n" +" //}\n" " //\n" -" //println!(\"Nossa biblioteca tem {} livros\", library.len());\n" +" //println!(\"Nossa biblioteca tem {} livros\", biblioteca.tamanho());\n" "}\n" "// ANCHOR_END: main" @@ -16141,10 +16602,10 @@ msgid "" " assert!(library.is_empty());" msgstr "" "#[test]\n" -"fn test_library_len() {\n" -" let mut library = Library::new();\n" -" assert_eq!(library.len(), 0);\n" -" assert!(library.is_empty());" +"fn test_tamanho_biblioteca() {\n" +" let mut biblioteca = Biblioteca::new();\n" +" assert_eq!(biblioteca.tamanho(), 0);\n" +" assert!(biblioteca.esta_vazia());" #: src/exercises/day-1/solutions-afternoon.md:135 msgid "" @@ -16154,10 +16615,10 @@ msgid "" " assert!(!library.is_empty());\n" "}" msgstr "" -" library.add_book(Book::new(\"O Senhor dos Anéis\", 1954));\n" -" library.add_book(Book::new(\"As Aventuras de Alice no País das Maravilhas\", 1865));\n" -" assert_eq!(library.len(), 2);\n" -" assert!(!library.is_empty());\n" +" biblioteca.adiciona_livro(Livro::new(\"O Senhor dos Anéis\", 1954));\n" +" biblioteca.adiciona_livro(Livro::new(\"As Aventuras de Alice no País das Maravilhas\", 1865));\n" +" assert_eq!(biblioteca.tamanho(), 2);\n" +" assert!(!biblioteca.esta_vazia());\n" "}" #: src/exercises/day-1/solutions-afternoon.md:141 @@ -16168,9 +16629,9 @@ msgid "" " assert!(library.is_empty());" msgstr "" "#[test]\n" -"fn test_library_is_empty() {\n" -" let mut library = Library::new();\n" -" assert!(library.is_empty());" +"fn test_biblioteca_esta_vazia() {\n" +" let mut biblioteca = Biblioteca::new();\n" +" assert!(biblioteca.esta_vazia());" #: src/exercises/day-1/solutions-afternoon.md:146 msgid "" @@ -16178,8 +16639,8 @@ msgid "" " assert!(!library.is_empty());\n" "}" msgstr "" -" library.add_book(Book::new(\"O Senhor dos Anéis\", 1954));\n" -" assert!(!library.is_empty());\n" +" biblioteca.adiciona_livro(Livro::new(\"O Senhor dos Anéis\", 1954));\n" +" assert!(!biblioteca.esta_vazia());\n" "}" #: src/exercises/day-1/solutions-afternoon.md:150 @@ -16195,13 +16656,13 @@ msgid "" "}" msgstr "" "#[test]\n" -"fn test_library_print_books() {\n" -" let mut library = Library::new();\n" -" library.add_book(Book::new(\"O Senhor dos Anéis\", 1954));\n" -" library.add_book(Book::new(\"As Aventuras de Alice no País das Maravilhas\", 1865));\n" +"fn test_biblioteca_imprime_livros() {\n" +" let mut biblioteca = Biblioteca::new();\n" +" biblioteca.adiciona_livro(Livro::new(\"O Senhor dos Anéis\", 1954));\n" +" biblioteca.adiciona_livro(Livro::new(\"As Aventuras de Alice no País das Maravilhas\", 1865));\n" " // Poderíamos tentar capturar stdout, mas vamos apenas chamar o\n" " // método para começar.\n" -" library.print_books();\n" +" biblioteca.imprime_livros();\n" "}" #: src/exercises/day-1/solutions-afternoon.md:160 @@ -16212,9 +16673,9 @@ msgid "" " assert!(library.oldest_book().is_none());" msgstr "" "#[test]\n" -"fn test_library_oldest_book() {\n" -" let mut library = Library::new();\n" -" assert!(library.oldest_book().is_none());" +"fn test_biblioteca_livro_mais_antigo() {\n" +" let mut biblioteca = Biblioteca::new();\n" +" assert!(biblioteca.livro_mais_antigo().is_none());" #: src/exercises/day-1/solutions-afternoon.md:165 msgid "" @@ -16224,9 +16685,9 @@ msgid "" " Some(\"Lord of the Rings\")\n" " );" msgstr "" -" library.add_book(Book::new(\"O Senhor dos Anéis\", 1954));\n" +" biblioteca.adiciona_livro(Livro::new(\"O Senhor dos Anéis\", 1954));\n" " assert_eq!(\n" -" library.oldest_book().map(|b| b.title.as_str()),\n" +" biblioteca.livro_mais_antigo().map(|b| b.titulo.as_str()),\n" " Some(\"O Senhor dos Anéis\")\n" " );" @@ -16240,9 +16701,9 @@ msgid "" "}\n" "```" msgstr "" -" library.add_book(Book::new(\"As Aventuras de Alice no País das Maravilhas\", 1865));\n" +" biblioteca.adiciona_livro(Livro::new(\"As Aventuras de Alice no País das Maravilhas\", 1865));\n" " assert_eq!(\n" -" library.oldest_book().map(|b| b.title.as_str()),\n" +" biblioteca.livro_mais_antigo().map(|b| b.titulo.as_str()),\n" " Some(\"As Aventuras de Alice no País das Maravilhas\")\n" " );\n" "}\n" @@ -16254,7 +16715,7 @@ msgstr "# Dia 2 Exercícios matinais" #: src/exercises/day-2/solutions-morning.md:3 msgid "## Points and Polygons" -msgstr "## Points e Polígonos" +msgstr "## Pontos e Polígonos" #: src/exercises/day-2/solutions-morning.md:5 msgid "([back to exercise](points-polygons.md))" @@ -16272,7 +16733,7 @@ msgid "" msgstr "" "#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" "// ANCHOR: Point\n" -"pub struct Point {\n" +"pub struct Ponto {\n" " // ANCHOR_END: Point\n" " x: i32,\n" " y: i32,\n" @@ -16288,10 +16749,10 @@ msgid "" " }" msgstr "" "// ANCHOR: Point-impl\n" -"impl Point {\n" +"impl Ponto {\n" " // ANCHOR_END: Point-impl\n" -" pub fn new(x: i32, y: i32) -> Point {\n" -" Point { x, y }\n" +" pub fn new(x: i32, y: i32) -> Ponto {\n" +" Ponto { x, y }\n" " }" #: src/exercises/day-2/solutions-morning.md:37 @@ -16311,8 +16772,8 @@ msgid "" " }\n" "}" msgstr "" -" pub fn dist(self, other: Point) -> f64 {\n" -" (self - other).magnitude()\n" +" pub fn dist(self, outro: Ponto) -> f64 {\n" +" (self - outro).magnitude()\n" " }\n" "}" @@ -16326,10 +16787,10 @@ msgid "" " }\n" "}" msgstr "" -" fn add(self, other: Self) -> Self::Output {\n" +" fn add(self, outro: Self) -> Self::Output {\n" " Self {\n" -" x: self.x + other.x,\n" -" y: self.y + other.y,\n" +" x: self.x + outro.x,\n" +" y: self.y + outro.y,\n" " }\n" " }\n" "}" @@ -16339,7 +16800,7 @@ msgid "" "impl std::ops::Sub for Point {\n" " type Output = Self;" msgstr "" -"impl std::ops::Sub for Point {\n" +"impl std::ops::Sub for Ponto {\n" " type Output = Self;" #: src/exercises/day-2/solutions-morning.md:60 @@ -16352,10 +16813,10 @@ msgid "" " }\n" "}" msgstr "" -" fn sub(self, other: Self) -> Self::Output {\n" +" fn sub(self, outro: Self) -> Self::Output {\n" " Self {\n" -" x: self.x - other.x,\n" -" y: self.y - other.y,\n" +" x: self.x - outro.x,\n" +" y: self.y - outro.y,\n" " }\n" " }\n" "}" @@ -16369,9 +16830,9 @@ msgid "" "}" msgstr "" "// ANCHOR: Polygon\n" -"pub struct Polygon {\n" +"pub struct Poligono {\n" " // ANCHOR_END: Polygon\n" -" points: Vec,\n" +" pontos: Vec,\n" "}" #: src/exercises/day-2/solutions-morning.md:74 @@ -16384,10 +16845,9 @@ msgid "" " }" msgstr "" "// ANCHOR: Polygon-impl\n" -"impl Polygon {\n" -" // ANCHOR_END: Polygon-impl\n" -" pub fn new() -> Polygon {\n" -" Polygon { points: Vec::new() }\n" +"impl Poligono {\n" +" pub fn new() -> Poligono {\n" +" Poligono { pontos: Vec::new() }\n" " }" #: src/exercises/day-2/solutions-morning.md:81 @@ -16396,8 +16856,8 @@ msgid "" " self.points.push(point);\n" " }" msgstr "" -" pub fn add_point(&mut self, point: Point) {\n" -" self.points.push(point);\n" +" pub fn adiciona_ponto(&mut self, ponto: Ponto) {\n" +" self.pontos.push(ponto);\n" " }" #: src/exercises/day-2/solutions-morning.md:85 @@ -16406,8 +16866,8 @@ msgid "" " self.points.iter().min_by_key(|p| p.x).copied()\n" " }" msgstr "" -" pub fn left_most_point(&self) -> Option {\n" -" self.points.iter().min_by_key(|p| p.x).copied()\n" +" pub fn ponto_mais_a_esquerda(&self) -> Option {\n" +" self.pontos.iter().min_by_key(|p| p.x).copied()\n" " }" #: src/exercises/day-2/solutions-morning.md:89 @@ -16416,8 +16876,8 @@ msgid "" " self.points.iter()\n" " }" msgstr "" -" pub fn iter(&self) -> impl Iterator {\n" -" self.points.iter()\n" +" pub fn iter(&self) -> impl Iterator {\n" +" self.pontos.iter()\n" " }" #: src/exercises/day-2/solutions-morning.md:93 @@ -16427,8 +16887,8 @@ msgid "" " return 0.0;\n" " }" msgstr "" -" pub fn length(&self) -> f64 {\n" -" if self.points.is_empty() {\n" +" pub fn comprimento(&self) -> f64 {\n" +" if self.pontos.is_empty() {\n" " return 0.0;\n" " }" @@ -16445,14 +16905,14 @@ msgid "" " }\n" "}" msgstr "" -" let mut result = 0.0;\n" -" let mut last_point = self.points[0];\n" -" for point in &self.points[1..] {\n" -" result += last_point.dist(*point);\n" -" last_point = *point;\n" +" let mut resultado = 0.0;\n" +" let mut ultimo_ponto = self.pontos[0];\n" +" for ponto in &self.pontos[1..] {\n" +" resultado += ultimo_ponto.dist(*ponto);\n" +" ultimo_ponto = *ponto;\n" " }\n" -" result += last_point.dist(self.points[0]);\n" -" result\n" +" resultado += ultimo_ponto.dist(self.pontos[0]);\n" +" resultado\n" " }\n" "}" @@ -16466,14 +16926,13 @@ msgid "" "}" msgstr "" "// ANCHOR: Circle\n" -"pub struct Circle {\n" +"pub struct Circulo {\n" " // ANCHOR_END: Circle\n" -" center: Point,\n" -" radius: i32,\n" +" centro: Ponto,\n" +" raio: i32,\n" "}" #: src/exercises/day-2/solutions-morning.md:116 -#, fuzzy msgid "" "// ANCHOR: Circle-impl\n" "impl Circle {\n" @@ -16483,25 +16942,22 @@ msgid "" " }" msgstr "" "// ANCHOR: Circle-impl\n" -"impl Círculo {\n" -" // ANCHOR_END: Implantação do círculo\n" -" pub fn new(center: Point, radius: i32) -> Circle {\n" -" Círculo { centro, raio }\n" +"impl Circulo {\n" +" pub fn new(centro: Ponto, raio: i32) -> Circulo {\n" +" Circulo { centro, raio }\n" " }" #: src/exercises/day-2/solutions-morning.md:123 -#, fuzzy msgid "" " pub fn circumference(&self) -> f64 {\n" " 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" " }" msgstr "" -" pub fn circunferência(&self) -> f64 {\n" -" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +" pub fn circunferencia(&self) -> f64 {\n" +" 2.0 * std::f64::consts::PI * f64::from(self.raio)\n" " }" #: src/exercises/day-2/solutions-morning.md:127 -#, fuzzy msgid "" " pub fn dist(&self, other: &Self) -> f64 {\n" " self.center.dist(other.center)\n" @@ -16509,7 +16965,7 @@ msgid "" "}" msgstr "" " pub fn dist(&self, outro: &Self) -> f64 {\n" -" self.center.dist(outro.centro)\n" +" self.centro.dist(outro.centro)\n" " }\n" "}" @@ -16523,9 +16979,9 @@ msgid "" "// ANCHOR_END: Shape" msgstr "" "// ANCHOR: Shape\n" -"pub enum Shape {\n" -" Polygon(Polygon),\n" -" Circle(Circle),\n" +"pub enum Forma {\n" +" Poligono(Poligono),\n" +" Circulo(Circulo),\n" "}\n" "// ANCHOR_END: Shape" @@ -16537,9 +16993,9 @@ msgid "" " }\n" "}" msgstr "" -"impl From for Shape {\n" -" fn from(poly: Polygon) -> Self {\n" -" Shape:: Polygon (poly)\n" +"impl From for Forma {\n" +" fn from(poli: Poligono) -> Self {\n" +" Forma::Poligono(poli)\n" " }\n" "}" @@ -16551,9 +17007,9 @@ msgid "" " }\n" "}" msgstr "" -"impl From for Shape {\n" -" fn from(circle: Circle) -> Self {\n" -" Shape::Circle(circle)\n" +"impl From for Forma {\n" +" fn from(circulo: Circulo) -> Self {\n" +" Forma::Circulo(circulo)\n" " }\n" "}" @@ -16568,11 +17024,11 @@ msgid "" " }\n" "}" msgstr "" -"impl Shape {\n" -" pub fn perimeter(&self) -> f64 {\n" +"impl Forma {\n" +" pub fn perimetro(&self) -> f64 {\n" " match self {\n" -" Shape::Polygon(poly) => poly.length(),\n" -" Shape::Circle(circle) => circle.circumference(),\n" +" Forma::Poligono(poli) => poli.comprimento(),\n" +" Forma::Circulo(circulo) => circulo.circunferencia(),\n" " }\n" " }\n" "}" @@ -16612,21 +17068,21 @@ msgid "" "// ANCHOR_END: unit-tests" msgstr "" " #[test]\n" -" fn test_shape_perimeters() {\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(Point::new(12, 13));\n" -" poly.add_point(Point::new(17, 11));\n" -" poly.add_point(Point::new(16, 16));\n" -" let shapes = vec![\n" -" Shape::from(poly),\n" -" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" fn test_forma_perimetros() {\n" +" let mut poli = Poligono::new();\n" +" poli.adiciona_ponto(Ponto::new(12, 13));\n" +" poli.adiciona_ponto(Ponto::new(17, 11));\n" +" poli.adiciona_ponto(Ponto::new(16, 16));\n" +" let formas = vec![\n" +" Forma::from(poli),\n" +" Forma::from(Circulo::new(Ponto::new(10, 20), 5)),\n" " ];\n" -" let perimeters = shapes\n" +" let perimetros = formas\n" " .iter()\n" -" .map(Shape::perimeter)\n" -" .map(round_two_digits)\n" +" .map(Forma::perimetro)\n" +" .map(arredonda_dois_digitos)\n" " .collect::>();\n" -" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" assert_eq!(perimetros, vec![15.48, 31.42]);\n" " }\n" "}\n" "// ANCHOR_END: unit-tests" @@ -16675,20 +17131,20 @@ msgid "" " }" msgstr "" "// ANCHOR: luhn\n" -"pub fn luhn(cc_number: &str) -> bool {\n" +"pub fn luhn(numero_cc: &str) -> bool {\n" " // ANCHOR_END: luhn\n" -" let mut digits_seen = 0;\n" -" let mut sum = 0;\n" -" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ').enumerate() {\n" +" let mut digitos_vistos = 0;\n" +" let mut soma = 0;\n" +" for (i, ch) in numero_cc.chars().rev().filter(|&ch| ch != ' ').enumerate() {\n" " match ch.to_digit(10) {\n" " Some(d) => {\n" -" sum += if i % 2 == 1 {\n" +" soma += if i % 2 == 1 {\n" " let dd = d * 2;\n" " dd / 10 + dd % 10\n" " } else {\n" " d\n" " };\n" -" digits_seen += 1;\n" +" digitos_vistos += 1;\n" " }\n" " None => return false,\n" " }\n" @@ -16700,7 +17156,7 @@ msgid "" " return false;\n" " }" msgstr "" -" if digits_seen < 2 {\n" +" if digitos_vistos < 2 {\n" " return false;\n" " }" @@ -16709,7 +17165,7 @@ msgid "" " sum % 10 == 0\n" "}" msgstr "" -" sum % 10 == 0\n" +" soma % 10 == 0\n" "}" #: src/exercises/day-2/solutions-afternoon.md:49 @@ -16724,11 +17180,11 @@ msgid "" "}" msgstr "" "fn main() {\n" -" let cc_number = \"1234 5678 1234 5670\";\n" +" let numero_cc = \"1234 5678 1234 5670\";\n" " println!(\n" -" \"Is {} a valid credit card number? {}\",\n" -" cc_number,\n" -" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" +" \"{} é um número de cartão de crédito válido? {}\",\n" +" numero_cc,\n" +" if luhn(numero_cc) { \"Sim\" } else { \"Não\" }\n" " );\n" "}" @@ -16742,7 +17198,7 @@ msgid "" msgstr "" "// ANCHOR: unit-tests\n" "#[test]\n" -"fn test_non_digit_cc_number() {\n" +"fn test_numero_cc_nao_numerico() {\n" " assert!(!luhn(\"foo\"));\n" "}" @@ -16758,7 +17214,7 @@ msgid "" "```" msgstr "" "#[test]\n" -"fn test_invalid_cc_number() {\n" +"fn test_numero_cc_invalido() {\n" " assert!(!luhn(\"4223 9826 4026 9299\"));\n" " assert!(!luhn(\"4539 3195 0343 6476\"));\n" " assert!(!luhn(\"8273 1232 7352 0569\"));\n" @@ -16786,10 +17242,10 @@ msgid "" " .chain(std::iter::once(None));" msgstr "" "// ANCHOR: prefix_matches\n" -"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" -" // ANCHOR_END: prefix_matches\n" -" let prefixes = prefix.split('/');\n" -" let request_paths = request_path\n" +"pub fn correspondencia_prefixo(prefixo: &str, caminho_requisitado: &str) -> bool {\n" +"// ANCHOR_END: prefix_matches\n" +" let prefixos = prefixo.split('/');\n" +" let caminhos_requisitados = caminho_requisitado\n" " .split('/')\n" " .map(|p| Some(p))\n" " .chain(std::iter::once(None));" @@ -16809,10 +17265,10 @@ msgid "" " true\n" "}" msgstr "" -" for (prefix, request_path) in prefixes.zip(request_paths) {\n" -" match request_path {\n" -" Some(request_path) => {\n" -" if (prefix != \"*\") && (prefix != request_path) {\n" +" for (prefixo, caminho_requisitado) in prefixos.zip(caminhos_requisitados) {\n" +" match caminho_requisitado {\n" +" Some(caminho_requisitado) => {\n" +" if (prefixo != \"*\") && (prefixo != caminho_requisitado) {\n" " return false;\n" " }\n" " }\n" @@ -16834,9 +17290,9 @@ msgstr "" "// ANCHOR: unit-tests\n" "#[test]\n" "fn test_matches_without_wildcard() {\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" +" assert!(correspondencia_prefixo(\"/v1/publishers\", \"/v1/publishers\"));\n" +" assert!(correspondencia_prefixo(\"/v1/publishers\", \"/v1/publishers/abc-123\"));\n" +" assert!(correspondencia_prefixo(\"/v1/publishers\", \"/v1/publishers/abc/books\"));" #: src/exercises/day-2/solutions-afternoon.md:166 msgid "" @@ -16848,8 +17304,8 @@ msgid "" "}\n" "// ANCHOR_END: unit-tests" msgstr "" -" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" -" assert!(!prefix_matches(\n" +" assert!(!correspondencia_prefixo(\"/v1/publishers/*/books\", \"/v1/publishers\"));\n" +" assert!(!correspondencia_prefixo(\n" " \"/v1/publishers/*/books\",\n" " \"/v1/publishers/foo/booksByAuthor\"\n" " ));\n" @@ -16866,7 +17322,7 @@ msgstr "## Uma biblioteca GUI simples" #: src/exercises/day-3/solutions-morning.md:5 msgid "([back to exercise](simple-gui.md))" -msgstr "([voltar ao exercício](simples-gui.md))" +msgstr "([voltar ao exercício](simple-gui.md))" #: src/exercises/day-3/solutions-morning.md:22 msgid "" @@ -17047,7 +17503,6 @@ msgstr "" "}" #: src/exercises/day-3/solutions-morning.md:157 -#, fuzzy msgid "" "// ANCHOR: main\n" "fn main() {\n" @@ -17066,7 +17521,7 @@ msgstr "" "fn main() {\n" " let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" " window.add_widget(Box::new(Label::new(\"Esta é uma pequena demonstração de GUI de texto.\")));\n" -" window.add_widget(Caixa::new(Botão::new(\n" +" window.add_widget(Box::new(Button::new(\n" " \"Clique em mim!\",\n" " Box::new(|| println!(\"Você clicou no botão!\")),\n" " )));\n" @@ -17081,7 +17536,7 @@ msgstr "# Dia 3 Exercícios da Tarde" #: src/exercises/day-3/solutions-afternoon.md:3 msgid "## Safe FFI Wrapper" -msgstr "## Invólucro FFI Seguro" +msgstr "## Wrapper FFI Seguro" #: src/exercises/day-3/solutions-afternoon.md:5 msgid "([back to exercise](safe-ffi-wrapper.md))" @@ -17138,11 +17593,11 @@ msgstr "" " // Call opendir and return a Ok value if that worked,\n" " // otherwise return Err with a message.\n" " // ANCHOR_END: DirectoryIterator\n" -" let path = CString::new(path).map_err(|err| format!(\"Invalid path: {err}\"))?;\n" +" let path = CString::new(path).map_err(|err| format!(\"Caminho inválido: {err}\"))?;\n" " // SAFETY: path.as_ptr() cannot be NULL.\n" " let dir = unsafe { ffi::opendir(path.as_ptr()) };\n" " if dir.is_null() {\n" -" Err(format!(\"Could not open {:?}\", path))\n" +" Err(format!(\"Não foi possível abrir {:?}\", path))\n" " } else {\n" " Ok(DirectoryIterator { path, dir })\n" " }\n" @@ -17215,7 +17670,7 @@ msgstr "" " if !self.dir.is_null() {\n" " // SAFETY: self.dir is not NULL.\n" " if unsafe { ffi::closedir(self.dir) } != 0 {\n" -" panic!(\"Could not close {:?}\", self.path);\n" +" panic!(\"Não foi possível fechar {:?}\", self.path);\n" " }\n" " }\n" " }\n" @@ -17235,7 +17690,7 @@ msgstr "" "// ANCHOR: main\n" "fn main() -> Result<(), String> {\n" " let iter = DirectoryIterator::new(\".\")?;\n" -" println!(\"files: {:#?}\", iter.collect::>());\n" +" println!(\"Arquivos: {:#?}\", iter.collect::>());\n" " Ok(())\n" "}\n" "// ANCHOR_END: main\n" @@ -17247,7 +17702,7 @@ msgstr "# Dia 4 Exercício matinal" #: src/exercises/day-4/solutions-morning.md:3 msgid "## Dining Philosophers" -msgstr "## Jantar com Filósofos" +msgstr "## Filósofos jantando" #: src/exercises/day-4/solutions-morning.md:5 msgid "([back to exercise](dining-philosophers.md))" @@ -17277,12 +17732,12 @@ msgid "" " thoughts: mpsc::SyncSender,\n" "}" msgstr "" -"struct Philosopher {\n" -" name: String,\n" +"struct Filosofo {\n" +" nome: String,\n" " // ANCHOR_END: Philosopher\n" -" left_fork: Arc>,\n" -" right_fork: Arc>,\n" -" thoughts: mpsc::SyncSender,\n" +" garfo_esquerda: Arc>,\n" +" garfo_direita: Arc>,\n" +" pensamentos: mpsc::SyncSender,\n" "}" #: src/exercises/day-4/solutions-morning.md:38 @@ -17297,10 +17752,10 @@ msgid "" " // ANCHOR_END: Philosopher-think" msgstr "" "// ANCHOR: Philosopher-think\n" -"impl Philosopher {\n" -" fn think(&self) {\n" -" self.thoughts\n" -" .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" +"impl Filosofo {\n" +" fn pensar(&self) {\n" +" self.pensamentos\n" +" .send(format!(\"Eureka! {} teve uma nova ideia!\", &self.nome))\n" " .unwrap();\n" " }\n" " // ANCHOR_END: Philosopher-think" @@ -17315,11 +17770,11 @@ msgid "" " let right = self.right_fork.lock().unwrap();" msgstr "" " // ANCHOR: Philosopher-eat\n" -" fn eat(&self) {\n" +" fn comer(&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();" +" println!(\"{} está tentando comer\", &self.nome);\n" +" let _esquerda = self.garfo_esquerda.lock().unwrap();\n" +" let _direita = self.garfo_direita.lock().unwrap();" #: src/exercises/day-4/solutions-morning.md:54 msgid "" @@ -17330,7 +17785,7 @@ msgid "" "}" msgstr "" " // ANCHOR: Philosopher-eat-end\n" -" println!(\"{} is eating...\", &self.name);\n" +" println!(\"{} está comendo...\", &self.nome);\n" " thread::sleep(Duration::from_millis(10));\n" " }\n" "}" @@ -17351,8 +17806,8 @@ msgid "" " .map(|_| Arc::new(Mutex::new(Fork)))\n" " .collect::>();" msgstr "" -" let forks = (0..PHILOSOPHERS.len())\n" -" .map(|_| Arc::new(Mutex::new(Fork)))\n" +" let garfos = (0..FILOSOFOS.len())\n" +" .map(|_| Arc::new(Mutex::new(Garfo)))\n" " .collect::>();" #: src/exercises/day-4/solutions-morning.md:71 @@ -17362,10 +17817,10 @@ msgid "" " let mut left_fork = forks[i].clone();\n" " let mut right_fork = forks[(i + 1) % forks.len()].clone();" msgstr "" -" for i in 0..forks.len() {\n" +" for i in 0..garfos.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();" +" let mut garfo_esquerda = garfos[i].clone();\n" +" let mut garfo_direita = garfos[(i + 1) % garfos.len()].clone();" #: src/exercises/day-4/solutions-morning.md:76 msgid "" @@ -17379,8 +17834,8 @@ msgstr "" " // Para evitar um impasse, temos que quebrar a simetria\n" " // algum lugar. Isso irá trocar os garfos sem desinicializar\n" " // qualquer um deles.\n" -" if i == forks.len() - 1 {\n" -" std::mem::swap(&mut left_fork, &mut right_fork);\n" +" if i == garfos.len() - 1 {\n" +" std::mem::swap(&mut garfo_esquerda, &mut garfo_direita);\n" " }" #: src/exercises/day-4/solutions-morning.md:83 @@ -17392,11 +17847,11 @@ msgid "" " right_fork,\n" " };" msgstr "" -" let philosopher = Philosopher {\n" -" name: PHILOSOPHERS[i].to_string(),\n" -" thoughts: tx,\n" -" left_fork,\n" -" right_fork,\n" +" let filosofo = Filosofo {\n" +" nome: FILOSOFOS[i].to_string(),\n" +" pensamentos: tx,\n" +" garfo_esquerda,\n" +" garfo_direita,\n" " };" #: src/exercises/day-4/solutions-morning.md:90 @@ -17411,8 +17866,8 @@ msgid "" msgstr "" " thread::spawn(move || {\n" " for _ in 0..100 {\n" -" philosopher.eat();\n" -" philosopher.think();\n" +" filosofo.comer();\n" +" filosofo.pensar();\n" " }\n" " });\n" " }" @@ -17427,8 +17882,8 @@ msgid "" "```" msgstr "" " drop(tx);\n" -" for thought in rx {\n" -" println!(\"{thought}\");\n" +" for pensamento in rx {\n" +" println!(\"{pensamento}\");\n" " }\n" "}\n" "```" @@ -17439,3 +17894,4 @@ msgstr "" #~ msgstr "" #~ "* `Box` é como `std::unique_ptr` em C++.\n" #~ "* No exemplo acima, você pode até deixar de fora o `*` na declaração `println!` graças a `Deref`." + diff --git a/po/uz.po b/po/uz.po index a5f8ab2..3af27e6 100644 --- a/po/uz.po +++ b/po/uz.po @@ -804,8 +804,9 @@ msgid "" "anything\n" "about Rust and hope to:" msgstr "" -"Kurs siz Rust haqida hech narsa bilmasligingizni taxmin qiladi" -"va quyidagi maqsadlarga ega:" +"Kursning maqsadi sizga Rustni o'rgatishdir. Siz Rust haqida hech" +"narsa bilmaysiz deb o'ylaymiz\n" +"va umid qilamizki:" #: src/welcome.md:10 msgid "" @@ -813,13 +814,10 @@ msgid "" "* Enable you to modify existing programs and write new programs in Rust.\n" "* Show you common Rust idioms." msgstr "" -"* Rust sintaksisi va tili haqida har tomonlama tushuncha beradi.\n" -"* Rust-da mavjud dasturlarni o'zgartirishingiz va yangilarini yozishingiz mumkin.\n" -"* Umumiy Rust idiomalarini ko'rsatadi." #: src/welcome.md:14 msgid "On Day 4, we will cover Android-specific things such as:" -msgstr "4-kuni biz Android-ga xos narsalarni ko'rib chiqamiz, masalan:" +msgstr "" #: src/welcome.md:16 msgid "" @@ -827,9 +825,6 @@ msgid "" "* AIDL servers and clients.\n" "* Interoperability with C, C++, and Java." msgstr "" -"* Rust-da Android komponentlarini yaratish.\n" -"* AIDL serverlari va mijozlari.\n" -"* C, C++ va Java bilan o'zaro ishlash." #: src/welcome.md:20 msgid "" @@ -839,13 +834,10 @@ msgid "" "about\n" "writing code for Android itself, the operating system. " msgstr "" -"Ushbu kurs Rust bilan Android ilovalarini ishlab chiqishni qamrab olmaydi. \n" -"Ushbu ma'ruzada ko'rib chiqilgan Android-ga xos tarkib Android OS qismlarini" -"Rust bilan ishlab chiqish haqida." #: src/welcome.md:24 msgid "## Non-Goals" -msgstr "## Istisnolar" +msgstr "" #: src/welcome.md:26 msgid "" @@ -853,8 +845,6 @@ msgid "" "days.\n" "Some non-goals of this course are:" msgstr "" -"Rust - bu katta til va biz bir necha kun ichida hammasini qamrab ololmaymiz. \n" -"Ushbu kursning ba'zi bir istisnolari:" #: src/welcome.md:29 msgid "" @@ -866,17 +856,10 @@ msgid "" " 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 "" -"* Async Rustdan qanday foydalanishni o'rganing - biz faqat an'anaviy parallellik \n" -" primitivlarini qamrab olganimizda async Rust haqida gapiramiz.\n" -" Iltimos, ushbu mavzu bo'yicha batafsil ma'lumot uchun" -" [Rust-da Asinxron Dasturlash](https://rust-lang.github.io/async-book/) bo'limini ko'ring." -"* Makroslarni qanday ishlab chiqishni o'rganing, uning o'rniga [Rust \n" -" kitobining 19.5-bobiga](https://doc.rust-lang.org/book/ch19-06-macros.html) qarang va" -" [Rust by Example](https://doc.rust-lang.org/rust-by-example/macros.html)." #: src/welcome.md:37 msgid "## Assumptions" -msgstr "## O'quvchi darajasi haqida taxminlar" +msgstr "" #: src/welcome.md:39 msgid "" @@ -886,9 +869,6 @@ msgid "" "better\n" "explain or contrast the Rust approach." msgstr "" -"Kurs siz allaqachon dasturlashni bilasiz deb taxmin qiladi. Rust - bu statik" -"tarzda yozilgan til va biz Rust yondashuvini yaxshiroq tushuntirish yoki farqlash" -"uchun ba'zan C va C ++ bilan taqqoslash qilamiz." #: src/welcome.md:43 msgid "" @@ -896,8 +876,6 @@ msgid "" "or\n" "JavaScript, then you will be able to follow along just fine too." msgstr "" -"Agar siz Python yoki JavaScript kabi dinamik tarzda yozilgan tilda dasturlashni" -"bilsangiz, unga amal qilishda sizda katta muammo bo‘lmaydi." #: src/welcome.md:46 src/cargo/rust-ecosystem.md:19 #: src/cargo/code-samples.md:22 src/cargo/running-locally.md:68 diff --git a/rustfmt.toml b/rustfmt.toml index 26ba63e..40b837b 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1,2 @@ +imports_granularity = "module" # Please use nightly for this setting. max_width = 90 diff --git a/src/SUMMARY.md b/src/SUMMARY.md index e508f67..9a12b02 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -31,6 +31,7 @@ - [Slices](basic-syntax/slices.md) - [String vs str](basic-syntax/string-slices.md) - [Functions](basic-syntax/functions.md) + - [Rustdoc](basic-syntax/rustdoc.md) - [Methods](basic-syntax/methods.md) - [Overloading](basic-syntax/functions-interlude.md) - [Exercises](exercises/day-1/morning.md) @@ -125,25 +126,25 @@ ---- - [Welcome](welcome-day-3.md) -- [Traits](traits.md) - - [Deriving Traits](traits/deriving-traits.md) - - [Default Methods](traits/default-methods.md) - - [Important Traits](traits/important-traits.md) - - [Iterator](traits/iterator.md) - - [FromIterator](traits/from-iterator.md) - - [From and Into](traits/from-into.md) - - [Read and Write](traits/read-write.md) - - [Add, Mul, ...](traits/operators.md) - - [Drop](traits/drop.md) - - [Default](traits/default.md) - [Generics](generics.md) - [Generic Data Types](generics/data-types.md) - [Generic Methods](generics/methods.md) - - [Trait Bounds](generics/trait-bounds.md) - - [impl Trait](generics/impl-trait.md) - - [Closures](generics/closures.md) - [Monomorphization](generics/monomorphization.md) - - [Trait Objects](generics/trait-objects.md) +- [Traits](traits.md) + - [Trait Objects](traits/trait-objects.md) + - [Deriving Traits](traits/deriving-traits.md) + - [Default Methods](traits/default-methods.md) + - [Trait Bounds](traits/trait-bounds.md) + - [impl Trait](traits/impl-trait.md) +- [Important Traits](traits/important-traits.md) + - [Iterator](traits/iterator.md) + - [FromIterator](traits/from-iterator.md) + - [From and Into](traits/from-into.md) + - [Read and Write](traits/read-write.md) + - [Drop](traits/drop.md) + - [Default](traits/default.md) + - [Operators: Add, Mul, ...](traits/operators.md) + - [Closures: Fn, FnMut, FnOnce](traits/closures.md) - [Exercises](exercises/day-3/morning.md) - [A Simple GUI Library](exercises/day-3/simple-gui.md) @@ -164,6 +165,7 @@ - [Test Modules](testing/test-modules.md) - [Documentation Tests](testing/doc-tests.md) - [Integration Tests](testing/integration-tests.md) + - [Useful crates](testing/useful-crates.md) - [Unsafe Rust](unsafe.md) - [Dereferencing Raw Pointers](unsafe/raw-pointers.md) - [Mutable Static Variables](unsafe/mutable-static-variables.md) @@ -176,61 +178,131 @@ - [Safe FFI Wrapper](exercises/day-3/safe-ffi-wrapper.md) -# Day 4: Morning +# Android ---- -- [Welcome](welcome-day-4.md) -- [Concurrency](concurrency.md) - - [Threads](concurrency/threads.md) - - [Scoped Threads](concurrency/scoped-threads.md) - - [Channels](concurrency/channels.md) - - [Unbounded Channels](concurrency/channels/unbounded.md) - - [Bounded Channels](concurrency/channels/bounded.md) - - [Shared State](concurrency/shared_state.md) - - [Arc](concurrency/shared_state/arc.md) - - [Mutex](concurrency/shared_state/mutex.md) - - [Example](concurrency/shared_state/example.md) - - [Send and Sync](concurrency/send-sync.md) - - [Send](concurrency/send-sync/send.md) - - [Sync](concurrency/send-sync/sync.md) - - [Examples](concurrency/send-sync/examples.md) -- [Exercises](exercises/day-4/morning.md) - - [Dining Philosophers](exercises/day-4/dining-philosophers.md) - - [Multi-threaded Link Checker](exercises/day-4/link-checker.md) - -# Day 4: Afternoon +- [Welcome](android.md) +- [Setup](android/setup.md) +- [Build Rules](android/build-rules.md) + - [Binary](android/build-rules/binary.md) + - [Library](android/build-rules/library.md) +- [AIDL](android/aidl.md) + - [Interface](android/aidl/interface.md) + - [Implementation](android/aidl/implementation.md) + - [Server](android/aidl/server.md) + - [Deploy](android/aidl/deploy.md) + - [Client](android/aidl/client.md) + - [Changing API](android/aidl/changing.md) +- [Logging](android/logging.md) +- [Interoperability](android/interoperability.md) + - [With C](android/interoperability/with-c.md) + - [Calling C with Bindgen](android/interoperability/with-c/bindgen.md) + - [Calling Rust from C](android/interoperability/with-c/rust.md) + - [With C++](android/interoperability/cpp.md)) + - [With Java](android/interoperability/java.md) +- [Exercises](exercises/android/morning.md) + + +# Bare Metal: Morning ---- -- [Android](android.md) - - [Setup](android/setup.md) - - [Build Rules](android/build-rules.md) - - [Binary](android/build-rules/binary.md) - - [Library](android/build-rules/library.md) - - [AIDL](android/aidl.md) - - [Interface](android/aidl/interface.md) - - [Implementation](android/aidl/implementation.md) - - [Server](android/aidl/server.md) - - [Deploy](android/aidl/deploy.md) - - [Client](android/aidl/client.md) - - [Changing API](android/aidl/changing.md) - - [Logging](android/logging.md) - - [Interoperability](android/interoperability.md) - - [With C](android/interoperability/with-c.md) - - [Calling C with Bindgen](android/interoperability/with-c/bindgen.md) - - [Calling Rust from C](android/interoperability/with-c/rust.md) - - [With C++](android/interoperability/cpp.md)) - - [With Java](android/interoperability/java.md) -- [Exercises](exercises/day-4/afternoon.md) +- [Welcome](bare-metal.md) +- [no_std](bare-metal/no_std.md) + - [A Minimal Example](bare-metal/minimal.md) + - [alloc](bare-metal/alloc.md) +- [Microcontrollers](bare-metal/microcontrollers.md) + - [Raw MMIO](bare-metal/microcontrollers/mmio.md) + - [PACs](bare-metal/microcontrollers/pacs.md) + - [HAL Crates](bare-metal/microcontrollers/hals.md) + - [Board Support Crates](bare-metal/microcontrollers/board-support.md) + - [The Type State Pattern](bare-metal/microcontrollers/type-state.md) + - [embedded-hal](bare-metal/microcontrollers/embedded-hal.md) + - [probe-rs, cargo-embed](bare-metal/microcontrollers/probe-rs.md) + - [Debugging](bare-metal/microcontrollers/debugging.md) + - [Other Projects](bare-metal/microcontrollers/other-projects.md) +- [Exercises](exercises/bare-metal/morning.md) + - [Compass](exercises/bare-metal/compass.md) + +# Bare Metal: Afternoon + +- [Application Processors](bare-metal/aps.md) + - [Inline Assembly](bare-metal/aps/inline-assembly.md) + - [MMIO](bare-metal/aps/mmio.md) + - [Let's Write a UART Driver](bare-metal/aps/uart.md) + - [More Traits](bare-metal/aps/uart/traits.md) + - [A Better UART Driver](bare-metal/aps/better-uart.md) + - [Bitflags](bare-metal/aps/better-uart/bitflags.md) + - [Multiple Registers](bare-metal/aps/better-uart/registers.md) + - [Driver](bare-metal/aps/better-uart/driver.md) + - [Using It](bare-metal/aps/better-uart/using.md) + - [Logging](bare-metal/aps/logging.md) + - [Using It](bare-metal/aps/logging/using.md) + - [Other Projects](bare-metal/aps/other-projects.md) +- [Useful Crates](bare-metal/useful-crates.md) + - [zerocopy](bare-metal/useful-crates/zerocopy.md) + - [aarch64-paging](bare-metal/useful-crates/aarch64-paging.md) + - [buddy_system_allocator](bare-metal/useful-crates/buddy_system_allocator.md) + - [tinyvec](bare-metal/useful-crates/tinyvec.md) + - [spin](bare-metal/useful-crates/spin.md) +- [Android](bare-metal/android.md) + - [vmbase](bare-metal/android/vmbase.md) +- [Exercises](exercises/bare-metal/afternoon.md) + - [RTC Driver](exercises/bare-metal/rtc.md) + + +# Concurrency: Morning + +---- + +- [Welcome](concurrency.md) +- [Threads](concurrency/threads.md) + - [Scoped Threads](concurrency/scoped-threads.md) +- [Channels](concurrency/channels.md) + - [Unbounded Channels](concurrency/channels/unbounded.md) + - [Bounded Channels](concurrency/channels/bounded.md) +- [Send and Sync](concurrency/send-sync.md) + - [Send](concurrency/send-sync/send.md) + - [Sync](concurrency/send-sync/sync.md) + - [Examples](concurrency/send-sync/examples.md) +- [Shared State](concurrency/shared_state.md) + - [Arc](concurrency/shared_state/arc.md) + - [Mutex](concurrency/shared_state/mutex.md) + - [Example](concurrency/shared_state/example.md) +- [Exercises](exercises/concurrency/morning.md) + - [Dining Philosophers](exercises/concurrency/dining-philosophers.md) + - [Multi-threaded Link Checker](exercises/concurrency/link-checker.md) + +# Concurrency: Afternoon + +- [Async Basics](async.md) + - [async/await](async/async-await.md) + - [Futures](async/futures.md) + - [Runtimes](async/runtimes.md) + - [Tokio](async/runtimes/tokio.md) + - [Tasks](async/tasks.md) + - [Async Channels](async/channels.md) +- [Control Flow](async/control-flow.md) + - [Join](async/control-flow/join.md) + - [Select](async/control-flow/select.md) +- [Pitfalls](async/pitfalls.md) + - [Blocking the Executor](async/pitfalls/blocking-executor.md) + - [Pin](async/pitfalls/pin.md) + - [Async Traits](async/pitfalls/async-traits.md) +- [Exercises](exercises/concurrency/afternoon.md) + - [Dining Philosophers](exercises/concurrency/dining-philosophers-async.md) + - [Broadcast Chat Application](exercises/concurrency/chat-app.md) + # Final Words +---- + - [Thanks!](thanks.md) - [Other Resources](other-resources.md) - [Credits](credits.md) ----- # Solutions @@ -243,4 +315,7 @@ - [Day 2 Afternoon](exercises/day-2/solutions-afternoon.md) - [Day 3 Morning](exercises/day-3/solutions-morning.md) - [Day 3 Afternoon](exercises/day-3/solutions-afternoon.md) - - [Day 4 Morning](exercises/day-4/solutions-morning.md) + - [Bare Metal Rust Morning](exercises/bare-metal/solutions-morning.md) + - [Bare Metal Rust Afternoon](exercises/bare-metal/solutions-afternoon.md) + - [Concurrency Morning](exercises/concurrency/solutions-morning.md) + - [Concurrency Afternoon](exercises/concurrency/solutions-afternoon.md) diff --git a/src/android.md b/src/android.md index c0424d5..6844460 100644 --- a/src/android.md +++ b/src/android.md @@ -1,6 +1,10 @@ -# Android +# Welcome to Rust in Android Rust is supported for native platform development on Android. This means that you can write new operating system services in Rust, as well as extending existing services. +> We will attempt to call Rust from one of your own projects today. So try to +> find a little corner of your code base where we can move some lines of code to +> Rust. The fewer dependencies and "exotic" types the better. Something that +> parses some raw bytes would be ideal. diff --git a/src/async.md b/src/async.md new file mode 100644 index 0000000..28d39cf --- /dev/null +++ b/src/async.md @@ -0,0 +1,25 @@ +# Async Rust + +"Async" is a concurrency model where multiple tasks are executed concurrently by +executing each task until it would block, then switching to another task that is +ready to make progress. The model allows running a larger number of tasks on a +limited number of threads. This is because the per-task overhead is typically +very low and operating systems provide primitives for efficiently identifying +I/O that is able to proceed. + +Rust's asynchronous operation is based on "futures", which represent work that +may be completed in the future. Futures are "polled" until they signal that +they are complete. + +Futures are polled by an async runtime, and several different runtimes are +available. + +## Comparisons + + * Python has a similar model in its `asyncio`. However, its `Future` type is + callback-based, and not polled. Async Python programs require a "loop", + similar to a runtime in Rust. + + * JavaScript's `Promise` is similar, but again callback-based. The language + runtime implements the event loop, so many of the details of Promise + resolution are hidden. diff --git a/src/async/async-await.md b/src/async/async-await.md new file mode 100644 index 0000000..7906033 --- /dev/null +++ b/src/async/async-await.md @@ -0,0 +1,48 @@ +# `async`/`await` + +At a high level, async Rust code looks very much like "normal" sequential code: + +```rust,editable,compile_fail +use futures::executor::block_on; + +async fn count_to(count: i32) { + for i in 1..=count { + println!("Count is: {i}!"); + } +} + +async fn async_main(count: i32) { + count_to(count).await; +} + +fn main() { + block_on(async_main(10)); +} +``` + +
+ +Key points: + +* Note that this is a simplified example to show the syntax. There is no long + running operation or any real concurrency in it! + +* What is the return type of an async call? + * Use `let future: () = async_main(10);` in `main` to see the type. + +* The "async" keyword is syntactic sugar. The compiler replaces the return type + with a future. + +* You cannot make `main` async, without additional instructions to the compiler + on how to use the returned future. + +* You need an executor to run async code. `block_on` blocks the current thread + until the provided future has run to completion. + +* `.await` asynchronously waits for the completion of another operation. Unlike + `block_on`, `.await` doesn't block the current thread. + +* `.await` can only be used inside an `async` function (or block; these are + introduced later). + +
diff --git a/src/async/channels.md b/src/async/channels.md new file mode 100644 index 0000000..9e0a5bf --- /dev/null +++ b/src/async/channels.md @@ -0,0 +1,49 @@ +# Async Channels + +Several crates have support for `async`/`await`. For instance `tokio` channels: + +```rust,editable,compile_fail +use tokio::sync::mpsc::{self, Receiver}; + +async fn ping_handler(mut input: Receiver<()>) { + let mut count: usize = 0; + + while let Some(_) = input.recv().await { + count += 1; + println!("Received {count} pings so far."); + } + + println!("ping_handler complete"); +} + +#[tokio::main] +async fn main() { + let (sender, receiver) = mpsc::channel(32); + let ping_handler_task = tokio::spawn(ping_handler(receiver)); + for i in 0..10 { + sender.send(()).await.expect("Failed to send ping."); + println!("Sent {} pings so far.", i + 1); + } + + std::mem::drop(sender); + ping_handler_task.await.expect("Something went wrong in ping handler task."); +} +``` + +
+ +* Change the channel size to `3` and see how it affects the execution. + +* Overall, the interface is similar to the `sync` channels as seen in the + [morning class](concurrency/channels.md). + +* Try removing the `std::mem::drop` call. What happens? Why? + +* The [Flume](https://docs.rs/flume/latest/flume/) crate has channels that + implement both `sync` and `async` `send` and `recv`. This can be convenient + for complex applications with both IO and heavy CPU processing tasks. + +* What makes working with `async` channels preferable is the ability to combine + them with other `future`s to combine them and create complex control flow. + +
diff --git a/src/async/control-flow.md b/src/async/control-flow.md new file mode 100644 index 0000000..69b1d03 --- /dev/null +++ b/src/async/control-flow.md @@ -0,0 +1,7 @@ +# Futures Control Flow + +Futures can be combined together to produce concurrent compute flow graphs. We +have already seen tasks, that function as independent threads of execution. + +- [Join](control-flow/join.md) +- [Select](control-flow/select.md) diff --git a/src/async/control-flow/join.md b/src/async/control-flow/join.md new file mode 100644 index 0000000..4a93e5c --- /dev/null +++ b/src/async/control-flow/join.md @@ -0,0 +1,50 @@ +# Join + +A join operation waits until all of a set of futures are ready, and +returns a collection of their results. This is similar to `Promise.all` in +JavaScript or `asyncio.gather` in Python. + +```rust,editable,compile_fail +use anyhow::Result; +use futures::future; +use reqwest; +use std::collections::HashMap; + +async fn size_of_page(url: &str) -> Result { + let resp = reqwest::get(url).await?; + Ok(resp.text().await?.len()) +} + +#[tokio::main] +async fn main() { + let urls: [&str; 4] = [ + "https://google.com", + "https://httpbin.org/ip", + "https://play.rust-lang.org/", + "BAD_URL", + ]; + let futures_iter = urls.into_iter().map(size_of_page); + let results = future::join_all(futures_iter).await; + let page_sizes_dict: HashMap<&str, Result> = + urls.into_iter().zip(results.into_iter()).collect(); + println!("{:?}", page_sizes_dict); +} +``` + +
+ +Copy this example into your prepared `src/main.rs` and run it from there. + +* For multiple futures of disjoint types, you can use `std::future::join!` but + you must know how many futures you will have at compile time. This is + currently in the `futures` crate, soon to be stabilised in `std::future`. + +* The risk of `join` is that one of the futures may never resolve, this would + cause your program to stall. + +* You can also combine `join_all` with `join!` for instance to join all requests + to an http service as well as a database query. Try adding a + `tokio::time::sleep` to the future, using `futures::join!`. This is not a + timeout (that requires `select!`, explained in the next chapter), but demonstrates `join!`. + +
diff --git a/src/async/control-flow/select.md b/src/async/control-flow/select.md new file mode 100644 index 0000000..62d5ac4 --- /dev/null +++ b/src/async/control-flow/select.md @@ -0,0 +1,77 @@ +# Select + +A select operation waits until any of a set of futures is ready, and responds to +that future's result. In JavaScript, this is similar to `Promise.race`. In +Python, it compares to `asyncio.wait(task_set, +return_when=asyncio.FIRST_COMPLETED)`. + +This is usually a macro, similar to match, with each arm of the form `pattern = +future => statement`. When the future is ready, the statement is executed with the +variable bound to the future's result. + +```rust,editable,compile_fail +use tokio::sync::mpsc::{self, Receiver}; +use tokio::time::{sleep, Duration}; + +#[derive(Debug, PartialEq)] +enum Animal { + Cat { name: String }, + Dog { name: String }, +} + +async fn first_animal_to_finish_race( + mut cat_rcv: Receiver, + mut dog_rcv: Receiver, +) -> Option { + tokio::select! { + cat_name = cat_rcv.recv() => Some(Animal::Cat { name: cat_name? }), + dog_name = dog_rcv.recv() => Some(Animal::Dog { name: dog_name? }) + } +} + +#[tokio::main] +async fn main() { + let (cat_sender, cat_receiver) = mpsc::channel(32); + let (dog_sender, dog_receiver) = mpsc::channel(32); + tokio::spawn(async move { + sleep(Duration::from_millis(500)).await; + cat_sender + .send(String::from("Felix")) + .await + .expect("Failed to send cat."); + }); + tokio::spawn(async move { + sleep(Duration::from_millis(50)).await; + dog_sender + .send(String::from("Rex")) + .await + .expect("Failed to send dog."); + }); + + let winner = first_animal_to_finish_race(cat_receiver, dog_receiver) + .await + .expect("Failed to receive winner"); + + println!("Winner is {winner:?}"); +} +``` + +
+ +* In this example, we have a race between a cat and a dog. + `first_animal_to_finish_race` listens to both channels and will pick whichever + arrives first. Since the dog takes 50ms, it wins against the cat that + take 500ms seconds. + +* You can use `oneshot` channels in this example as the channels are supposed to + receive only one `send`. + +* Try adding a deadline to the race, demonstrating selecting different sorts of + futures. + +* Note that `select!` moves the values it is given. It is easiest to use + when every execution of `select!` creates new futures. An alternative is to + pass `&mut future` instead of the future itself, but this can lead to + issues, further discussed in the pinning slide. + +
diff --git a/src/async/futures.md b/src/async/futures.md new file mode 100644 index 0000000..d9d4347 --- /dev/null +++ b/src/async/futures.md @@ -0,0 +1,45 @@ +# Futures + +[`Future`](https://doc.rust-lang.org/std/future/trait.Future.html) +is a trait, implemented by objects that represent an operation that may not be +complete yet. A future can be polled, and `poll` returns a +[`Poll`](https://doc.rust-lang.org/std/task/enum.Poll.html). + +```rust +use std::pin::Pin; +use std::task::Context; + +pub trait Future { + type Output; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; +} + +pub enum Poll { + Ready(T), + Pending, +} +``` + +An async function returns an `impl Future`. It's also possible (but uncommon) to +implement `Future` for your own types. For example, the `JoinHandle` returned +from `tokio::spawn` implements `Future` to allow joining to it. + +The `.await` keyword, applied to a Future, causes the current async function to +pause until that Future is ready, and then evaluates to its output. + +
+ +* The `Future` and `Poll` types are implemented exactly as shown; click the + links to show the implementations in the docs. + +* We will not get to `Pin` and `Context`, as we will focus on writing async + code, rather than building new async primitives. Briefly: + + * `Context` allows a Future to schedule itself to be polled again when an + event occurs. + + * `Pin` ensures that the Future isn't moved in memory, so that pointers into + that future remain valid. This is required to allow references to remain + valid after an `.await`. + +
diff --git a/src/async/pitfalls.md b/src/async/pitfalls.md new file mode 100644 index 0000000..a8ae89e --- /dev/null +++ b/src/async/pitfalls.md @@ -0,0 +1,7 @@ +# Pitfalls of async/await + +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: + +- [Blocking the Executor](pitfalls/blocking-executor.md) +- [Pin](pitfalls/pin.md) +- [Async Traits](pitfall/async-traits.md) diff --git a/src/async/pitfalls/async-traits.md b/src/async/pitfalls/async-traits.md new file mode 100644 index 0000000..a4ea8a0 --- /dev/null +++ b/src/async/pitfalls/async-traits.md @@ -0,0 +1,63 @@ +# Async Traits + +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)) + +The crate [async_trait](https://docs.rs/async-trait/latest/async_trait/) provides a workaround through a macro: + +```rust,editable,compile_fail +use async_trait::async_trait; +use std::time::Instant; +use tokio::time::{sleep, Duration}; + +#[async_trait] +trait Sleeper { + async fn sleep(&self); +} + +struct FixedSleeper { + sleep_ms: u64, +} + +#[async_trait] +impl Sleeper for FixedSleeper { + async fn sleep(&self) { + sleep(Duration::from_millis(self.sleep_ms)).await; + } +} + +async fn run_all_sleepers_multiple_times(sleepers: Vec>, n_times: usize) { + for _ in 0..n_times { + println!("running all sleepers.."); + for sleeper in &sleepers { + let start = Instant::now(); + sleeper.sleep().await; + println!("slept for {}ms", start.elapsed().as_millis()); + } + } +} + +#[tokio::main] +async fn main() { + let sleepers: Vec> = vec![ + Box::new(FixedSleeper { sleep_ms: 50 }), + Box::new(FixedSleeper { sleep_ms: 100 }), + ]; + run_all_sleepers_multiple_times(sleepers, 5).await; +} +``` + +
+ +* `async_trait` is easy to use, but note that it's using heap allocations to + achieve this. This heap allocation has performance overhead. + +* The challenges in language support for `async trait` are deep Rust and + probably not worth describing in-depth. Niko Matsakis did a good job of + explaining them in [this + post](https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/) + if you are interested in digging deeper. + +* Try creating a new sleeper struct that will sleep for a random amount of time + and adding it to the Vec. + +
diff --git a/src/async/pitfalls/blocking-executor.md b/src/async/pitfalls/blocking-executor.md new file mode 100644 index 0000000..cfbfb46 --- /dev/null +++ b/src/async/pitfalls/blocking-executor.md @@ -0,0 +1,50 @@ +# Blocking the executor + +Most async runtimes only allow IO tasks to run concurrently. +This means that CPU blocking tasks will block the executor and prevent other tasks from being executed. +An easy workaround is to use async equivalent methods where possible. + +```rust,editable,compile_fail +use futures::future::join_all; +use std::time::Instant; + +async fn sleep_ms(start: &Instant, id: u64, duration_ms: u64) { + std::thread::sleep(std::time::Duration::from_millis(duration_ms)); + println!( + "future {id} slept for {duration_ms}ms, finished after {}ms", + start.elapsed().as_millis() + ); +} + +#[tokio::main(flavor = "current_thread")] +async fn main() { + let start = Instant::now(); + let sleep_futures = (1..=10).map(|t| sleep_ms(&start, t, t * 10)); + join_all(sleep_futures).await; +} +``` + +
+ +* Run the code and see that the sleeps happen consecutively rather than + concurrently. + +* The `"current_thread"` flavor puts all tasks on a single thread. This makes the + effect more obvious, but the bug is still present in the multi-threaded + flavor. + +* Switch the `std::thread::sleep` to `tokio::time::sleep` and await its result. + +* Another fix would be to `tokio::task::spawn_blocking` which spawns an actual + thread and transforms its handle into a future without blocking the executor. + +* You should not think of tasks as OS threads. They do not map 1 to 1 and most + executors will allow many tasks to run on a single OS thread. This is + particularly problematic when interacting with other libraries via FFI, where + that library might depend on thread-local storage or map to specific OS + threads (e.g., CUDA). Prefer `tokio::task::spawn_blocking` in such situations. + +* Use sync mutexes with care. Holding a mutex over an `.await` may cause another + task to block, and that task may be running on the same thread. + +
diff --git a/src/async/pitfalls/pin.md b/src/async/pitfalls/pin.md new file mode 100644 index 0000000..a6b9211 --- /dev/null +++ b/src/async/pitfalls/pin.md @@ -0,0 +1,112 @@ +# Pin + +When you await a future, all local variables (that would ordinarily be stored on +a stack frame) are instead stored in the Future for the current async block. If your +future has pointers to data on the stack, those pointers might get invalidated. +This is unsafe. + +Therefore, you must guarantee that the addresses your future points to don't +change. That is why we need to `pin` futures. Using the same future repeatedly +in a `select!` often leads to issues with pinned values. + +```rust,editable,compile_fail +use tokio::sync::{mpsc, oneshot}; +use tokio::task::spawn; +use tokio::time::{sleep, Duration}; + +// A work item. In this case, just sleep for the given time and respond +// with a message on the `respond_on` channel. +#[derive(Debug)] +struct Work { + input: u32, + respond_on: oneshot::Sender, +} + +// A worker which listens for work on a queue and performs it. +async fn worker(mut work_queue: mpsc::Receiver) { + let mut iterations = 0; + loop { + tokio::select! { + Some(work) = work_queue.recv() => { + sleep(Duration::from_millis(10)).await; // Pretend to work. + work.respond_on + .send(work.input * 1000) + .expect("failed to send response"); + iterations += 1; + } + // TODO: report number of iterations every 100ms + } + } +} + +// A requester which requests work and waits for it to complete. +async fn do_work(work_queue: &mpsc::Sender, input: u32) -> u32 { + let (tx, rx) = oneshot::channel(); + work_queue + .send(Work { + input, + respond_on: tx, + }) + .await + .expect("failed to send on work queue"); + rx.await.expect("failed waiting for response") +} + +#[tokio::main] +async fn main() { + let (tx, rx) = mpsc::channel(10); + spawn(worker(rx)); + for i in 0..100 { + let resp = do_work(&tx, i).await; + println!("work result for iteration {i}: {resp}"); + } +} +``` + +
+ +* You may recognize this as an example of the actor pattern. Actors + typically call `select!` in a loop. + +* This serves as a summation of a few of the previous lessons, so take your time + with it. + + * Naively add a `_ = sleep(Duration::from_millis(100)) => { println!(..) }` + to the `select!`. This will never execute. Why? + + * Instead, add a `timeout_fut` containing that future outside of the `loop`: + + ```rust,compile_fail + let mut timeout_fut = sleep(Duration::from_millis(100)); + loop { + select! { + .., + _ = timeout_fut => { println!(..); }, + } + } + ``` + * This still doesn't work. Follow the compiler errors, adding `&mut` to the + `timeout_fut` in the `select!` to work around the move, then using + `Box::pin`: + + ```rust,compile_fail + let mut timeout_fut = Box::pin(sleep(Duration::from_millis(100))); + loop { + select! { + .., + _ = &mut timeout_fut => { println!(..); }, + } + } + ``` + + * This compiles, but once the timeout expires it is `Poll::Ready` on every + iteration (a fused future would help with this). Update to reset + `timeout_fut` every time it expires. + +* Box allocates on the heap. In some cases, `std::pin::pin!` (only recently + stabilized, with older code often using `tokio::pin!`) is also an option, but + that is difficult to use for a future that is reassigned. + +* Another alternative is to not use `pin` at all but spawn another task that will send to a `oneshot` channel every 100ms. + +
diff --git a/src/async/runtimes.md b/src/async/runtimes.md new file mode 100644 index 0000000..22a7062 --- /dev/null +++ b/src/async/runtimes.md @@ -0,0 +1,29 @@ +# Runtimes + +A *runtime* provides support for performing operations asynchronously (a +*reactor*) and is responsible for executing futures (an *executor*). Rust does not have a +"built-in" runtime, but several options are available: + + * [Tokio](https://tokio.rs/) - performant, with a well-developed ecosystem of + functionality like [Hyper](https://hyper.rs/) for HTTP or + [Tonic](https://github.com/hyperium/tonic) for gRPC. + * [async-std](https://async.rs/) - aims to be a "std for async", and includes a + basic runtime in `async::task`. + * [smol](https://docs.rs/smol/latest/smol/) - simple and lightweight + +Several larger applications have their own runtimes. For example, +[Fuchsia](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/lib/fuchsia-async/src/lib.rs) +already has one. + +
+ +* Note that of the listed runtimes, only Tokio is supported in the Rust + playground. The playground also does not permit any I/O, so most interesting + async things can't run in the playground. + +* Futures are "inert" in that they do not do anything (not even start an I/O + operation) unless there is an executor polling them. This differs from JS + Promises, for example, which will run to completion even if they are never + used. + +
diff --git a/src/async/runtimes/tokio.md b/src/async/runtimes/tokio.md new file mode 100644 index 0000000..c9dfbd4 --- /dev/null +++ b/src/async/runtimes/tokio.md @@ -0,0 +1,49 @@ +# Tokio + + +Tokio provides: + +* A multi-threaded runtime for executing asynchronous code. +* An asynchronous version of the standard library. +* A large ecosystem of libraries. + +```rust,editable,compile_fail +use tokio::time; + +async fn count_to(count: i32) { + for i in 1..=count { + println!("Count in task: {i}!"); + time::sleep(time::Duration::from_millis(5)).await; + } +} + +#[tokio::main] +async fn main() { + tokio::spawn(count_to(10)); + + for i in 1..5 { + println!("Main task: {i}"); + time::sleep(time::Duration::from_millis(5)).await; + } +} +``` + +
+ +* With the `tokio::main` macro we can now make `main` async. + +* The `spawn` function creates a new, concurrent "task". + +* Note: `spawn` takes a `Future`, you don't call `.await` on `count_to`. + +**Further exploration:** + +* Why does `count_to` not (usually) get to 10? This is an example of async + cancellation. `tokio::spawn` returns a handle which can be awaited to wait + until it finishes. + +* Try `count_to(10).await` instead of spawning. + +* Try awaiting the task returned from `tokio::spawn`. + +
diff --git a/src/async/tasks.md b/src/async/tasks.md new file mode 100644 index 0000000..6aebfa0 --- /dev/null +++ b/src/async/tasks.md @@ -0,0 +1,64 @@ +# Tasks + +Runtimes have the concept of a "task", similar to a thread but much +less resource-intensive. + +A task has a single top-level future which the executor polls to make progress. +That future may have one or more nested futures that its `poll` method polls, +corresponding loosely to a call stack. Concurrency within a task is possible by +polling multiple child futures, such as racing a timer and an I/O operation. + +```rust,compile_fail +use tokio::io::{self, AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpListener; + +#[tokio::main] +async fn main() -> io::Result<()> { + let listener = TcpListener::bind("127.0.0.1:6142").await?; + println!("listening on port 6142"); + + loop { + let (mut socket, addr) = listener.accept().await?; + + println!("connection from {addr:?}"); + + tokio::spawn(async move { + if let Err(e) = socket.write_all(b"Who are you?\n").await { + println!("socket error: {e:?}"); + return; + } + + let mut buf = vec![0; 1024]; + let reply = match socket.read(&mut buf).await { + Ok(n) => { + let name = std::str::from_utf8(&buf[..n]).unwrap().trim(); + format!("Thanks for dialing in, {name}!\n") + } + Err(e) => { + println!("socket error: {e:?}"); + return; + } + }; + + if let Err(e) = socket.write_all(reply.as_bytes()).await { + println!("socket error: {e:?}"); + } + }); + } +} +``` + +
+ +Copy this example into your prepared `src/main.rs` and run it from there. + +* Ask students to visualize what the state of the example server would be with a + few connected clients. What tasks exist? What are their Futures? + +* This is the first time we've seen an `async` block. This is similar to a + closure, but does not take any arguments. Its return value is a Future, + similar to an `async fn`. + +* Refactor the async block into a function, and improve the error handling using `?`. + +
diff --git a/src/bare-metal.md b/src/bare-metal.md new file mode 100644 index 0000000..2900efb --- /dev/null +++ b/src/bare-metal.md @@ -0,0 +1,48 @@ +# Welcome to Bare Metal Rust + +This is a standalone one-day course about bare-metal Rust, aimed at people who are familiar with the +basics of Rust (perhaps from completing the Comprehensive Rust course), and ideally also have some +experience with bare-metal programming in some other language such as C. + +Today we will talk about 'bare-metal' Rust: running Rust code without an OS underneath us. This will +be divided into several parts: + +- What is `no_std` Rust? +- Writing firmware for microcontrollers. +- Writing bootloader / kernel code for application processors. +- Some useful crates for bare-metal Rust development. + +For the microcontroller part of the course we will use the [BBC micro:bit](https://microbit.org/) v2 +as an example. It's a [development board](https://tech.microbit.org/hardware/) based on the Nordic +nRF51822 microcontroller with some LEDs and buttons, an I2C-connected accelerometer and compass, and +an on-board SWD debugger. + +To get started, install some tools we'll need later. On gLinux or Debian: + +```bash +sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom pkg-config qemu-system-arm +rustup update +rustup target add aarch64-unknown-none thumbv7em-none-eabihf +rustup component add llvm-tools-preview +cargo install cargo-binutils cargo-embed +``` + +And give users in the `plugdev` group access to the micro:bit programmer: + +```bash +echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="0d28", MODE="0664", GROUP="plugdev"' |\ + sudo tee /etc/udev/rules.d/50-microbit.rules +sudo udevadm control --reload-rules +``` + +On MacOS: + +```bash +xcode-select --install +brew install gdb picocom qemu +brew install --cask gcc-aarch64-embedded +rustup update +rustup target add aarch64-unknown-none thumbv7em-none-eabihf +rustup component add llvm-tools-preview +cargo install cargo-binutils cargo-embed +``` diff --git a/src/bare-metal/alloc-example/.cargo/config.toml b/src/bare-metal/alloc-example/.cargo/config.toml new file mode 100644 index 0000000..724feba --- /dev/null +++ b/src/bare-metal/alloc-example/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "aarch64-unknown-none" diff --git a/src/bare-metal/alloc-example/Cargo.lock b/src/bare-metal/alloc-example/Cargo.lock new file mode 100644 index 0000000..7cf60a2 --- /dev/null +++ b/src/bare-metal/alloc-example/Cargo.lock @@ -0,0 +1,57 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "alloc-example" +version = "0.1.0" +dependencies = [ + "buddy_system_allocator", + "panic-halt", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "buddy_system_allocator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f9365b6b0c9e1663ca4ca9440c00eda46bc85a3407070be8b5e0d8d1f29629" +dependencies = [ + "spin", +] + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "panic-halt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] diff --git a/src/bare-metal/alloc-example/Cargo.toml b/src/bare-metal/alloc-example/Cargo.toml new file mode 100644 index 0000000..472ba6e --- /dev/null +++ b/src/bare-metal/alloc-example/Cargo.toml @@ -0,0 +1,17 @@ +[workspace] + +[package] +name = "alloc-example" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +buddy_system_allocator = "0.9.0" +panic-halt = "0.2.0" + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" diff --git a/src/bare-metal/alloc-example/src/main.rs b/src/bare-metal/alloc-example/src/main.rs new file mode 100644 index 0000000..7ab8ba5 --- /dev/null +++ b/src/bare-metal/alloc-example/src/main.rs @@ -0,0 +1,43 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: Alloc +#![no_main] +#![no_std] + +extern crate alloc; +extern crate panic_halt as _; + +use alloc::string::ToString; +use alloc::vec::Vec; +use buddy_system_allocator::LockedHeap; + +#[global_allocator] +static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new(); + +static mut HEAP: [u8; 65536] = [0; 65536]; + +pub fn entry() { + // Safe because `HEAP` is only used here and `entry` is only called once. + unsafe { + // Give the allocator some memory to allocate. + HEAP_ALLOCATOR + .lock() + .init(HEAP.as_mut_ptr() as usize, HEAP.len()); + } + + // Now we can do things that require heap allocation. + let mut v = Vec::new(); + v.push("A string".to_string()); +} diff --git a/src/bare-metal/alloc.md b/src/bare-metal/alloc.md new file mode 100644 index 0000000..e600b79 --- /dev/null +++ b/src/bare-metal/alloc.md @@ -0,0 +1,22 @@ +# `alloc` + +To use `alloc` you must implement a +[global (heap) allocator](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html). + +```rust,editable,compile_fail +{{#include alloc-example/src/main.rs:Alloc}} +``` + +
+ +* `buddy_system_allocator` is a third-party crate implementing a basic buddy system allocator. Other + crates are available, or you can write your own or hook into your existing allocator. +* The const parameter of `LockedHeap` is the max order of the allocator; i.e. in this case it can + allocate regions of up to 2**32 bytes. +* If any crate in your dependency tree depends on `alloc` then you must have exactly one global + allocator defined in your binary. Usually this is done in the top-level binary crate. +* `extern crate panic_halt as _` is necessary to ensure that the `panic_halt` crate is linked in so + we get its panic handler. +* This example will build but not run, as it doesn't have an entry point. + +
diff --git a/src/bare-metal/android.md b/src/bare-metal/android.md new file mode 100644 index 0000000..c5fb523 --- /dev/null +++ b/src/bare-metal/android.md @@ -0,0 +1,44 @@ +# Android + +To build a bare-metal Rust binary in AOSP, you need to use a `rust_ffi_static` Soong rule to build +your Rust code, then a `cc_binary` with a linker script to produce the binary itself, and then a +`raw_binary` to convert the ELF to a raw binary ready to be run. + +```soong +rust_ffi_static { + name: "libvmbase_example", + defaults: ["vmbase_ffi_defaults"], + crate_name: "vmbase_example", + srcs: ["src/main.rs"], + rustlibs: [ + "libvmbase", + ], +} + +cc_binary { + name: "vmbase_example", + defaults: ["vmbase_elf_defaults"], + srcs: [ + "idmap.S", + ], + static_libs: [ + "libvmbase_example", + ], + linker_scripts: [ + "image.ld", + ":vmbase_sections", + ], +} + +raw_binary { + name: "vmbase_example_bin", + stem: "vmbase_example.bin", + src: ":vmbase_example", + enabled: false, + target: { + android_arm64: { + enabled: true, + }, + }, +} +``` diff --git a/src/bare-metal/android/vmbase.md b/src/bare-metal/android/vmbase.md new file mode 100644 index 0000000..2e70dc2 --- /dev/null +++ b/src/bare-metal/android/vmbase.md @@ -0,0 +1,27 @@ +# vmbase + +For VMs running under crosvm on aarch64, the [vmbase][1] library provides a linker script and useful +defaults for the build rules, along with an entry point, UART console logging and more. + +```rust,compile_fail +#![no_main] +#![no_std] + +use vmbase::{main, println}; + +main!(main); + +pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) { + println!("Hello world"); +} +``` + +
+ +* The `main!` macro marks your main function, to be called from the `vmbase` entry point. +* The `vmbase` entry point handles console initialisation, and issues a PSCI_SYSTEM_OFF to shutdown + the VM if your main function returns. + +
+ +[1]: https://android.googlesource.com/platform/packages/modules/Virtualization/+/refs/heads/master/vmbase/ diff --git a/src/bare-metal/aps.md b/src/bare-metal/aps.md new file mode 100644 index 0000000..8e937fb --- /dev/null +++ b/src/bare-metal/aps.md @@ -0,0 +1,15 @@ +# Application processors + +So far we've talked about microcontrollers, such as the Arm Cortex-M series. Now let's try writing +something for Cortex-A. For simplicity we'll just work with QEMU's aarch64 +['virt'](https://qemu-project.gitlab.io/qemu/system/arm/virt.html) board. + +
+ +* Broadly speaking, microcontrollers don't have an MMU or multiple levels of privilege (exception + levels on Arm CPUs, rings on x86), while application processors do. +* QEMU supports emulating various different machines or board models for each architecture. The + 'virt' board doesn't correspond to any particular real hardware, but is designed purely for + virtual machines. + +
diff --git a/src/bare-metal/aps/better-uart.md b/src/bare-metal/aps/better-uart.md new file mode 100644 index 0000000..99ceb51 --- /dev/null +++ b/src/bare-metal/aps/better-uart.md @@ -0,0 +1,30 @@ +# A better UART driver + +The PL011 actually has [a bunch more registers][1], and adding offsets to construct pointers to access +them is error-prone and hard to read. Plus, some of them are bit fields which would be nice to +access in a structured way. + +| Offset | Register name | Width | +| ------ | ------------- | ----- | +| 0x00 | DR | 12 | +| 0x04 | RSR | 4 | +| 0x18 | FR | 9 | +| 0x20 | ILPR | 8 | +| 0x24 | IBRD | 16 | +| 0x28 | FBRD | 6 | +| 0x2c | LCR_H | 8 | +| 0x30 | CR | 16 | +| 0x34 | IFLS | 6 | +| 0x38 | IMSC | 11 | +| 0x3c | RIS | 11 | +| 0x40 | MIS | 11 | +| 0x44 | ICR | 11 | +| 0x48 | DMACR | 3 | + +
+ +- There are also some ID registers which have been omitted for brevity. + +
+ +[1]: https://developer.arm.com/documentation/ddi0183/g/programmers-model/summary-of-registers diff --git a/src/bare-metal/aps/better-uart/bitflags.md b/src/bare-metal/aps/better-uart/bitflags.md new file mode 100644 index 0000000..0ee6c0c --- /dev/null +++ b/src/bare-metal/aps/better-uart/bitflags.md @@ -0,0 +1,14 @@ +# Bitflags + +The [`bitflags`](https://crates.io/crates/bitflags) crate is useful for working with bitflags. + +```rust,editable,compile_fail +{{#include ../examples/src/pl011.rs:Flags}} +``` + +
+ +* The `bitflags!` macro creates a newtype something like `Flags(u16)`, along with a bunch of method + implementations to get and set flags. + +
diff --git a/src/bare-metal/aps/better-uart/driver.md b/src/bare-metal/aps/better-uart/driver.md new file mode 100644 index 0000000..28bad72 --- /dev/null +++ b/src/bare-metal/aps/better-uart/driver.md @@ -0,0 +1,14 @@ +# Driver + +Now let's use the new `Registers` struct in our driver. + +```rust,editable,compile_fail +{{#include ../examples/src/pl011.rs:Uart}} +``` + +
+ +* Note the use of `addr_of!` / `addr_of_mut!` to get pointers to individual fields without creating + an intermediate reference, which would be unsound. + +
diff --git a/src/bare-metal/aps/better-uart/registers.md b/src/bare-metal/aps/better-uart/registers.md new file mode 100644 index 0000000..e4d3367 --- /dev/null +++ b/src/bare-metal/aps/better-uart/registers.md @@ -0,0 +1,16 @@ +# Multiple registers + +We can use a struct to represent the memory layout of the UART's registers. + +```rust,editable,compile_fail +{{#include ../examples/src/pl011.rs:Registers}} +``` + +
+ +* [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-representation) tells + the compiler to lay the struct fields out in order, following the same rules as C. This is + necessary for our struct to have a predictable layout, as default Rust representation allows the + compiler to (among other things) reorder fields however it sees fit. + +
diff --git a/src/bare-metal/aps/better-uart/using.md b/src/bare-metal/aps/better-uart/using.md new file mode 100644 index 0000000..5089224 --- /dev/null +++ b/src/bare-metal/aps/better-uart/using.md @@ -0,0 +1,16 @@ +# Using it + +Let's write a small program using our driver to write to the serial console, and echo incoming +bytes. + +```rust,editable,compile_fail +{{#include ../examples/src/main_improved.rs:main}} +``` + +
+ +* As in the [inline assembly](../inline-assembly.md) example, this `main` function is called from our + entry point code in `entry.S`. See the speaker notes there for details. +* Run the example in QEMU with `make qemu` under `src/bare-metal/aps/examples`. + +
diff --git a/src/bare-metal/aps/examples/.cargo/config.toml b/src/bare-metal/aps/examples/.cargo/config.toml new file mode 100644 index 0000000..ffecab4 --- /dev/null +++ b/src/bare-metal/aps/examples/.cargo/config.toml @@ -0,0 +1,3 @@ +[build] +target = "aarch64-unknown-none" +rustflags = ["-C", "link-arg=-Timage.ld"] diff --git a/src/bare-metal/aps/examples/Cargo.lock b/src/bare-metal/aps/examples/Cargo.lock new file mode 100644 index 0000000..bc80073 --- /dev/null +++ b/src/bare-metal/aps/examples/Cargo.lock @@ -0,0 +1,78 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ap-examples" +version = "0.1.0" +dependencies = [ + "bitflags", + "cc", + "log", + "smccc", + "spin", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f6e5df9abedba5099a01a6567c6086a6fbcff57af07c360d356737f9e0c644" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "smccc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617d17f088ec733e5a6b86da6ce4cce1414e6e856d6061c16dda51cceae6f68c" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] diff --git a/src/bare-metal/aps/examples/Cargo.toml b/src/bare-metal/aps/examples/Cargo.toml new file mode 100644 index 0000000..bf6c86a --- /dev/null +++ b/src/bare-metal/aps/examples/Cargo.toml @@ -0,0 +1,32 @@ +[workspace] + +[package] +name = "ap-examples" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +bitflags = "2.0.0" +log = "0.4.17" +smccc = "0.1.1" +spin = "0.9.8" + +[build-dependencies] +cc = "1.0.73" + +[[bin]] +name = "improved" +path = "src/main_improved.rs" + +[[bin]] +name = "logger" +path = "src/main_logger.rs" + +[[bin]] +name = "minimal" +path = "src/main_minimal.rs" + +[[bin]] +name = "psci" +path = "src/main_psci.rs" diff --git a/src/bare-metal/aps/examples/Makefile b/src/bare-metal/aps/examples/Makefile new file mode 100644 index 0000000..5f65d18 --- /dev/null +++ b/src/bare-metal/aps/examples/Makefile @@ -0,0 +1,50 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +UNAME := $(shell uname -s) +ifeq ($(UNAME),Linux) + TARGET = aarch64-linux-gnu +else + TARGET = aarch64-none-elf +endif +OBJCOPY = $(TARGET)-objcopy + +.PHONY: build qemu qemu_logger qemu_minimal qemu_psci + +all: minimal.bin improved.bin logger.bin + +build: + cargo build + +improved.bin: build + $(OBJCOPY) -O binary target/aarch64-unknown-none/debug/improved $@ +logger.bin: build + $(OBJCOPY) -O binary target/aarch64-unknown-none/debug/logger $@ +minimal.bin: build + $(OBJCOPY) -O binary target/aarch64-unknown-none/debug/minimal $@ +psci.bin: build + $(OBJCOPY) -O binary target/aarch64-unknown-none/debug/psci $@ + +qemu: improved.bin + qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s +qemu_logger: logger.bin + qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s +qemu_minimal: minimal.bin + qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s +qemu_psci: psci.bin + qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel $< -s + +clean: + cargo clean + rm -f *.bin diff --git a/src/bare-metal/aps/examples/build.rs b/src/bare-metal/aps/examples/build.rs new file mode 100644 index 0000000..7a58b29 --- /dev/null +++ b/src/bare-metal/aps/examples/build.rs @@ -0,0 +1,29 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use cc::Build; +use std::env; + +fn main() { + #[cfg(target_os = "linux")] + env::set_var("CROSS_COMPILE", "aarch64-linux-gnu"); + #[cfg(not(target_os = "linux"))] + env::set_var("CROSS_COMPILE", "aarch64-none-elf"); + + Build::new() + .file("entry.S") + .file("exceptions.S") + .file("idmap.S") + .compile("empty") +} diff --git a/src/bare-metal/aps/examples/entry.S b/src/bare-metal/aps/examples/entry.S new file mode 100644 index 0000000..cd554f2 --- /dev/null +++ b/src/bare-metal/aps/examples/entry.S @@ -0,0 +1,142 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.macro adr_l, reg:req, sym:req + adrp \reg, \sym + add \reg, \reg, :lo12:\sym +.endm + +.macro mov_i, reg:req, imm:req + movz \reg, :abs_g3:\imm + movk \reg, :abs_g2_nc:\imm + movk \reg, :abs_g1_nc:\imm + movk \reg, :abs_g0_nc:\imm +.endm + +.set .L_MAIR_DEV_nGnRE, 0x04 +.set .L_MAIR_MEM_WBWA, 0xff +.set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8) + +/* 4 KiB granule size for TTBR0_EL1. */ +.set .L_TCR_TG0_4KB, 0x0 << 14 +/* 4 KiB granule size for TTBR1_EL1. */ +.set .L_TCR_TG1_4KB, 0x2 << 30 +/* Disable translation table walk for TTBR1_EL1, generating a translation fault instead. */ +.set .L_TCR_EPD1, 0x1 << 23 +/* Translation table walks for TTBR0_EL1 are inner sharable. */ +.set .L_TCR_SH_INNER, 0x3 << 12 +/* + * Translation table walks for TTBR0_EL1 are outer write-back read-allocate write-allocate + * cacheable. + */ +.set .L_TCR_RGN_OWB, 0x1 << 10 +/* + * Translation table walks for TTBR0_EL1 are inner write-back read-allocate write-allocate + * cacheable. + */ +.set .L_TCR_RGN_IWB, 0x1 << 8 +/* Size offset for TTBR0_EL1 is 2**39 bytes (512 GiB). */ +.set .L_TCR_T0SZ_512, 64 - 39 +.set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_TG1_4KB | .L_TCR_EPD1 | .L_TCR_RGN_OWB +.set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | .L_TCR_T0SZ_512 + +/* Stage 1 instruction access cacheability is unaffected. */ +.set .L_SCTLR_ELx_I, 0x1 << 12 +/* SP alignment fault if SP is not aligned to a 16 byte boundary. */ +.set .L_SCTLR_ELx_SA, 0x1 << 3 +/* Stage 1 data access cacheability is unaffected. */ +.set .L_SCTLR_ELx_C, 0x1 << 2 +/* EL0 and EL1 stage 1 MMU enabled. */ +.set .L_SCTLR_ELx_M, 0x1 << 0 +/* Privileged Access Never is unchanged on taking an exception to EL1. */ +.set .L_SCTLR_EL1_SPAN, 0x1 << 23 +/* SETEND instruction disabled at EL0 in aarch32 mode. */ +.set .L_SCTLR_EL1_SED, 0x1 << 8 +/* Various IT instructions are disabled at EL0 in aarch32 mode. */ +.set .L_SCTLR_EL1_ITD, 0x1 << 7 +.set .L_SCTLR_EL1_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29) +.set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | .L_SCTLR_EL1_ITD | .L_SCTLR_EL1_SED +.set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL1_SPAN | .L_SCTLR_EL1_RES1 + +/** + * This is a generic entry point for an image. It carries out the operations required to prepare the + * loaded image to be run. Specifically, it zeroes the bss section using registers x25 and above, + * prepares the stack, enables floating point, and sets up the exception vector. It preserves x0-x3 + * for the Rust entry point, as these may contain boot parameters. + */ +.section .init.entry, "ax" +.global entry +entry: + /* Load and apply the memory management configuration, ready to enable MMU and caches. */ + adrp x30, idmap + msr ttbr0_el1, x30 + + mov_i x30, .Lmairval + msr mair_el1, x30 + + mov_i x30, .Ltcrval + /* Copy the supported PA range into TCR_EL1.IPS. */ + mrs x29, id_aa64mmfr0_el1 + bfi x30, x29, #32, #4 + + msr tcr_el1, x30 + + mov_i x30, .Lsctlrval + + /* + * Ensure everything before this point has completed, then invalidate any potentially stale + * local TLB entries before they start being used. + */ + isb + tlbi vmalle1 + ic iallu + dsb nsh + isb + + /* + * Configure sctlr_el1 to enable MMU and cache and don't proceed until this has completed. + */ + msr sctlr_el1, x30 + isb + + /* Disable trapping floating point access in EL1. */ + mrs x30, cpacr_el1 + orr x30, x30, #(0x3 << 20) + msr cpacr_el1, x30 + isb + + /* Zero out the bss section. */ + adr_l x29, bss_begin + adr_l x30, bss_end +0: cmp x29, x30 + b.hs 1f + stp xzr, xzr, [x29], #16 + b 0b + +1: /* Prepare the stack. */ + adr_l x30, boot_stack_end + mov sp, x30 + + /* Set up exception vector. */ + adr x30, vector_table_el1 + msr vbar_el1, x30 + + /* Call into Rust code. */ + bl main + + /* Loop forever waiting for interrupts. */ +2: wfi + b 2b diff --git a/src/bare-metal/aps/examples/exceptions.S b/src/bare-metal/aps/examples/exceptions.S new file mode 100644 index 0000000..434b050 --- /dev/null +++ b/src/bare-metal/aps/examples/exceptions.S @@ -0,0 +1,178 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Saves the volatile registers onto the stack. This currently takes 14 + * instructions, so it can be used in exception handlers with 18 instructions + * left. + * + * On return, x0 and x1 are initialised to elr_el2 and spsr_el2 respectively, + * which can be used as the first and second arguments of a subsequent call. + */ +.macro save_volatile_to_stack + /* Reserve stack space and save registers x0-x18, x29 & x30. */ + stp x0, x1, [sp, #-(8 * 24)]! + stp x2, x3, [sp, #8 * 2] + stp x4, x5, [sp, #8 * 4] + stp x6, x7, [sp, #8 * 6] + stp x8, x9, [sp, #8 * 8] + stp x10, x11, [sp, #8 * 10] + stp x12, x13, [sp, #8 * 12] + stp x14, x15, [sp, #8 * 14] + stp x16, x17, [sp, #8 * 16] + str x18, [sp, #8 * 18] + stp x29, x30, [sp, #8 * 20] + + /* + * Save elr_el1 & spsr_el1. This such that we can take nested exception + * and still be able to unwind. + */ + mrs x0, elr_el1 + mrs x1, spsr_el1 + stp x0, x1, [sp, #8 * 22] +.endm + +/** + * Restores the volatile registers from the stack. This currently takes 14 + * instructions, so it can be used in exception handlers while still leaving 18 + * instructions left; if paired with save_volatile_to_stack, there are 4 + * instructions to spare. + */ +.macro restore_volatile_from_stack + /* Restore registers x2-x18, x29 & x30. */ + ldp x2, x3, [sp, #8 * 2] + ldp x4, x5, [sp, #8 * 4] + ldp x6, x7, [sp, #8 * 6] + ldp x8, x9, [sp, #8 * 8] + ldp x10, x11, [sp, #8 * 10] + ldp x12, x13, [sp, #8 * 12] + ldp x14, x15, [sp, #8 * 14] + ldp x16, x17, [sp, #8 * 16] + ldr x18, [sp, #8 * 18] + ldp x29, x30, [sp, #8 * 20] + + /* Restore registers elr_el1 & spsr_el1, using x0 & x1 as scratch. */ + ldp x0, x1, [sp, #8 * 22] + msr elr_el1, x0 + msr spsr_el1, x1 + + /* Restore x0 & x1, and release stack space. */ + ldp x0, x1, [sp], #8 * 24 +.endm + +/** + * This is a generic handler for exceptions taken at the current EL while using + * SP0. It behaves similarly to the SPx case by first switching to SPx, doing + * the work, then switching back to SP0 before returning. + * + * Switching to SPx and calling the Rust handler takes 16 instructions. To + * restore and return we need an additional 16 instructions, so we can implement + * the whole handler within the allotted 32 instructions. + */ +.macro current_exception_sp0 handler:req + msr spsel, #1 + save_volatile_to_stack + bl \handler + restore_volatile_from_stack + msr spsel, #0 + eret +.endm + +/** + * This is a generic handler for exceptions taken at the current EL while using + * SPx. It saves volatile registers, calls the Rust handler, restores volatile + * registers, then returns. + * + * This also works for exceptions taken from EL0, if we don't care about + * non-volatile registers. + * + * Saving state and jumping to the Rust handler takes 15 instructions, and + * restoring and returning also takes 15 instructions, so we can fit the whole + * handler in 30 instructions, under the limit of 32. + */ +.macro current_exception_spx handler:req + save_volatile_to_stack + bl \handler + restore_volatile_from_stack + eret +.endm + +.section .text.vector_table_el1, "ax" +.global vector_table_el1 +.balign 0x800 +vector_table_el1: +sync_cur_sp0: + current_exception_sp0 sync_exception_current + +.balign 0x80 +irq_cur_sp0: + current_exception_sp0 irq_current + +.balign 0x80 +fiq_cur_sp0: + current_exception_sp0 fiq_current + +.balign 0x80 +serr_cur_sp0: + current_exception_sp0 serr_current + +.balign 0x80 +sync_cur_spx: + current_exception_spx sync_exception_current + +.balign 0x80 +irq_cur_spx: + current_exception_spx irq_current + +.balign 0x80 +fiq_cur_spx: + current_exception_spx fiq_current + +.balign 0x80 +serr_cur_spx: + current_exception_spx serr_current + +.balign 0x80 +sync_lower_64: + current_exception_spx sync_lower + +.balign 0x80 +irq_lower_64: + current_exception_spx irq_lower + +.balign 0x80 +fiq_lower_64: + current_exception_spx fiq_lower + +.balign 0x80 +serr_lower_64: + current_exception_spx serr_lower + +.balign 0x80 +sync_lower_32: + current_exception_spx sync_lower + +.balign 0x80 +irq_lower_32: + current_exception_spx irq_lower + +.balign 0x80 +fiq_lower_32: + current_exception_spx fiq_lower + +.balign 0x80 +serr_lower_32: + current_exception_spx serr_lower diff --git a/src/bare-metal/aps/examples/idmap.S b/src/bare-metal/aps/examples/idmap.S new file mode 100644 index 0000000..a79f3af --- /dev/null +++ b/src/bare-metal/aps/examples/idmap.S @@ -0,0 +1,42 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.set .L_TT_TYPE_BLOCK, 0x1 +.set .L_TT_TYPE_PAGE, 0x3 +.set .L_TT_TYPE_TABLE, 0x3 + +/* Access flag. */ +.set .L_TT_AF, 0x1 << 10 +/* Not global. */ +.set .L_TT_NG, 0x1 << 11 +.set .L_TT_XN, 0x3 << 53 + +.set .L_TT_MT_DEV, 0x0 << 2 // MAIR #0 (DEV_nGnRE) +.set .L_TT_MT_MEM, (0x1 << 2) | (0x3 << 8) // MAIR #1 (MEM_WBWA), inner shareable + +.set .L_BLOCK_DEV, .L_TT_TYPE_BLOCK | .L_TT_MT_DEV | .L_TT_AF | .L_TT_XN +.set .L_BLOCK_MEM, .L_TT_TYPE_BLOCK | .L_TT_MT_MEM | .L_TT_AF | .L_TT_NG + +.section ".rodata.idmap", "a", %progbits +.global idmap +.align 12 +idmap: + /* level 1 */ + .quad .L_BLOCK_DEV | 0x0 // 1 GiB of device mappings + .quad .L_BLOCK_MEM | 0x40000000 // 1 GiB of DRAM + .fill 254, 8, 0x0 // 254 GiB of unmapped VA space + .quad .L_BLOCK_DEV | 0x4000000000 // 1 GiB of device mappings + .fill 255, 8, 0x0 // 255 GiB of remaining VA space diff --git a/src/bare-metal/aps/examples/image.ld b/src/bare-metal/aps/examples/image.ld new file mode 100644 index 0000000..59c7752 --- /dev/null +++ b/src/bare-metal/aps/examples/image.ld @@ -0,0 +1,104 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Code will start running at this symbol which is placed at the start of the + * image. + */ +ENTRY(entry) + +MEMORY +{ + image : ORIGIN = 0x40080000, LENGTH = 2M +} + +SECTIONS +{ + /* + * Collect together the code. + */ + .init : ALIGN(4096) { + text_begin = .; + *(.init.entry) + *(.init.*) + } >image + .text : { + *(.text.*) + } >image + text_end = .; + + /* + * Collect together read-only data. + */ + .rodata : ALIGN(4096) { + rodata_begin = .; + *(.rodata.*) + } >image + .got : { + *(.got) + } >image + rodata_end = .; + + /* + * Collect together the read-write data including .bss at the end which + * will be zero'd by the entry code. + */ + .data : ALIGN(4096) { + data_begin = .; + *(.data.*) + /* + * The entry point code assumes that .data is a multiple of 32 + * bytes long. + */ + . = ALIGN(32); + data_end = .; + } >image + + /* Everything beyond this point will not be included in the binary. */ + bin_end = .; + + /* The entry point code assumes that .bss is 16-byte aligned. */ + .bss : ALIGN(16) { + bss_begin = .; + *(.bss.*) + *(COMMON) + . = ALIGN(16); + bss_end = .; + } >image + + .stack (NOLOAD) : ALIGN(4096) { + boot_stack_begin = .; + . += 40 * 4096; + . = ALIGN(4096); + boot_stack_end = .; + } >image + + . = ALIGN(4K); + PROVIDE(dma_region = .); + + /* + * Remove unused sections from the image. + */ + /DISCARD/ : { + /* The image loads itself so doesn't need these sections. */ + *(.gnu.hash) + *(.hash) + *(.interp) + *(.eh_frame_hdr) + *(.eh_frame) + *(.note.gnu.build-id) + } +} diff --git a/src/bare-metal/aps/examples/src/exceptions.rs b/src/bare-metal/aps/examples/src/exceptions.rs new file mode 100644 index 0000000..4ad9038 --- /dev/null +++ b/src/bare-metal/aps/examples/src/exceptions.rs @@ -0,0 +1,65 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use log::error; +use smccc::psci::system_off; +use smccc::Hvc; + +#[no_mangle] +extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) { + error!("sync_exception_current"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn irq_current(_elr: u64, _spsr: u64) { + error!("irq_current"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn fiq_current(_elr: u64, _spsr: u64) { + error!("fiq_current"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn serr_current(_elr: u64, _spsr: u64) { + error!("serr_current"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn sync_lower(_elr: u64, _spsr: u64) { + error!("sync_lower"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn irq_lower(_elr: u64, _spsr: u64) { + error!("irq_lower"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn fiq_lower(_elr: u64, _spsr: u64) { + error!("fiq_lower"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn serr_lower(_elr: u64, _spsr: u64) { + error!("serr_lower"); + system_off::().unwrap(); +} diff --git a/src/bare-metal/aps/examples/src/logger.rs b/src/bare-metal/aps/examples/src/logger.rs new file mode 100644 index 0000000..8151949 --- /dev/null +++ b/src/bare-metal/aps/examples/src/logger.rs @@ -0,0 +1,54 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: main +use crate::pl011::Uart; +use core::fmt::Write; +use log::{LevelFilter, Log, Metadata, Record, SetLoggerError}; +use spin::mutex::SpinMutex; + +static LOGGER: Logger = Logger { + uart: SpinMutex::new(None), +}; + +struct Logger { + uart: SpinMutex>, +} + +impl Log for Logger { + fn enabled(&self, _metadata: &Metadata) -> bool { + true + } + + fn log(&self, record: &Record) { + writeln!( + self.uart.lock().as_mut().unwrap(), + "[{}] {}", + record.level(), + record.args() + ) + .unwrap(); + } + + fn flush(&self) {} +} + +/// Initialises UART logger. +pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), SetLoggerError> { + LOGGER.uart.lock().replace(uart); + + log::set_logger(&LOGGER)?; + log::set_max_level(max_level); + Ok(()) +} diff --git a/src/bare-metal/aps/examples/src/main_improved.rs b/src/bare-metal/aps/examples/src/main_improved.rs new file mode 100644 index 0000000..b31e495 --- /dev/null +++ b/src/bare-metal/aps/examples/src/main_improved.rs @@ -0,0 +1,63 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: main +#![no_main] +#![no_std] + +mod exceptions; +mod pl011; + +use crate::pl011::Uart; +use core::fmt::Write; +use core::panic::PanicInfo; +use log::error; +use smccc::psci::system_off; +use smccc::Hvc; + +/// Base address of the primary PL011 UART. +const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _; + +#[no_mangle] +extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { + // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device, + // and nothing else accesses that address range. + let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) }; + + writeln!(uart, "main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})").unwrap(); + + loop { + if let Some(b) = uart.read_byte() { + uart.write_byte(b); + match b { + b'\r' => { + uart.write_byte(b'\n'); + } + b'q' => break, + _ => {} + } + } + } + + writeln!(uart, "Bye!").unwrap(); + system_off::().unwrap(); +} +// ANCHOR_END: main + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + error!("{info}"); + system_off::().unwrap(); + loop {} +} diff --git a/src/bare-metal/aps/examples/src/main_logger.rs b/src/bare-metal/aps/examples/src/main_logger.rs new file mode 100644 index 0000000..10667fe --- /dev/null +++ b/src/bare-metal/aps/examples/src/main_logger.rs @@ -0,0 +1,52 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: main +#![no_main] +#![no_std] + +mod exceptions; +mod logger; +mod pl011; + +use crate::pl011::Uart; +use core::panic::PanicInfo; +use log::{error, info, LevelFilter}; +use smccc::psci::system_off; +use smccc::Hvc; + +/// Base address of the primary PL011 UART. +const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _; + +#[no_mangle] +extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { + // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device, + // and nothing else accesses that address range. + let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) }; + logger::init(uart, LevelFilter::Trace).unwrap(); + + info!("main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})"); + + assert_eq!(x1, 42); + + system_off::().unwrap(); +} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + error!("{info}"); + system_off::().unwrap(); + loop {} +} +// ANCHOR_END: main diff --git a/src/bare-metal/aps/examples/src/main_minimal.rs b/src/bare-metal/aps/examples/src/main_minimal.rs new file mode 100644 index 0000000..df56809 --- /dev/null +++ b/src/bare-metal/aps/examples/src/main_minimal.rs @@ -0,0 +1,49 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: main +#![no_main] +#![no_std] + +mod exceptions; +mod pl011_minimal; + +use crate::pl011_minimal::Uart; +use core::fmt::Write; +use core::panic::PanicInfo; +use log::error; +use smccc::psci::system_off; +use smccc::Hvc; + +/// Base address of the primary PL011 UART. +const PL011_BASE_ADDRESS: *mut u8 = 0x900_0000 as _; + +#[no_mangle] +extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { + // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device, + // and nothing else accesses that address range. + let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) }; + + writeln!(uart, "main({:#x}, {:#x}, {:#x}, {:#x})", x0, x1, x2, x3).unwrap(); + + system_off::().unwrap(); +} +// ANCHOR_END: main + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + error!("{}", info); + system_off::().unwrap(); + loop {} +} diff --git a/src/bare-metal/aps/examples/src/main_psci.rs b/src/bare-metal/aps/examples/src/main_psci.rs new file mode 100644 index 0000000..53377b9 --- /dev/null +++ b/src/bare-metal/aps/examples/src/main_psci.rs @@ -0,0 +1,51 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: main +#![no_main] +#![no_std] + +use core::arch::asm; +use core::panic::PanicInfo; + +mod exceptions; + +const PSCI_SYSTEM_OFF: u32 = 0x84000008; + +#[no_mangle] +extern "C" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) { + // Safe because this only uses the declared registers and doesn't do + // anything with memory. + unsafe { + asm!("hvc #0", + inout("w0") PSCI_SYSTEM_OFF => _, + inout("w1") 0 => _, + inout("w2") 0 => _, + inout("w3") 0 => _, + inout("w4") 0 => _, + inout("w5") 0 => _, + inout("w6") 0 => _, + inout("w7") 0 => _, + options(nomem, nostack) + ); + } + + loop {} +} +// ANCHOR_END: main + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} diff --git a/src/bare-metal/aps/examples/src/pl011.rs b/src/bare-metal/aps/examples/src/pl011.rs new file mode 100644 index 0000000..a633012 --- /dev/null +++ b/src/bare-metal/aps/examples/src/pl011.rs @@ -0,0 +1,166 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::fmt::{self, Write}; +use core::ptr::{addr_of, addr_of_mut}; + +// ANCHOR: Flags +use bitflags::bitflags; + +bitflags! { + /// Flags from the UART flag register. + #[repr(transparent)] + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + struct Flags: u16 { + /// Clear to send. + const CTS = 1 << 0; + /// Data set ready. + const DSR = 1 << 1; + /// Data carrier detect. + const DCD = 1 << 2; + /// UART busy transmitting data. + const BUSY = 1 << 3; + /// Receive FIFO is empty. + const RXFE = 1 << 4; + /// Transmit FIFO is full. + const TXFF = 1 << 5; + /// Receive FIFO is full. + const RXFF = 1 << 6; + /// Transmit FIFO is empty. + const TXFE = 1 << 7; + /// Ring indicator. + const RI = 1 << 8; + } +} +// ANCHOR_END: Flags + +bitflags! { + /// Flags from the UART Receive Status Register / Error Clear Register. + #[repr(transparent)] + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + struct ReceiveStatus: u16 { + /// Framing error. + const FE = 1 << 0; + /// Parity error. + const PE = 1 << 1; + /// Break error. + const BE = 1 << 2; + /// Overrun error. + const OE = 1 << 3; + } +} + +// ANCHOR: Registers +#[repr(C, align(4))] +struct Registers { + dr: u16, + _reserved0: [u8; 2], + rsr: ReceiveStatus, + _reserved1: [u8; 19], + fr: Flags, + _reserved2: [u8; 6], + ilpr: u8, + _reserved3: [u8; 3], + ibrd: u16, + _reserved4: [u8; 2], + fbrd: u8, + _reserved5: [u8; 3], + lcr_h: u8, + _reserved6: [u8; 3], + cr: u16, + _reserved7: [u8; 3], + ifls: u8, + _reserved8: [u8; 3], + imsc: u16, + _reserved9: [u8; 2], + ris: u16, + _reserved10: [u8; 2], + mis: u16, + _reserved11: [u8; 2], + icr: u16, + _reserved12: [u8; 2], + dmacr: u8, + _reserved13: [u8; 3], +} +// ANCHOR_END: Registers + +// ANCHOR: Uart +/// Driver for a PL011 UART. +#[derive(Debug)] +pub struct Uart { + registers: *mut Registers, +} + +impl Uart { + /// Constructs a new instance of the UART driver for a PL011 device at the + /// given base address. + /// + /// # Safety + /// + /// The given base address must point to the 8 MMIO control registers of a + /// PL011 device, which must be mapped into the address space of the process + /// as device memory and not have any other aliases. + pub unsafe fn new(base_address: *mut u32) -> Self { + Self { + registers: base_address as *mut Registers, + } + } + + /// Writes a single byte to the UART. + pub fn write_byte(&self, byte: u8) { + // Wait until there is room in the TX buffer. + while self.read_flag_register().contains(Flags::TXFF) {} + + // Safe because we know that self.registers points to the control + // registers of a PL011 device which is appropriately mapped. + unsafe { + // Write to the TX buffer. + addr_of_mut!((*self.registers).dr).write_volatile(byte.into()); + } + + // Wait until the UART is no longer busy. + while self.read_flag_register().contains(Flags::BUSY) {} + } + + /// Reads and returns a pending byte, or `None` if nothing has been received. + pub fn read_byte(&self) -> Option { + if self.read_flag_register().contains(Flags::RXFE) { + None + } else { + let data = unsafe { addr_of!((*self.registers).dr).read_volatile() }; + // TODO: Check for error conditions in bits 8-11. + Some(data as u8) + } + } + + fn read_flag_register(&self) -> Flags { + // Safe because we know that self.registers points to the control + // registers of a PL011 device which is appropriately mapped. + unsafe { addr_of!((*self.registers).fr).read_volatile() } + } +} +// ANCHOR_END: Uart + +impl Write for Uart { + fn write_str(&mut self, s: &str) -> fmt::Result { + for c in s.as_bytes() { + self.write_byte(*c); + } + Ok(()) + } +} + +// Safe because it just contains a pointer to device memory, which can be +// accessed from any context. +unsafe impl Send for Uart {} diff --git a/src/bare-metal/aps/examples/src/pl011_minimal.rs b/src/bare-metal/aps/examples/src/pl011_minimal.rs new file mode 100644 index 0000000..f747e20 --- /dev/null +++ b/src/bare-metal/aps/examples/src/pl011_minimal.rs @@ -0,0 +1,78 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: Example +const FLAG_REGISTER_OFFSET: usize = 0x18; +const FR_BUSY: u8 = 1 << 3; +const FR_TXFF: u8 = 1 << 5; + +/// Minimal driver for a PL011 UART. +#[derive(Debug)] +pub struct Uart { + base_address: *mut u8, +} + +impl Uart { + /// Constructs a new instance of the UART driver for a PL011 device at the + /// given base address. + /// + /// # Safety + /// + /// The given base address must point to the 8 MMIO control registers of a + /// PL011 device, which must be mapped into the address space of the process + /// as device memory and not have any other aliases. + pub unsafe fn new(base_address: *mut u8) -> Self { + Self { base_address } + } + + /// Writes a single byte to the UART. + pub fn write_byte(&self, byte: u8) { + // Wait until there is room in the TX buffer. + while self.read_flag_register() & FR_TXFF != 0 {} + + // Safe because we know that the base address points to the control + // registers of a PL011 device which is appropriately mapped. + unsafe { + // Write to the TX buffer. + self.base_address.write_volatile(byte); + } + + // Wait until the UART is no longer busy. + while self.read_flag_register() & FR_BUSY != 0 {} + } + + fn read_flag_register(&self) -> u8 { + // Safe because we know that the base address points to the control + // registers of a PL011 device which is appropriately mapped. + unsafe { self.base_address.add(FLAG_REGISTER_OFFSET).read_volatile() } + } +} +// ANCHOR_END: Example + +// ANCHOR: Traits +use core::fmt::{self, Write}; + +impl Write for Uart { + fn write_str(&mut self, s: &str) -> fmt::Result { + for c in s.as_bytes() { + self.write_byte(*c); + } + Ok(()) + } +} + +// Safe because it just contains a pointer to device memory, which can be +// accessed from any context. +unsafe impl Send for Uart {} +// ANCHOR_END: Traits diff --git a/src/bare-metal/aps/inline-assembly.md b/src/bare-metal/aps/inline-assembly.md new file mode 100644 index 0000000..f17bcca --- /dev/null +++ b/src/bare-metal/aps/inline-assembly.md @@ -0,0 +1,31 @@ +# Inline assembly + +Sometimes we need to use assembly to do things that aren't possible with Rust code. For example, +to make an HVC to tell the firmware to power off the system: + +```rust,editable,compile_fail +{{#include examples/src/main_psci.rs:main}} +``` + +(If you actually want to do this, use the [`smccc`][1] crate which has wrappers for all these functions.) + +
+ +* PSCI is the Arm Power State Coordination Interface, a standard set of functions to manage system + and CPU power states, among other things. It is implemented by EL3 firmware and hypervisors on + many systems. +* The `0 => _` syntax means initialise the register to 0 before running the inline assembly code, + and ignore its contents afterwards. We need to use `inout` rather than `in` because the call could + potentially clobber the contents of the registers. +* This `main` function needs to be `#[no_mangle]` and `extern "C"` because it is called from our + entry point in `entry.S`. +* `_x0`–`_x3` are the values of registers `x0`–`x3`, which are conventionally used by the bootloader + to pass things like a pointer to the device tree. According to the standard aarch64 calling + convention (which is what `extern "C"` specifies to use), registers `x0`–`x7` are used for the + first 8 arguments passed to a function, so `entry.S` doesn't need to do anything special except + make sure it doesn't change these registers. +* Run the example in QEMU with `make qemu_psci` under `src/bare-metal/aps/examples`. + +
+ +[1]: https://crates.io/crates/smccc diff --git a/src/bare-metal/aps/logging.md b/src/bare-metal/aps/logging.md new file mode 100644 index 0000000..8a72bab --- /dev/null +++ b/src/bare-metal/aps/logging.md @@ -0,0 +1,16 @@ +# Logging + +It would be nice to be able to use the logging macros from the [`log`][1] crate. We can do this by +implementing the `Log` trait. + +```rust,editable,compile_fail +{{#include examples/src/logger.rs:main}} +``` + +
+ +* The unwrap in `log` is safe because we initialise `LOGGER` before calling `set_logger`. + +
+ +[1]: https://crates.io/crates/log diff --git a/src/bare-metal/aps/logging/using.md b/src/bare-metal/aps/logging/using.md new file mode 100644 index 0000000..a2e1500 --- /dev/null +++ b/src/bare-metal/aps/logging/using.md @@ -0,0 +1,14 @@ +# Using it + +We need to initialise the logger before we use it. + +```rust,editable,compile_fail +{{#include ../examples/src/main_logger.rs:main}} +``` + +
+ +* Note that our panic handler can now log details of panics. +* Run the example in QEMU with `make qemu_logger` under `src/bare-metal/aps/examples`. + +
diff --git a/src/bare-metal/aps/mmio.md b/src/bare-metal/aps/mmio.md new file mode 100644 index 0000000..4c63731 --- /dev/null +++ b/src/bare-metal/aps/mmio.md @@ -0,0 +1,17 @@ +# Volatile memory access for MMIO + + * Use `pointer::read_volatile` and `pointer::write_volatile`. + * Never hold a reference. + * `addr_of!` lets you get fields of structs without creating an intermediate reference. + +
+ + * Volatile access: read or write operations may have side-effects, so prevent the compiler or + hardware from reordering, duplicating or eliding them. + * Usually if you write and then read, e.g. via a mutable reference, the compiler may assume that + the value read is the same as the value just written, and not bother actually reading memory. + * Some existing crates for volatile access to hardware do hold references, but this is unsound. + Whenever a reference exist, the compiler may choose to dereference it. + * Use the `addr_of!` macro to get struct field pointers from a pointer to the struct. + +
diff --git a/src/bare-metal/aps/other-projects.md b/src/bare-metal/aps/other-projects.md new file mode 100644 index 0000000..7f21289 --- /dev/null +++ b/src/bare-metal/aps/other-projects.md @@ -0,0 +1,11 @@ +# Other projects + + * [oreboot](https://github.com/oreboot/oreboot) + * "coreboot without the C" + * Supports x86, aarch64 and RISC-V. + * Relies on LinuxBoot rather than having many drivers itself. + * [Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials) + * Initialisation, UART driver, simple bootloader, JTAG, exception levels, exception handling, page tables + * Not all very well written, so beware. + * [`cargo-call-stack`](https://crates.io/crates/cargo-call-stack) + * Static analysis to determine maximum stack usage. diff --git a/src/bare-metal/aps/uart.md b/src/bare-metal/aps/uart.md new file mode 100644 index 0000000..e18933f --- /dev/null +++ b/src/bare-metal/aps/uart.md @@ -0,0 +1,24 @@ +# Let's write a UART driver + +The QEMU 'virt' machine has a [PL011][1] UART, so let's write a driver for that. + +```rust,editable +{{#include examples/src/pl011_minimal.rs:Example}} +``` + +
+ +* Note that `Uart::new` is unsafe while the other methods are safe. This is because as long as the + caller of `Uart::new` guarantees that its safety requirements are met (i.e. that there is only + ever one instance of the driver for a given UART, and nothing else aliasing its address space), + then it is always safe to call `write_byte` later because we can assume the necessary + preconditions. +* We could have done it the other way around (making `new` safe but `write_byte` unsafe), but that + would be much less convenient to use as every place that calls `write_byte` would need to reason + about the safety +* This is a common pattern for writing safe wrappers of unsafe code: moving the burden of proof for + soundness from a large number of places to a smaller number of places. + + + +[1]: https://developer.arm.com/documentation/ddi0183/g diff --git a/src/bare-metal/aps/uart/traits.md b/src/bare-metal/aps/uart/traits.md new file mode 100644 index 0000000..95b5f74 --- /dev/null +++ b/src/bare-metal/aps/uart/traits.md @@ -0,0 +1,14 @@ +# More traits + +We derived the `Debug` trait. It would be useful to implement a few more traits too. + +```rust,editable,compile_fail +{{#include ../examples/src/pl011_minimal.rs:Traits}} +``` + +
+ +* Implementing `Write` lets us use the `write!` and `writeln!` macros with our `Uart` type. +* Run the example in QEMU with `make qemu_minimal` under `src/bare-metal/aps/examples`. + +
diff --git a/src/bare-metal/microcontrollers.md b/src/bare-metal/microcontrollers.md new file mode 100644 index 0000000..17c9a2d --- /dev/null +++ b/src/bare-metal/microcontrollers.md @@ -0,0 +1,17 @@ +# Microcontrollers + +The `cortex_m_rt` crate provides (among other things) a reset handler for Cortex M microcontrollers. + +```rust,editable,compile_fail +{{#include microcontrollers/examples/src/bin/minimal.rs:Example}} +``` + +Next we'll look at how to access peripherals, with increasing levels of abstraction. + +
+ +* The `cortex_m_rt::entry` macro requires that the function have type `fn() -> !`, because returning + to the reset handler doesn't make sense. +* Run the example with `cargo embed --bin minimal` + +
diff --git a/src/bare-metal/microcontrollers/board-support.md b/src/bare-metal/microcontrollers/board-support.md new file mode 100644 index 0000000..a6b1a5f --- /dev/null +++ b/src/bare-metal/microcontrollers/board-support.md @@ -0,0 +1,23 @@ +# Board support crates + +Board support crates provide a further level of wrapping for a specific board for convenience. + +```rust,editable,compile_fail +{{#include examples/src/bin/board_support.rs:Example}} +``` + +
+ + * In this case the board support crate is just providing more useful names, and a bit of + initialisation. + * The crate may also include drivers for some on-board devices outside of the microcontroller + itself. + * `microbit-v2` includes a simple driver for the LED matrix. + +Run the example with: + +```sh +cargo embed --bin board_support +``` + +
diff --git a/src/bare-metal/microcontrollers/debugging.md b/src/bare-metal/microcontrollers/debugging.md new file mode 100644 index 0000000..6d8a22e --- /dev/null +++ b/src/bare-metal/microcontrollers/debugging.md @@ -0,0 +1,38 @@ +# Debugging + +Embed.toml: + +```toml +[default.general] +chip = "nrf52833_xxAA" + +[debug.gdb] +enabled = true +``` + +In one terminal under `src/bare-metal/microcontrollers/examples/`: + +```sh +cargo embed --bin board_support debug +``` + +In another terminal in the same directory: + +```sh +gdb-multiarch target/thumbv7em-none-eabihf/debug/board_support --eval-command="target remote :1337" +``` + +
+ +In GDB, try running: + +```gdb +b src/bin/board_support.rs:29 +b src/bin/board_support.rs:30 +b src/bin/board_support.rs:32 +c +c +c +``` + +
diff --git a/src/bare-metal/microcontrollers/embedded-hal.md b/src/bare-metal/microcontrollers/embedded-hal.md new file mode 100644 index 0000000..d1d325e --- /dev/null +++ b/src/bare-metal/microcontrollers/embedded-hal.md @@ -0,0 +1,23 @@ +# `embedded-hal` + +The [`embedded-hal`](https://crates.io/crates/embedded-hal) crate provides a number of traits +covering common microcontroller peripherals. + + * GPIO + * ADC + * I2C, SPI, UART, CAN + * RNG + * Timers + * Watchdogs + +Other crates then implement +[drivers](https://github.com/rust-embedded/awesome-embedded-rust#driver-crates) in terms of these +traits, e.g. an accelerometer driver might need an I2C or SPI bus implementation. + +
+ + * There are implementations for many microcontrollers, as well as other platforms such as Linux on +Raspberry Pi. + * There is work in progress on an `async` version of `embedded-hal`, but it isn't stable yet. + +
diff --git a/src/bare-metal/microcontrollers/examples/.cargo/config.toml b/src/bare-metal/microcontrollers/examples/.cargo/config.toml new file mode 100644 index 0000000..702b87d --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/.cargo/config.toml @@ -0,0 +1,5 @@ +[build] +target = "thumbv7em-none-eabihf" # Cortex-M4F + +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +rustflags = ["-C", "link-arg=-Tlink.x"] diff --git a/src/bare-metal/microcontrollers/examples/Cargo.lock b/src/bare-metal/microcontrollers/examples/Cargo.lock new file mode 100644 index 0000000..a8dd4bd --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/Cargo.lock @@ -0,0 +1,366 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bare-metal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bytemuck" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal 0.2.5", + "bitfield", + "embedded-hal", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "critical-section" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1706d332edc22aef4d9f23a6bb1c92360a403013c291af51247a737472dcae6" +dependencies = [ + "bare-metal 1.0.0", + "critical-section 1.1.1", +] + +[[package]] +name = "critical-section" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "embedded-dma" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c8c02e4347a0267ca60813c952017f4c5948c232474c6010a381a337f1bda4" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-storage" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723dce4e9f25b6e6c5f35628e144794e5b459216ed7da97b7c4b66cdb3fa82ca" + +[[package]] +name = "fixed" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f3be4cf4fc227d3a63bb77512a2b7d364200b2a715f389155785c4d3345495" +dependencies = [ + "az", + "bytemuck", + "half", + "typenum", +] + +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + +[[package]] +name = "microbit-common" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45651d001be4281a6f4536c30f3d8522f231bc56fd58d5baf2c630f565d31256" +dependencies = [ + "embedded-hal", + "nrf52833-hal", + "tiny-led-matrix", +] + +[[package]] +name = "microbit-v2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9895242259950730bc112623e4a2e37345dc51ddb5fc8878c110489260d84e7" +dependencies = [ + "microbit-common", +] + +[[package]] +name = "microcontroller-examples" +version = "0.1.0" +dependencies = [ + "cortex-m-rt", + "embedded-hal", + "microbit-v2", + "nrf52833-hal", + "nrf52833-pac", + "panic-halt", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.0.0", +] + +[[package]] +name = "nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" + +[[package]] +name = "nrf-hal-common" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd37b3fd039327b4005cc0d4ef20bce0a41bf521071774d5adb854e4b1230639" +dependencies = [ + "cast", + "cfg-if", + "cortex-m", + "embedded-dma", + "embedded-hal", + "embedded-storage", + "fixed", + "nb 1.0.0", + "nrf-usbd", + "nrf52833-pac", + "rand_core", + "void", +] + +[[package]] +name = "nrf-usbd" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "640e88d4c108743c667f03320d0c9ab24a20f183a7a1b18bde7891ee13fd92c5" +dependencies = [ + "bare-metal 1.0.0", + "cortex-m", + "critical-section 0.2.8", + "usb-device", + "vcell", +] + +[[package]] +name = "nrf52833-hal" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f76d269c9a239ffe24edaa5ee0972b102c04e898b464e3e9a12ab0eacd5f76" +dependencies = [ + "embedded-hal", + "nrf-hal-common", + "nrf52833-pac", +] + +[[package]] +name = "nrf52833-pac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd69bdb25903e18e098c040ef31dc863814437af010dea8bd55aa31f686cb461" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "vcell", +] + +[[package]] +name = "panic-halt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" + +[[package]] +name = "proc-macro2" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tiny-led-matrix" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a718c727b686154a7c7913f70d7ebc8956f701cbab466bc22035cb27f378882b" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "usb-device" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" +dependencies = [ + "vcell", +] diff --git a/src/bare-metal/microcontrollers/examples/Cargo.toml b/src/bare-metal/microcontrollers/examples/Cargo.toml new file mode 100644 index 0000000..7a48c62 --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/Cargo.toml @@ -0,0 +1,33 @@ +[workspace] + +[package] +name = "microcontroller-examples" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +cortex-m-rt = "0.7.3" +embedded-hal = "0.2.6" +microbit-v2 = "0.13.0" +nrf52833-hal = "0.14.1" +nrf52833-pac = { version = "0.10.1", features = ["rt"] } +panic-halt = "0.2.0" + +[[bin]] +name = "board_support" + +[[bin]] +name = "hal" + +[[bin]] +name = "minimal" + +[[bin]] +name = "mmio" + +[[bin]] +name = "pac" + +[[bin]] +name = "typestate" diff --git a/src/bare-metal/microcontrollers/examples/Embed.toml b/src/bare-metal/microcontrollers/examples/Embed.toml new file mode 100644 index 0000000..0f270ac --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/Embed.toml @@ -0,0 +1,8 @@ +[default.general] +chip = "nrf52833_xxAA" + +[debug.gdb] +enabled = true + +[debug.reset] +halt_afterwards = true diff --git a/src/bare-metal/microcontrollers/examples/src/bin/board_support.rs b/src/bare-metal/microcontrollers/examples/src/bin/board_support.rs new file mode 100644 index 0000000..3914845 --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/src/bin/board_support.rs @@ -0,0 +1,33 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: Example +#![no_main] +#![no_std] + +extern crate panic_halt as _; + +use cortex_m_rt::entry; +use microbit::hal::prelude::*; +use microbit::Board; + +#[entry] +fn main() -> ! { + let mut board = Board::take().unwrap(); + + board.display_pins.col1.set_low().unwrap(); + board.display_pins.row1.set_high().unwrap(); + + loop {} +} diff --git a/src/bare-metal/microcontrollers/examples/src/bin/hal.rs b/src/bare-metal/microcontrollers/examples/src/bin/hal.rs new file mode 100644 index 0000000..5b44d3f --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/src/bin/hal.rs @@ -0,0 +1,42 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: Example +#![no_main] +#![no_std] + +extern crate panic_halt as _; + +use cortex_m_rt::entry; +use nrf52833_hal::gpio::{p0, Level}; +use nrf52833_hal::pac::Peripherals; +use nrf52833_hal::prelude::*; + +#[entry] +fn main() -> ! { + let p = Peripherals::take().unwrap(); + + // Create HAL wrapper for GPIO port 0. + let gpio0 = p0::Parts::new(p.P0); + + // Configure GPIO 0 pins 21 and 28 as push-pull outputs. + let mut col1 = gpio0.p0_28.into_push_pull_output(Level::High); + let mut row1 = gpio0.p0_21.into_push_pull_output(Level::Low); + + // Set pin 28 low and pin 21 high to turn the LED on. + col1.set_low().unwrap(); + row1.set_high().unwrap(); + + loop {} +} diff --git a/src/bare-metal/microcontrollers/examples/src/bin/interrupts/mod.rs b/src/bare-metal/microcontrollers/examples/src/bin/interrupts/mod.rs new file mode 100644 index 0000000..2dc2402 --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/src/bin/interrupts/mod.rs @@ -0,0 +1,17 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[link_section = ".vector_table.interrupts"] +#[no_mangle] +pub static __INTERRUPTS: [usize; 1] = [0]; diff --git a/src/bare-metal/microcontrollers/examples/src/bin/minimal.rs b/src/bare-metal/microcontrollers/examples/src/bin/minimal.rs new file mode 100644 index 0000000..4ee5d7f --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/src/bin/minimal.rs @@ -0,0 +1,28 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: Example +#![no_main] +#![no_std] + +extern crate panic_halt as _; + +mod interrupts; + +use cortex_m_rt::entry; + +#[entry] +fn main() -> ! { + loop {} +} diff --git a/src/bare-metal/microcontrollers/examples/src/bin/mmio.rs b/src/bare-metal/microcontrollers/examples/src/bin/mmio.rs new file mode 100644 index 0000000..db973ea --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/src/bin/mmio.rs @@ -0,0 +1,68 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: Example +#![no_main] +#![no_std] + +extern crate panic_halt as _; + +mod interrupts; + +use core::mem::size_of; +use cortex_m_rt::entry; + +/// GPIO port 0 peripheral address +const GPIO_P0: usize = 0x5000_0000; + +// GPIO peripheral offsets +const PIN_CNF: usize = 0x700; +const OUTSET: usize = 0x508; +const OUTCLR: usize = 0x50c; + +// PIN_CNF fields +const DIR_OUTPUT: u32 = 0x1; +const INPUT_DISCONNECT: u32 = 0x1 << 1; +const PULL_DISABLED: u32 = 0x0 << 2; +const DRIVE_S0S1: u32 = 0x0 << 8; +const SENSE_DISABLED: u32 = 0x0 << 16; + +#[entry] +fn main() -> ! { + // Configure GPIO 0 pins 21 and 28 as push-pull outputs. + let pin_cnf_21 = (GPIO_P0 + PIN_CNF + 21 * size_of::()) as *mut u32; + let pin_cnf_28 = (GPIO_P0 + PIN_CNF + 28 * size_of::()) as *mut u32; + // Safe because the pointers are to valid peripheral control registers, and + // no aliases exist. + unsafe { + pin_cnf_21.write_volatile( + DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED, + ); + pin_cnf_28.write_volatile( + DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED, + ); + } + + // Set pin 28 low and pin 21 high to turn the LED on. + let gpio0_outset = (GPIO_P0 + OUTSET) as *mut u32; + let gpio0_outclr = (GPIO_P0 + OUTCLR) as *mut u32; + // Safe because the pointers are to valid peripheral control registers, and + // no aliases exist. + unsafe { + gpio0_outclr.write_volatile(1 << 28); + gpio0_outset.write_volatile(1 << 21); + } + + loop {} +} diff --git a/src/bare-metal/microcontrollers/examples/src/bin/pac.rs b/src/bare-metal/microcontrollers/examples/src/bin/pac.rs new file mode 100644 index 0000000..9b86cf3 --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/src/bin/pac.rs @@ -0,0 +1,52 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: Example +#![no_main] +#![no_std] + +extern crate panic_halt as _; + +use cortex_m_rt::entry; +use nrf52833_pac::Peripherals; + +#[entry] +fn main() -> ! { + let p = Peripherals::take().unwrap(); + let gpio0 = p.P0; + + // Configure GPIO 0 pins 21 and 28 as push-pull outputs. + gpio0.pin_cnf[21].write(|w| { + w.dir().output(); + w.input().disconnect(); + w.pull().disabled(); + w.drive().s0s1(); + w.sense().disabled(); + w + }); + gpio0.pin_cnf[28].write(|w| { + w.dir().output(); + w.input().disconnect(); + w.pull().disabled(); + w.drive().s0s1(); + w.sense().disabled(); + w + }); + + // Set pin 28 low and pin 21 high to turn the LED on. + gpio0.outclr.write(|w| w.pin28().clear()); + gpio0.outset.write(|w| w.pin21().set()); + + loop {} +} diff --git a/src/bare-metal/microcontrollers/examples/src/bin/typestate.rs b/src/bare-metal/microcontrollers/examples/src/bin/typestate.rs new file mode 100644 index 0000000..8ef87e4 --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/src/bin/typestate.rs @@ -0,0 +1,52 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![no_main] +#![no_std] + +extern crate panic_halt as _; + +use cortex_m_rt::entry; +use nrf52833_hal::gpio::p0::{self, P0_01, P0_02, P0_03}; +use nrf52833_hal::gpio::{ + Disconnected, Floating, Input, Level, OpenDrain, OpenDrainConfig, Output, PushPull, +}; +use nrf52833_hal::pac::Peripherals; +use nrf52833_hal::prelude::*; + +// ANCHOR: Example +#[entry] +fn main() -> ! { + let p = Peripherals::take().unwrap(); + let gpio0 = p0::Parts::new(p.P0); + + let pin: P0_01 = gpio0.p0_01; + + // let gpio0_01_again = gpio0.p0_01; // Error, moved. + let pin_input: P0_01> = pin.into_floating_input(); + if pin_input.is_high().unwrap() { + // ... + } + let mut pin_output: P0_01> = pin_input + .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low); + pin_output.set_high().unwrap(); + // pin_input.is_high(); // Error, moved. + + let _pin2: P0_02> = gpio0 + .p0_02 + .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low); + let _pin3: P0_03> = gpio0.p0_03.into_push_pull_output(Level::Low); + + loop {} +} diff --git a/src/bare-metal/microcontrollers/hals.md b/src/bare-metal/microcontrollers/hals.md new file mode 100644 index 0000000..642e0ad --- /dev/null +++ b/src/bare-metal/microcontrollers/hals.md @@ -0,0 +1,23 @@ +# HAL crates + +[HAL crates](https://github.com/rust-embedded/awesome-embedded-rust#hal-implementation-crates) for +many microcontrollers provide wrappers around various peripherals. These generally implement traits +from [`embedded-hal`](https://crates.io/crates/embedded-hal). + +```rust,editable,compile_fail +{{#include examples/src/bin/hal.rs:Example}} +``` + +
+ + * `set_low` and `set_high` are methods on the `embedded_hal` `OutputPin` trait. + * HAL crates exist for many Cortex-M and RISC-V devices, including various STM32, GD32, nRF, NXP, + MSP430, AVR and PIC microcontrollers. + +Run the example with: + +```sh +cargo embed --bin hal +``` + +
diff --git a/src/bare-metal/microcontrollers/mmio.md b/src/bare-metal/microcontrollers/mmio.md new file mode 100644 index 0000000..57f3711 --- /dev/null +++ b/src/bare-metal/microcontrollers/mmio.md @@ -0,0 +1,20 @@ +# Raw MMIO + +Most microcontrollers access peripherals via memory-mapped IO. Let's try turning on an LED on our +micro:bit: + +```rust,editable,compile_fail +{{#include examples/src/bin/mmio.rs:Example}} +``` + +
+ +* GPIO 0 pin 21 is connected to the first column of the LED matrix, and pin 28 to the first row. + +Run the example with: + +```sh +cargo embed --bin mmio +``` + +
diff --git a/src/bare-metal/microcontrollers/other-projects.md b/src/bare-metal/microcontrollers/other-projects.md new file mode 100644 index 0000000..d653c93 --- /dev/null +++ b/src/bare-metal/microcontrollers/other-projects.md @@ -0,0 +1,26 @@ +# Other projects + + * [RTIC](https://rtic.rs/) + * "Real-Time Interrupt-driven Concurrency" + * Shared resource management, message passing, task scheduling, timer queue + * [Embassy](https://embassy.dev/) + * `async` executors with priorities, timers, networking, USB + * [TockOS](https://www.tockos.org/documentation/getting-started) + * Security-focused RTOS with preemptive scheduling and Memory Protection Unit support + * [Hubris](https://hubris.oxide.computer/) + * Microkernel RTOS from Oxide Computer Company with memory protection, unprivileged drivers, IPC + * [Bindings for FreeRTOS](https://github.com/lobaro/FreeRTOS-rust) + * Some platforms have `std` implementations, e.g. + [esp-idf](https://esp-rs.github.io/book/overview/using-the-standard-library.html). + +
+ + * RTIC can be considered either an RTOS or a concurrency framework. + * It doesn't include any HALs. + * It uses the Cortex-M NVIC (Nested Virtual Interrupt Controller) for scheduling rather than a + proper kernel. + * Cortex-M only. + * Google uses TockOS on the Haven microcontroller for Titan security keys. + * FreeRTOS is mostly written in C, but there are Rust bindings for writing applications. + +
diff --git a/src/bare-metal/microcontrollers/pacs.md b/src/bare-metal/microcontrollers/pacs.md new file mode 100644 index 0000000..86e0b0d --- /dev/null +++ b/src/bare-metal/microcontrollers/pacs.md @@ -0,0 +1,29 @@ +# Peripheral Access Crates + +[`svd2rust`](https://crates.io/crates/svd2rust) generates mostly-safe Rust wrappers for +memory-mapped peripherals from [CMSIS-SVD](https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html) +files. + +```rust,editable,compile_fail +{{#include examples/src/bin/pac.rs:Example}} +``` + +
+ +* SVD (System View Description) files are XML files typically provided by silicon vendors which + describe the memory map of the device. + * They are organised by peripheral, register, field and value, with names, descriptions, addresses + and so on. + * SVD files are often buggy and incomplete, so there are various projects which patch the + mistakes, add missing details, and publish the generated crates. +* `cortex-m-rt` provides the vector table, among other things. +* If you `cargo install cargo-binutils` then you can run + `cargo objdump --bin pac -- -d --no-show-raw-insn` to see the resulting binary. + +Run the example with: + +```sh +cargo embed --bin pac +``` + +
diff --git a/src/bare-metal/microcontrollers/probe-rs.md b/src/bare-metal/microcontrollers/probe-rs.md new file mode 100644 index 0000000..a995477 --- /dev/null +++ b/src/bare-metal/microcontrollers/probe-rs.md @@ -0,0 +1,29 @@ +# `probe-rs`, `cargo-embed` + +[probe-rs](https://probe.rs/) is a handy toolset for embedded debugging, like OpenOCD but better +integrated. + +* SWD and JTAG via CMSIS-DAP, ST-Link and J-Link probes +* GDB stub and Microsoft DAP server +* Cargo integration + +`cargo-embed` is a cargo subcommand to build and flash binaries, log +RTT output and connect GDB. It's configured by an +`Embed.toml` file in your project directory. + +
+ +* [CMSIS-DAP](https://arm-software.github.io/CMSIS_5/DAP/html/index.html) is an Arm standard + protocol over USB for an in-circuit debugger to access the CoreSight Debug Access Port of various + Arm Cortex processors. It's what the on-board debugger on the BBC micro:bit uses. +* ST-Link is a range of in-circuit debuggers from ST Microelectronics, J-Link is a range from + SEGGER. +* The Debug Access Port is usually either a 5-pin JTAG interface or 2-pin Serial Wire Debug. +* probe-rs is a library which you can integrate into your own tools if you want to. +* The [Microsoft Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/) lets + VSCode and other IDEs debug code running on any supported microcontroller. +* cargo-embed is a binary built using the probe-rs library. +* RTT (Real Time Transfers) is a mechanism to transfer data between the debug host and the target + through a number of ringbuffers. + +
diff --git a/src/bare-metal/microcontrollers/type-state.md b/src/bare-metal/microcontrollers/type-state.md new file mode 100644 index 0000000..5829b17 --- /dev/null +++ b/src/bare-metal/microcontrollers/type-state.md @@ -0,0 +1,20 @@ +# The type state pattern + +```rust,editable,compile_fail +{{#include examples/src/bin/typestate.rs:Example}} +``` + +
+ + * Pins don't implement `Copy` or `Clone`, so only one instance of each can exist. Once a pin is + moved out of the port struct nobody else can take it. + * Changing the configuration of a pin consumes the old pin instance, so you can’t keep use the old + instance afterwards. + * The type of a value indicates the state that it is in: e.g. in this case, the configuration state + of a GPIO pin. This encodes the state machine into the type system, and ensures that you don't + try to use a pin in a certain way without properly configuring it first. Illegal state + transitions are caught at compile time. + * You can call `is_high` on an input pin and `set_high` on an output pin, but not vice-versa. + * Many HAL crates follow this pattern. + +
diff --git a/src/bare-metal/minimal.md b/src/bare-metal/minimal.md new file mode 100644 index 0000000..d96ff34 --- /dev/null +++ b/src/bare-metal/minimal.md @@ -0,0 +1,26 @@ +# A minimal `no_std` program + +```rust,editable,compile_fail +#![no_main] +#![no_std] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_panic: &PanicInfo) -> ! { + loop {} +} +``` + +
+ +* This will compile to an empty binary. +* `std` provides a panic handler; without it we must provide our own. +* It can also be provided by another crate, such as `panic-halt`. +* Depending on the target, you may need to compile with `panic = "abort"` to avoid an error about + `eh_personality`. +* Note that there is no `main` or any other entry point; it's up to you to define your own entry + point. This will typically involve a linker script and some assembly code to set things up ready + for Rust code to run. + +
diff --git a/src/bare-metal/no_std.md b/src/bare-metal/no_std.md new file mode 100644 index 0000000..9ea4d5d --- /dev/null +++ b/src/bare-metal/no_std.md @@ -0,0 +1,65 @@ +# `no_std` + + + + + + + + + + + + +
+ +`core` + + + +`alloc` + + + +`std` + +
+ +* Slices, `&str`, `CStr` +* `NonZeroU8`... +* `Option`, `Result` +* `Display`, `Debug`, `write!`... +* `Iterator` +* `panic!`, `assert_eq!`... +* `NonNull` and all the usual pointer-related functions +* `Future` and `async`/`await` +* `fence`, `AtomicBool`, `AtomicPtr`, `AtomicU32`... +* `Duration` + + + +* `Box`, `Cow`, `Arc`, `Rc` +* `Vec`, `BinaryHeap`, `BtreeMap`, `LinkedList`, `VecDeque` +* `String`, `CString`, `format!` + + + +* `Error` +* `HashMap` +* `Mutex`, `Condvar`, `Barrier`, `Once`, `RwLock`, `mpsc` +* `File` and the rest of `fs` +* `println!`, `Read`, `Write`, `Stdin`, `Stdout` and the rest of `io` +* `Path`, `OsString` +* `net` +* `Command`, `Child`, `ExitCode` +* `spawn`, `sleep` and the rest of `thread` +* `SystemTime`, `Instant` + +
+ +
+ +* `HashMap` depends on RNG. +* `std` re-exports the contents of both `core` and `alloc`. + +
diff --git a/src/bare-metal/useful-crates.md b/src/bare-metal/useful-crates.md new file mode 100644 index 0000000..d544efe --- /dev/null +++ b/src/bare-metal/useful-crates.md @@ -0,0 +1,3 @@ +# Useful crates + +We'll go over a few crates which solve some common problems in bare-metal programming. diff --git a/src/bare-metal/useful-crates/aarch64-paging.md b/src/bare-metal/useful-crates/aarch64-paging.md new file mode 100644 index 0000000..1d80978 --- /dev/null +++ b/src/bare-metal/useful-crates/aarch64-paging.md @@ -0,0 +1,36 @@ +# `aarch64-paging` + +The [`aarch64-paging`][1] crate lets you create page tables according to the AArch64 Virtual Memory +System Architecture. + +```rust,editable,compile_fail +use aarch64_paging::{ + idmap::IdMap, + paging::{Attributes, MemoryRegion}, +}; + +const ASID: usize = 1; +const ROOT_LEVEL: usize = 1; + +// Create a new page table with identity mapping. +let mut idmap = IdMap::new(ASID, ROOT_LEVEL); +// Map a 2 MiB region of memory as read-only. +idmap.map_range( + &MemoryRegion::new(0x80200000, 0x80400000), + Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY, +).unwrap(); +// Set `TTBR0_EL1` to activate the page table. +idmap.activate(); +``` + +
+ +* For now it only supports EL1, but support for other exception levels should be straightforward to + add. +* This is used in Android for the [Protected VM Firmware][2]. +* There's no easy way to run this example, as it needs to run on real hardware or under QEMU. + +
+ +[1]: https://crates.io/crates/aarch64-paging +[2]: https://cs.android.com/android/platform/superproject/+/master:packages/modules/Virtualization/pvmfw/ diff --git a/src/bare-metal/useful-crates/allocator-example/Cargo.toml b/src/bare-metal/useful-crates/allocator-example/Cargo.toml new file mode 100644 index 0000000..0d0c7b1 --- /dev/null +++ b/src/bare-metal/useful-crates/allocator-example/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "allocator-example" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +buddy_system_allocator = "0.9.0" diff --git a/src/bare-metal/useful-crates/allocator-example/src/main.rs b/src/bare-metal/useful-crates/allocator-example/src/main.rs new file mode 100644 index 0000000..73f36be --- /dev/null +++ b/src/bare-metal/useful-crates/allocator-example/src/main.rs @@ -0,0 +1,28 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: main +use buddy_system_allocator::FrameAllocator; +use core::alloc::Layout; + +fn main() { + let mut allocator = FrameAllocator::<32>::new(); + allocator.add_frame(0x200_0000, 0x400_0000); + + let layout = Layout::from_size_align(0x100, 0x100).unwrap(); + let bar = allocator + .alloc_aligned(layout) + .expect("Failed to allocate 0x100 byte MMIO region"); + println!("Allocated 0x100 byte MMIO region at {:#x}", bar); +} diff --git a/src/bare-metal/useful-crates/buddy_system_allocator.md b/src/bare-metal/useful-crates/buddy_system_allocator.md new file mode 100644 index 0000000..61efb6a --- /dev/null +++ b/src/bare-metal/useful-crates/buddy_system_allocator.md @@ -0,0 +1,23 @@ +# `buddy_system_allocator` + +[`buddy_system_allocator`][1] is a third-party crate implementing a basic buddy system allocator. +It can be used both for [`LockedHeap`][2] implementing [`GlobalAlloc`][3] so you can use the +standard `alloc` crate (as we saw [before][4]), or for allocating other address space. For example, +we might want to allocate MMIO space for PCI BARs: + +```rust,editable,compile_fail +{{#include allocator-example/src/main.rs:main}} +``` + +
+ +* PCI BARs always have alignment equal to their size. +* Run the example with `cargo run` under `src/bare-metal/useful-crates/allocator-example/`. (It won't + run in the Playground because of the crate dependency.) + +
+ +[1]: https://crates.io/crates/buddy_system_allocator +[2]: https://docs.rs/buddy_system_allocator/0.9.0/buddy_system_allocator/struct.LockedHeap.html +[3]: https://doc.rust-lang.org/core/alloc/trait.GlobalAlloc.html +[4]: ../alloc.md diff --git a/src/bare-metal/useful-crates/spin.md b/src/bare-metal/useful-crates/spin.md new file mode 100644 index 0000000..77ded7d --- /dev/null +++ b/src/bare-metal/useful-crates/spin.md @@ -0,0 +1,33 @@ +# `spin` + +`std::sync::Mutex` and the other synchronisation primitives from `std::sync` are not available in +`core` or `alloc`. How can we manage synchronisation or interior mutability, such as for sharing +state between different CPUs? + +The [`spin`][1] crate provides spinlock-based equivalents of many of these primitives. + +```rust,editable,compile_fail +use spin::mutex::SpinMutex; + +static counter: SpinMutex = SpinMutex::new(0); + +fn main() { + println!("count: {}", counter.lock()); + *counter.lock() += 2; + println!("count: {}", counter.lock()); +} +``` + +
+ +* Be careful to avoid deadlock if you take locks in interrupt handlers. +* `spin` also has a ticket lock mutex implementation; equivalents of `RwLock`, `Barrier` and `Once` + from `std::sync`; and `Lazy` for lazy initialisation. +* The [`once_cell`][2] crate also has some useful types for late initialisation with a slightly + different approach to `spin::once::Once`. +* The Rust Playground includes `spin`, so this example will run fine inline. + +
+ +[1]: https://crates.io/crates/spin +[2]: https://crates.io/crates/once_cell diff --git a/src/bare-metal/useful-crates/tinyvec.md b/src/bare-metal/useful-crates/tinyvec.md new file mode 100644 index 0000000..5522fd6 --- /dev/null +++ b/src/bare-metal/useful-crates/tinyvec.md @@ -0,0 +1,28 @@ +# `tinyvec` + +Sometimes you want something which can be resized like a `Vec`, but without heap allocation. +[`tinyvec`][1] provides this: a vector backed by an array or slice, which could be statically +allocated or on the stack, which keeps track of how many elements are used and panics if you try to +use more than are allocated. + +```rust,editable,compile_fail +use tinyvec::{array_vec, ArrayVec}; + +fn main() { + let mut numbers: ArrayVec<[u32; 5]> = array_vec!(42, 66); + println!("{numbers:?}"); + numbers.push(7); + println!("{numbers:?}"); + numbers.remove(1); + println!("{numbers:?}"); +} +``` + +
+ +* `tinyvec` requires that the element type implement `Default` for initialisation. +* The Rust Playground includes `tinyvec`, so this example will run fine inline. + +
+ +[1]: https://crates.io/crates/tinyvec diff --git a/src/bare-metal/useful-crates/zerocopy-example/Cargo.toml b/src/bare-metal/useful-crates/zerocopy-example/Cargo.toml new file mode 100644 index 0000000..f64cf03 --- /dev/null +++ b/src/bare-metal/useful-crates/zerocopy-example/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "zerocopy-example" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +zerocopy = "0.6.1" diff --git a/src/bare-metal/useful-crates/zerocopy-example/src/main.rs b/src/bare-metal/useful-crates/zerocopy-example/src/main.rs new file mode 100644 index 0000000..06841b6 --- /dev/null +++ b/src/bare-metal/useful-crates/zerocopy-example/src/main.rs @@ -0,0 +1,46 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: main +use zerocopy::AsBytes; + +#[repr(u32)] +#[derive(AsBytes, Debug, Default)] +enum RequestType { + #[default] + In = 0, + Out = 1, + Flush = 4, +} + +#[repr(C)] +#[derive(AsBytes, Debug, Default)] +struct VirtioBlockRequest { + request_type: RequestType, + reserved: u32, + sector: u64, +} + +fn main() { + let request = VirtioBlockRequest { + request_type: RequestType::Flush, + sector: 42, + ..Default::default() + }; + + assert_eq!( + request.as_bytes(), + &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0] + ); +} diff --git a/src/bare-metal/useful-crates/zerocopy.md b/src/bare-metal/useful-crates/zerocopy.md new file mode 100644 index 0000000..fe3df8a --- /dev/null +++ b/src/bare-metal/useful-crates/zerocopy.md @@ -0,0 +1,25 @@ +# `zerocopy` + +The [`zerocopy`][1] crate (from Fuchsia) provides traits and macros for safely converting between +byte sequences and other types. + +```rust,editable,compile_fail +{{#include zerocopy-example/src/main.rs:main}} +``` + +This is not suitable for MMIO (as it doesn't use volatile reads and writes), but can be useful for +working with structures shared with hardware e.g. by DMA, or sent over some external interface. + +
+ +* `FromBytes` can be implemented for types for which any byte pattern is valid, and so can safely be + converted from an untrusted sequence of bytes. +* Attempting to derive `FromBytes` for these types would fail, because `RequestType` doesn't use all + possible u32 values as discriminants, so not all byte patterns are valid. +* `zerocopy::byteorder` has types for byte-order aware numeric primitives. +* Run the example with `cargo run` under `src/bare-metal/useful-crates/zerocopy-example/`. (It won't + run in the Playground because of the crate dependency.) + +
+ +[1]: https://docs.rs/zerocopy/ diff --git a/src/basic-syntax/functions-interlude.md b/src/basic-syntax/functions-interlude.md index da58ca4..caa1706 100644 --- a/src/basic-syntax/functions-interlude.md +++ b/src/basic-syntax/functions-interlude.md @@ -27,5 +27,5 @@ fn main() { * When using generics, the standard library's `Into` can provide a kind of limited polymorphism on argument types. We will see more details in a later section. - +
diff --git a/src/basic-syntax/functions.md b/src/basic-syntax/functions.md index 705911e..3858f5e 100644 --- a/src/basic-syntax/functions.md +++ b/src/basic-syntax/functions.md @@ -4,28 +4,28 @@ A Rust version of the famous [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz) ```rust,editable fn main() { - fizzbuzz_to(20); // Defined below, no forward declaration needed + print_fizzbuzz_to(20); } -fn is_divisible_by(lhs: u32, rhs: u32) -> bool { - if rhs == 0 { - return false; // Corner case, early return +fn is_divisible(n: u32, divisor: u32) -> bool { + if divisor == 0 { + return false; } - lhs % rhs == 0 // The last expression in a block is the return value + n % divisor == 0 } -fn fizzbuzz(n: u32) -> () { // No return value means returning the unit type `()` - match (is_divisible_by(n, 3), is_divisible_by(n, 5)) { - (true, true) => println!("fizzbuzz"), - (true, false) => println!("fizz"), - (false, true) => println!("buzz"), - (false, false) => println!("{n}"), +fn fizzbuzz(n: u32) -> String { + let fizz = if is_divisible(n, 3) { "fizz" } else { "" }; + let buzz = if is_divisible(n, 5) { "buzz" } else { "" }; + if fizz.is_empty() && buzz.is_empty() { + return format!("{n}"); } + format!("{fizz}{buzz}") } -fn fizzbuzz_to(n: u32) { // `-> ()` is normally omitted +fn print_fizzbuzz_to(n: u32) { for i in 1..=n { - fizzbuzz(i); + println!("{}", fizzbuzz(i)); } } ``` @@ -36,19 +36,6 @@ fn fizzbuzz_to(n: u32) { // `-> ()` is normally omitted * Declaration parameters are followed by a type (the reverse of some programming languages), then a return type. * The last expression in a function body (or any block) becomes the return value. Simply omit the `;` at the end of the expression. * Some functions have no return value, and return the 'unit type', `()`. The compiler will infer this if the `-> ()` return type is omitted. -* The range expression in the `for` loop in `fizzbuzz_to()` contains `=n`, which causes it to include the upper bound. -* The `match` expression in `fizzbuzz()` is doing a lot of work. It is expanded below to show what is happening. - - (Type annotations added for clarity, but they can be elided.) - - ```rust,ignore - let by_3: bool = is_divisible_by(n, 3); - let by_5: bool = is_divisible_by(n, 5); - let by_35: (bool, bool) = (by_3, by_5); - match by_35 { - // ... - ``` - - +* The range expression in the `for` loop in `print_fizzbuzz_to()` contains `=n`, which causes it to include the upper bound. diff --git a/src/basic-syntax/methods.md b/src/basic-syntax/methods.md index d11d294..5294d88 100644 --- a/src/basic-syntax/methods.md +++ b/src/basic-syntax/methods.md @@ -1,7 +1,7 @@ # Methods -Rust has methods, they are simply functions that are associated with a particular type. The -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 +an instance of the type it is associated with: ```rust,editable struct Rectangle { @@ -28,3 +28,18 @@ fn main() { ``` * We will look much more at methods in today's exercise and in tomorrow's class. + +
+ +- Add a `Rectangle::new` constructor and call this from `main`: + + ```rust,editable,compile_fail + fn new(width: u32, height: u32) -> Rectangle { + Rectangle { width, height } + } + ``` + +- Add a `Rectangle::new_square(width: u32)` constructor to illustrate that + constructors can take arbitrary parameters. + +
diff --git a/src/basic-syntax/rustdoc.md b/src/basic-syntax/rustdoc.md new file mode 100644 index 0000000..484d435 --- /dev/null +++ b/src/basic-syntax/rustdoc.md @@ -0,0 +1,33 @@ +# Rustdoc + +All language items in Rust can be documented using special `///` syntax. + +```rust,editable +/// Determine whether the first argument is divisible by the second argument. +/// +/// If the second argument is zero, the result is false. +fn is_divisible_by(lhs: u32, rhs: u32) -> bool { + if rhs == 0 { + return false; // Corner case, early return + } + lhs % rhs == 0 // The last expression in a block is the return value +} +``` + +The contents are treated as Markdown. All published Rust library crates are +automatically documented at [`docs.rs`](https://docs.rs) using the +[rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It is +idiomatic to document all public items in an API using this pattern. + +
+ +* Show students the generated docs for the `rand` crate at + [`docs.rs/rand`](https://docs.rs/rand). + +* This course does not include rustdoc on slides, just to save space, but in + real code they should be present. + +* Inner doc comments are discussed later (in the page on modules) and need not + be addressed here. + +
diff --git a/src/basic-syntax/scalar-types.md b/src/basic-syntax/scalar-types.md index 2c34786..506f26b 100644 --- a/src/basic-syntax/scalar-types.md +++ b/src/basic-syntax/scalar-types.md @@ -5,9 +5,8 @@ | Signed integers | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `-10`, `0`, `1_000`, `123i64` | | Unsigned integers | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `0`, `123`, `10u16` | | Floating point numbers | `f32`, `f64` | `3.14`, `-10.0e20`, `2f32` | -| Strings | `&str` | `"foo"`, `r#"\\"#` | +| Strings | `&str` | `"foo"`, `"two\nlines"` | | Unicode scalar values | `char` | `'a'`, `'α'`, `'∞'` | -| Byte strings | `&[u8]` | `b"abc"`, `br#" " "#` | | Booleans | `bool` | `true`, `false` | The types have widths as follows: @@ -16,3 +15,29 @@ The types have widths as follows: * `isize` and `usize` are the width of a pointer, * `char` is 32 bit wide, * `bool` is 8 bit wide. + +
+ +There are a few syntaxes which are not shown above: + +- Raw strings allow you to create a `&str` value with escapes disabled: `r"\n" + == "\\\\n"`. You can embed double-quotes by using an equal amount of `#` on + either side of the quotes: + + ```rust,editable + fn main() { + println!(r#"link"#); + println!("link"); + } + ``` + +- Byte strings allow you to create a `&[u8]` value directly: + + ```rust,editable + fn main() { + println!("{:?}", b"abc"); + println!("{:?}", &[97, 98, 99]); + } + ``` + +
diff --git a/src/concurrency.md b/src/concurrency.md index d6bc5e3..5668336 100644 --- a/src/concurrency.md +++ b/src/concurrency.md @@ -1,4 +1,4 @@ -# Fearless Concurrency +# Welcome to Concurrency in Rust Rust has full support for concurrency using OS threads with mutexes and channels. diff --git a/src/concurrency/send-sync/send.md b/src/concurrency/send-sync/send.md index 8aa1be2..934ab3c 100644 --- a/src/concurrency/send-sync/send.md +++ b/src/concurrency/send-sync/send.md @@ -7,3 +7,10 @@ in that thread. So the question is when you can allocate a value in one thread and deallocate it in another. [1]: https://doc.rust-lang.org/std/marker/trait.Send.html + +
+ +As an example, a connection to the SQLite library must only be accessed from a +single thread. + +
diff --git a/src/concurrency/shared_state/arc.md b/src/concurrency/shared_state/arc.md index 8a5201d..c214706 100644 --- a/src/concurrency/shared_state/arc.md +++ b/src/concurrency/shared_state/arc.md @@ -1,6 +1,6 @@ # `Arc` -[`Arc`][1] allows shared read-only access via its `clone` method: +[`Arc`][1] allows shared read-only access via `Arc::clone`: ```rust,editable use std::thread; @@ -10,7 +10,7 @@ fn main() { let v = Arc::new(vec![10, 20, 30]); let mut handles = Vec::new(); for _ in 1..5 { - let v = v.clone(); + let v = Arc::clone(&v); handles.push(thread::spawn(move || { let thread_id = thread::current().id(); println!("{thread_id:?}: {v:?}"); diff --git a/src/concurrency/shared_state/example.md b/src/concurrency/shared_state/example.md index 8c559ff..0cbb1a7 100644 --- a/src/concurrency/shared_state/example.md +++ b/src/concurrency/shared_state/example.md @@ -7,7 +7,7 @@ use std::thread; // use std::sync::{Arc, Mutex}; fn main() { - let mut v = vec![10, 20, 30]; + let v = vec![10, 20, 30]; let handle = thread::spawn(|| { v.push(10); }); @@ -29,7 +29,7 @@ use std::thread; fn main() { let v = Arc::new(Mutex::new(vec![10, 20, 30])); - let v2 = v.clone(); + let v2 = Arc::clone(&v); let handle = thread::spawn(move || { let mut v2 = v2.lock().unwrap(); v2.push(10); @@ -42,10 +42,7 @@ fn main() { handle.join().unwrap(); - { - let v = v.lock().unwrap(); - println!("v: {v:?}"); - } + println!("v: {v:?}"); } ``` @@ -55,6 +52,5 @@ Notable parts: * Wrapping a `Mutex` in an `Arc` is a common pattern to share mutable state between threads. * `v: Arc<_>` needs to be cloned as `v2` before it can be moved into another thread. Note `move` was added to the lambda signature. * Blocks are introduced to narrow the scope of the `LockGuard` as much as possible. -* We still need to acquire the `Mutex` to print our `Vec`. diff --git a/src/control-flow/break-continue.md b/src/control-flow/break-continue.md index 5f7cd83..aac48a4 100644 --- a/src/control-flow/break-continue.md +++ b/src/control-flow/break-continue.md @@ -1,8 +1,11 @@ # `break` and `continue` -If you want to exit a loop early, use `break`, if you want to immediately start -the next iteration use `continue`. Both `continue` and `break` can optionally -take a label argument which is used to break out of nested loops: +- If you want to exit a loop early, use [`break`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions), +- If you want to immediately start +the next iteration use [`continue`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions). + +Both `continue` and `break` can optionally take a label argument which is used +to break out of nested loops: ```rust,editable fn main() { diff --git a/src/control-flow/for-expressions.md b/src/control-flow/for-expressions.md index b80f234..3f2b037 100644 --- a/src/control-flow/for-expressions.md +++ b/src/control-flow/for-expressions.md @@ -1,6 +1,7 @@ -# `for` expressions +# `for` loops -The `for` expression is closely related to the `while let` expression. It will +The [`for` loop](https://doc.rust-lang.org/std/keyword.for.html) is closely +related to the [`while let` loop](while-let-expression.md). It will automatically call `into_iter()` on the expression and then iterate over it: ```rust,editable diff --git a/src/control-flow/if-expressions.md b/src/control-flow/if-expressions.md index 1c7d86e..3a45e4c 100644 --- a/src/control-flow/if-expressions.md +++ b/src/control-flow/if-expressions.md @@ -1,6 +1,8 @@ # `if` expressions -You use `if` very similarly to how you would in other languages: +You use [`if` +expressions](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-expressions) +exactly like `if` statements in other languages: ```rust,editable fn main() { @@ -13,7 +15,9 @@ fn main() { } ``` -In addition, you can use it as an expression. This does the same as above: +In addition, you can use `if` as an expression. The last expression of each +block becomes the value of the `if` expression: + ```rust,editable fn main() { diff --git a/src/control-flow/if-let-expressions.md b/src/control-flow/if-let-expressions.md index 9c9a9c6..61b72af 100644 --- a/src/control-flow/if-let-expressions.md +++ b/src/control-flow/if-let-expressions.md @@ -1,6 +1,8 @@ # `if let` expressions -If you want to match a value against a pattern, you can use `if let`: +The [`if let` +expression](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-let-expressions) +lets you execute different code depending on whether a value matches a pattern: ```rust,editable fn main() { @@ -19,8 +21,21 @@ Rust.
* `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. - * For the similar use case consider demonstrating a newly stabilized [`let else`](https://github.com/rust-lang/rust/pull/93628) feature. * A common usage is handling `Some` values when working with `Option`. * Unlike `match`, `if let` does not support guard clauses for pattern matching. +* Since 1.65, a similar [let-else](https://doc.rust-lang.org/rust-by-example/flow_control/let_else.html) construct allows to do a destructuring assignment, or if it fails, have a non-returning block branch (panic/return/break/continue): + + ```rust,editable + fn main() { + println!("{:?}", second_word_to_upper("foo bar")); + } + + fn second_word_to_upper(s: &str) -> Option { + let mut it = s.split(' '); + let (Some(_), Some(item)) = (it.next(), it.next()) else { + return None; + }; + Some(item.to_uppercase()) + }
diff --git a/src/control-flow/loop-expressions.md b/src/control-flow/loop-expressions.md index 01990d6..faaecdb 100644 --- a/src/control-flow/loop-expressions.md +++ b/src/control-flow/loop-expressions.md @@ -1,7 +1,9 @@ # `loop` expressions -Finally, there is a `loop` keyword which creates an endless loop. Here you must -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) +which creates an endless loop. + +Here you must either `break` or `return` to stop the loop: ```rust,editable fn main() { @@ -23,5 +25,8 @@ fn main() {
* Break the `loop` with a value (e.g. `break 8`) and print it out. +* Note that `loop` is the only looping construct which returns a non-trivial + value. This is because it's guaranteed to be entered at least once (unlike + `while` and `for` loops).
diff --git a/src/control-flow/match-expressions.md b/src/control-flow/match-expressions.md index fb156b0..b410ca7 100644 --- a/src/control-flow/match-expressions.md +++ b/src/control-flow/match-expressions.md @@ -1,7 +1,8 @@ # `match` expressions -The `match` keyword is used to match a value against one or more patterns. In -that sense, it works like a series of `if let` expressions: +The [`match` keyword](https://doc.rust-lang.org/reference/expressions/match-expr.html) +is used to match a value against one or more patterns. In that sense, it works +like a series of `if let` expressions: ```rust,editable fn main() { diff --git a/src/control-flow/while-expressions.md b/src/control-flow/while-expressions.md index 9ff51d0..1ad351e 100644 --- a/src/control-flow/while-expressions.md +++ b/src/control-flow/while-expressions.md @@ -1,6 +1,7 @@ -# `while` expressions +# `while` loops -The `while` keyword works very similar to other languages: +The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops) +works very similar to other languages: ```rust,editable fn main() { diff --git a/src/control-flow/while-let-expressions.md b/src/control-flow/while-let-expressions.md index 4f75053..477952f 100644 --- a/src/control-flow/while-let-expressions.md +++ b/src/control-flow/while-let-expressions.md @@ -1,7 +1,7 @@ -# `while let` expressions +# `while let` loops -Like with `if`, there is a `while let` variant which repeatedly tests a value -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) +variant which repeatedly tests a value against a pattern: ```rust,editable fn main() { @@ -21,7 +21,6 @@ return `None`. The `while let` lets us keep iterating through all items. See [pattern matching](../pattern-matching.md) for more details on patterns in Rust. -
* Point out that the `while let` loop will keep going as long as the value matches the pattern. diff --git a/src/enums/sizes.md b/src/enums/sizes.md index 465ef62..32d2d5b 100644 --- a/src/enums/sizes.md +++ b/src/enums/sizes.md @@ -65,91 +65,91 @@ Key Points: types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees that `size_of::()` equals `size_of::>()`. -Example code if you want to show how the bitwise representation *may* look like in practice. -It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally unsafe. + Example code if you want to show how the bitwise representation *may* look like in practice. + It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally unsafe. -```rust,editable -use std::mem::transmute; - -macro_rules! dbg_bits { - ($e:expr, $bit_type:ty) => { - println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e)); - }; -} + ```rust,editable + use std::mem::transmute; -fn main() { - // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise - // representation of types. - unsafe { - println!("Bitwise representation of bool"); - dbg_bits!(false, u8); - dbg_bits!(true, u8); - - println!("Bitwise representation of Option"); - dbg_bits!(None::, u8); - dbg_bits!(Some(false), u8); - dbg_bits!(Some(true), u8); - - println!("Bitwise representation of Option>"); - dbg_bits!(Some(Some(false)), u8); - dbg_bits!(Some(Some(true)), u8); - dbg_bits!(Some(None::), u8); - dbg_bits!(None::>, u8); - - println!("Bitwise representation of Option<&i32>"); - dbg_bits!(None::<&i32>, usize); - dbg_bits!(Some(&0i32), usize); - } -} -``` + macro_rules! dbg_bits { + ($e:expr, $bit_type:ty) => { + println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e)); + }; + } -More complex example if you want to discuss what happens when we chain more than 256 `Option`s together. + fn main() { + // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise + // representation of types. + unsafe { + println!("Bitwise representation of bool"); + dbg_bits!(false, u8); + dbg_bits!(true, u8); + + println!("Bitwise representation of Option"); + dbg_bits!(None::, u8); + dbg_bits!(Some(false), u8); + dbg_bits!(Some(true), u8); + + println!("Bitwise representation of Option>"); + dbg_bits!(Some(Some(false)), u8); + dbg_bits!(Some(Some(true)), u8); + dbg_bits!(Some(None::), u8); + dbg_bits!(None::>, u8); + + println!("Bitwise representation of Option<&i32>"); + dbg_bits!(None::<&i32>, usize); + dbg_bits!(Some(&0i32), usize); + } + } + ``` -```rust,editable -#![recursion_limit = "1000"] + More complex example if you want to discuss what happens when we chain more than 256 `Option`s together. -use std::mem::transmute; + ```rust,editable + #![recursion_limit = "1000"] -macro_rules! dbg_bits { - ($e:expr, $bit_type:ty) => { - println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e)); - }; -} + use std::mem::transmute; + + macro_rules! dbg_bits { + ($e:expr, $bit_type:ty) => { + println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e)); + }; + } -// Macro to wrap a value in 2^n Some() where n is the number of "@" signs. -// Increasing the recursion limit is required to evaluate this macro. -macro_rules! many_options { - ($value:expr) => { Some($value) }; - ($value:expr, @) => { - Some(Some($value)) - }; - ($value:expr, @ $($more:tt)+) => { - many_options!(many_options!($value, $($more)+), $($more)+) - }; -} + // Macro to wrap a value in 2^n Some() where n is the number of "@" signs. + // Increasing the recursion limit is required to evaluate this macro. + macro_rules! many_options { + ($value:expr) => { Some($value) }; + ($value:expr, @) => { + Some(Some($value)) + }; + ($value:expr, @ $($more:tt)+) => { + many_options!(many_options!($value, $($more)+), $($more)+) + }; + } -fn main() { - // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise - // representation of types. - unsafe { - assert_eq!(many_options!(false), Some(false)); - assert_eq!(many_options!(false, @), Some(Some(false))); - assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false))))); - - println!("Bitwise representation of a chain of 128 Option's."); - dbg_bits!(many_options!(false, @@@@@@@), u8); - dbg_bits!(many_options!(true, @@@@@@@), u8); - - println!("Bitwise representation of a chain of 256 Option's."); - dbg_bits!(many_options!(false, @@@@@@@@), u16); - dbg_bits!(many_options!(true, @@@@@@@@), u16); - - println!("Bitwise representation of a chain of 257 Option's."); - dbg_bits!(many_options!(Some(false), @@@@@@@@), u16); - dbg_bits!(many_options!(Some(true), @@@@@@@@), u16); - dbg_bits!(many_options!(None::, @@@@@@@@), u16); - } -} -``` + fn main() { + // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise + // representation of types. + unsafe { + assert_eq!(many_options!(false), Some(false)); + assert_eq!(many_options!(false, @), Some(Some(false))); + assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false))))); + + println!("Bitwise representation of a chain of 128 Option's."); + dbg_bits!(many_options!(false, @@@@@@@), u8); + dbg_bits!(many_options!(true, @@@@@@@), u8); + + println!("Bitwise representation of a chain of 256 Option's."); + dbg_bits!(many_options!(false, @@@@@@@@), u16); + dbg_bits!(many_options!(true, @@@@@@@@), u16); + + println!("Bitwise representation of a chain of 257 Option's."); + dbg_bits!(many_options!(Some(false), @@@@@@@@), u16); + dbg_bits!(many_options!(Some(true), @@@@@@@@), u16); + dbg_bits!(many_options!(None::, @@@@@@@@), u16); + } + } + ```
diff --git a/src/error-handling/converting-error-types-example.md b/src/error-handling/converting-error-types-example.md index 378ea95..9cbd687 100644 --- a/src/error-handling/converting-error-types-example.md +++ b/src/error-handling/converting-error-types-example.md @@ -17,8 +17,8 @@ impl Error for ReadUsernameError {} impl Display for ReadUsernameError { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Self::IoError(e) => write!(f, "IO error: {}", e), - Self::EmptyUsername(filename) => write!(f, "Found no username in {}", filename), + Self::IoError(e) => write!(f, "IO error: {e}"), + Self::EmptyUsername(filename) => write!(f, "Found no username in {filename}"), } } } diff --git a/src/error-handling/error-contexts.md b/src/error-handling/error-contexts.md index bb676d3..50fb594 100644 --- a/src/error-handling/error-contexts.md +++ b/src/error-handling/error-contexts.md @@ -12,7 +12,7 @@ use anyhow::{Context, Result, bail}; fn read_username(path: &str) -> Result { let mut username = String::with_capacity(100); fs::File::open(path) - .context(format!("Failed to open {path}"))? + .with_context(|| format!("Failed to open {path}"))? .read_to_string(&mut username) .context("Failed to read")?; if username.is_empty() { diff --git a/src/error-handling/panic-unwind.md b/src/error-handling/panic-unwind.md index 6eaf6d3..beada98 100644 --- a/src/error-handling/panic-unwind.md +++ b/src/error-handling/panic-unwind.md @@ -2,7 +2,7 @@ By default, a panic will cause the stack to unwind. The unwinding can be caught: -```rust +```rust,editable use std::panic; let result = panic::catch_unwind(|| { diff --git a/src/error-handling/result.md b/src/error-handling/result.md index c9e8942..0a6740e 100644 --- a/src/error-handling/result.md +++ b/src/error-handling/result.md @@ -3,7 +3,7 @@ We have already seen the `Result` enum. This is used pervasively when errors are expected as part of normal operation: -```rust +```rust,editable use std::fs::File; use std::io::Read; diff --git a/src/error-handling/try-operator.md b/src/error-handling/try-operator.md index 02ad6d1..049a5d8 100644 --- a/src/error-handling/try-operator.md +++ b/src/error-handling/try-operator.md @@ -24,17 +24,15 @@ use std::io::{self, Read}; fn read_username(path: &str) -> Result { let username_file_result = fs::File::open(path); - let mut username_file = match username_file_result { Ok(file) => file, - Err(e) => return Err(e), + Err(err) => return Err(err), }; let mut username = String::new(); - match username_file.read_to_string(&mut username) { Ok(_) => Ok(username), - Err(e) => Err(e), + Err(err) => Err(err), } } diff --git a/src/exercises/Cargo.toml b/src/exercises/Cargo.toml index 584fff6..72c3e58 100644 --- a/src/exercises/Cargo.toml +++ b/src/exercises/Cargo.toml @@ -34,13 +34,16 @@ path = "day-3/simple-gui.rs" [[bin]] name = "dining-philosophers" -path = "day-4/dining-philosophers.rs" +path = "concurrency/dining-philosophers.rs" [[bin]] name = "link-checker" -path = "day-4/link-checker.rs" +path = "concurrency/link-checker.rs" [dependencies] reqwest = { version = "0.11.12", features = ["blocking"] } -scraper = "0.13.0" +scraper = "0.15.0" thiserror = "1.0.37" + +[dev-dependencies] +tempfile = "3.5.0" diff --git a/src/exercises/day-4/afternoon.md b/src/exercises/android/morning.md similarity index 69% rename from src/exercises/day-4/afternoon.md rename to src/exercises/android/morning.md index 21ada64..b339b3b 100644 --- a/src/exercises/day-4/afternoon.md +++ b/src/exercises/android/morning.md @@ -1,7 +1,7 @@ # Exercises -For the last exercise, we will look at one of the projects you work with. Let us -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 +try to integrate some Rust into it. Some suggestions: * Call your AIDL service with a client written in Rust. diff --git a/src/exercises/bare-metal/afternoon.md b/src/exercises/bare-metal/afternoon.md new file mode 100644 index 0000000..c69d106 --- /dev/null +++ b/src/exercises/bare-metal/afternoon.md @@ -0,0 +1,11 @@ +# Exercises + +We will write a driver for the PL031 real-time clock device. + +
+ +After looking at the exercises, you can look at the [solutions] provided. + +[solutions]: solutions-afternoon.md + +
diff --git a/src/exercises/bare-metal/compass.md b/src/exercises/bare-metal/compass.md new file mode 100644 index 0000000..ec3e5cf --- /dev/null +++ b/src/exercises/bare-metal/compass.md @@ -0,0 +1,79 @@ +# Compass + +We will read the direction from an I2C compass, and log the readings to a serial port. If you have +time, try displaying it on the LEDs somehow too, or use the buttons somehow. + +Hints: + +- Check the documentation for the [`lsm303agr`](https://docs.rs/lsm303agr/latest/lsm303agr/) and + [`microbit-v2`](https://docs.rs/microbit-v2/latest/microbit/) crates, as well as the + [micro:bit hardware](https://tech.microbit.org/hardware/). +- The LSM303AGR Inertial Measurement Unit is connected to the internal I2C bus. +- TWI is another name for I2C, so the I2C master peripheral is called TWIM. +- The LSM303AGR driver needs something implementing the `embedded_hal::blocking::i2c::WriteRead` + trait. The + [`microbit::hal::Twim`](https://docs.rs/microbit-v2/latest/microbit/hal/struct.Twim.html) struct + implements this. +- You have a [`microbit::Board`](https://docs.rs/microbit-v2/latest/microbit/struct.Board.html) + struct with fields for the various pins and peripherals. +- You can also look at the + [nRF52833 datasheet](https://infocenter.nordicsemi.com/pdf/nRF52833_PS_v1.5.pdf) if you want, but + it shouldn't be necessary for this exercise. + +Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the `compass` +directory for the following files. + +`src/main.rs`: + + + +```rust,compile_fail +{{#include compass/src/main.rs:top}} +use microbit::{hal::uarte::{Baudrate, Parity, Uarte}, Board}; + +{{#include compass/src/main.rs:main}} + // TODO + +{{#include compass/src/main.rs:loop}} + // TODO + } +} +``` + +`Cargo.toml` (you shouldn't need to change this): + + + +```toml +{{#include compass/Cargo.toml}} +``` + +`Embed.toml` (you shouldn't need to change this): + + + +```toml +{{#include compass/Embed.toml}} +``` + +`.cargo/config.toml` (you shouldn't need to change this): + + + +```toml +{{#include compass/.cargo/config.toml}} +``` + +See the serial output on Linux with: + +```sh +picocom --baud 115200 --imap lfcrlf /dev/ttyACM0 +``` + +Or on Mac OS something like (the device name may be slightly different): + +```sh +picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502 +``` + +Use Ctrl+A Ctrl+Q to quit picocom. diff --git a/src/exercises/bare-metal/compass/.cargo/config.toml b/src/exercises/bare-metal/compass/.cargo/config.toml new file mode 100644 index 0000000..702b87d --- /dev/null +++ b/src/exercises/bare-metal/compass/.cargo/config.toml @@ -0,0 +1,5 @@ +[build] +target = "thumbv7em-none-eabihf" # Cortex-M4F + +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +rustflags = ["-C", "link-arg=-Tlink.x"] diff --git a/src/exercises/bare-metal/compass/Cargo.lock b/src/exercises/bare-metal/compass/Cargo.lock new file mode 100644 index 0000000..8be7e31 --- /dev/null +++ b/src/exercises/bare-metal/compass/Cargo.lock @@ -0,0 +1,375 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bare-metal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bytemuck" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "compass" +version = "0.1.0" +dependencies = [ + "cortex-m-rt", + "embedded-hal", + "lsm303agr", + "microbit-v2", + "panic-halt", +] + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal 0.2.5", + "bitfield", + "embedded-hal", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "critical-section" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1706d332edc22aef4d9f23a6bb1c92360a403013c291af51247a737472dcae6" +dependencies = [ + "bare-metal 1.0.0", + "critical-section 1.1.1", +] + +[[package]] +name = "critical-section" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "embedded-dma" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c8c02e4347a0267ca60813c952017f4c5948c232474c6010a381a337f1bda4" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-storage" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723dce4e9f25b6e6c5f35628e144794e5b459216ed7da97b7c4b66cdb3fa82ca" + +[[package]] +name = "fixed" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f3be4cf4fc227d3a63bb77512a2b7d364200b2a715f389155785c4d3345495" +dependencies = [ + "az", + "bytemuck", + "half", + "typenum", +] + +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + +[[package]] +name = "lsm303agr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aab0b8c3a75dfdebe9f79c738458da139e8111207d176e9fb6b360117432ac4f" +dependencies = [ + "embedded-hal", + "nb 1.0.0", +] + +[[package]] +name = "microbit-common" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45651d001be4281a6f4536c30f3d8522f231bc56fd58d5baf2c630f565d31256" +dependencies = [ + "embedded-hal", + "nrf52833-hal", + "tiny-led-matrix", +] + +[[package]] +name = "microbit-v2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9895242259950730bc112623e4a2e37345dc51ddb5fc8878c110489260d84e7" +dependencies = [ + "microbit-common", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.0.0", +] + +[[package]] +name = "nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" + +[[package]] +name = "nrf-hal-common" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd37b3fd039327b4005cc0d4ef20bce0a41bf521071774d5adb854e4b1230639" +dependencies = [ + "cast", + "cfg-if", + "cortex-m", + "embedded-dma", + "embedded-hal", + "embedded-storage", + "fixed", + "nb 1.0.0", + "nrf-usbd", + "nrf52833-pac", + "rand_core", + "void", +] + +[[package]] +name = "nrf-usbd" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "640e88d4c108743c667f03320d0c9ab24a20f183a7a1b18bde7891ee13fd92c5" +dependencies = [ + "bare-metal 1.0.0", + "cortex-m", + "critical-section 0.2.8", + "usb-device", + "vcell", +] + +[[package]] +name = "nrf52833-hal" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f76d269c9a239ffe24edaa5ee0972b102c04e898b464e3e9a12ab0eacd5f76" +dependencies = [ + "embedded-hal", + "nrf-hal-common", + "nrf52833-pac", +] + +[[package]] +name = "nrf52833-pac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd69bdb25903e18e098c040ef31dc863814437af010dea8bd55aa31f686cb461" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "vcell", +] + +[[package]] +name = "panic-halt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" + +[[package]] +name = "proc-macro2" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tiny-led-matrix" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a718c727b686154a7c7913f70d7ebc8956f701cbab466bc22035cb27f378882b" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "usb-device" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" +dependencies = [ + "vcell", +] diff --git a/src/exercises/bare-metal/compass/Cargo.toml b/src/exercises/bare-metal/compass/Cargo.toml new file mode 100644 index 0000000..072ad64 --- /dev/null +++ b/src/exercises/bare-metal/compass/Cargo.toml @@ -0,0 +1,14 @@ +[workspace] + +[package] +name = "compass" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +cortex-m-rt = "0.7.3" +embedded-hal = "0.2.6" +lsm303agr = "0.2.2" +microbit-v2 = "0.13.0" +panic-halt = "0.2.0" diff --git a/src/exercises/bare-metal/compass/Embed.toml b/src/exercises/bare-metal/compass/Embed.toml new file mode 100644 index 0000000..0f270ac --- /dev/null +++ b/src/exercises/bare-metal/compass/Embed.toml @@ -0,0 +1,8 @@ +[default.general] +chip = "nrf52833_xxAA" + +[debug.gdb] +enabled = true + +[debug.reset] +halt_afterwards = true diff --git a/src/exercises/bare-metal/compass/src/main.rs b/src/exercises/bare-metal/compass/src/main.rs new file mode 100644 index 0000000..854975c --- /dev/null +++ b/src/exercises/bare-metal/compass/src/main.rs @@ -0,0 +1,156 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: top +#![no_main] +#![no_std] + +extern crate panic_halt as _; + +use core::fmt::Write; +use cortex_m_rt::entry; +// ANCHOR_END: top +use core::cmp::{max, min}; +use lsm303agr::{AccelOutputDataRate, Lsm303agr, MagOutputDataRate}; +use microbit::display::blocking::Display; +use microbit::hal::prelude::*; +use microbit::hal::twim::Twim; +use microbit::hal::uarte::{Baudrate, Parity, Uarte}; +use microbit::hal::Timer; +use microbit::pac::twim0::frequency::FREQUENCY_A; +use microbit::Board; + +const COMPASS_SCALE: i32 = 30000; +const ACCELEROMETER_SCALE: i32 = 700; + +// ANCHOR: main +#[entry] +fn main() -> ! { + let board = Board::take().unwrap(); + + // Configure serial port. + let mut serial = Uarte::new( + board.UARTE0, + board.uart.into(), + Parity::EXCLUDED, + Baudrate::BAUD115200, + ); + + // Set up the I2C controller and Inertial Measurement Unit. + // ANCHOR_END: main + writeln!(serial, "Setting up IMU...").unwrap(); + let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100); + let mut imu = Lsm303agr::new_with_i2c(i2c); + imu.init().unwrap(); + imu.set_mag_odr(MagOutputDataRate::Hz50).unwrap(); + imu.set_accel_odr(AccelOutputDataRate::Hz50).unwrap(); + let mut imu = imu.into_mag_continuous().ok().unwrap(); + + // Set up display and timer. + let mut timer = Timer::new(board.TIMER0); + let mut display = Display::new(board.display_pins); + + let mut mode = Mode::Compass; + let mut button_pressed = false; + + // ANCHOR: loop + writeln!(serial, "Ready.").unwrap(); + + loop { + // Read compass data and log it to the serial port. + // ANCHOR_END: loop + while !(imu.mag_status().unwrap().xyz_new_data + && imu.accel_status().unwrap().xyz_new_data) + {} + let compass_reading = imu.mag_data().unwrap(); + let accelerometer_reading = imu.accel_data().unwrap(); + writeln!( + serial, + "{},{},{}\t{},{},{}", + compass_reading.x, + compass_reading.y, + compass_reading.z, + accelerometer_reading.x, + accelerometer_reading.y, + accelerometer_reading.z, + ) + .unwrap(); + + let mut image = [[0; 5]; 5]; + let (x, y) = match mode { + Mode::Compass => ( + scale(-compass_reading.x, -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize, + scale(compass_reading.y, -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize, + ), + Mode::Accelerometer => ( + scale( + accelerometer_reading.x, + -ACCELEROMETER_SCALE, + ACCELEROMETER_SCALE, + 0, + 4, + ) as usize, + scale( + -accelerometer_reading.y, + -ACCELEROMETER_SCALE, + ACCELEROMETER_SCALE, + 0, + 4, + ) as usize, + ), + }; + image[y][x] = 255; + display.show(&mut timer, image, 100); + + // If button A is pressed, switch to the next mode and briefly blink all LEDs on. + if board.buttons.button_a.is_low().unwrap() { + if !button_pressed { + mode = mode.next(); + display.show(&mut timer, [[255; 5]; 5], 200); + } + button_pressed = true; + } else { + button_pressed = false; + } + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +enum Mode { + Compass, + Accelerometer, +} + +impl Mode { + fn next(self) -> Self { + match self { + Self::Compass => Self::Accelerometer, + Self::Accelerometer => Self::Compass, + } + } +} + +fn scale(value: i32, min_in: i32, max_in: i32, min_out: i32, max_out: i32) -> i32 { + let range_in = max_in - min_in; + let range_out = max_out - min_out; + cap( + min_out + range_out * (value - min_in) / range_in, + min_out, + max_out, + ) +} + +fn cap(value: i32, min_value: i32, max_value: i32) -> i32 { + max(min_value, min(value, max_value)) +} diff --git a/src/exercises/bare-metal/morning.md b/src/exercises/bare-metal/morning.md new file mode 100644 index 0000000..e4c01bc --- /dev/null +++ b/src/exercises/bare-metal/morning.md @@ -0,0 +1,11 @@ +# Exercises + +We will read the direction from an I2C compass, and log the readings to a serial port. + +
+ +After looking at the exercises, you can look at the [solutions] provided. + +[solutions]: solutions-morning.md + +
diff --git a/src/exercises/bare-metal/rtc.md b/src/exercises/bare-metal/rtc.md new file mode 100644 index 0000000..609f697 --- /dev/null +++ b/src/exercises/bare-metal/rtc.md @@ -0,0 +1,130 @@ +# RTC driver + +The QEMU aarch64 virt machine has a [PL031][1] real-time clock at 0x9010000. For this exercise, you +should write a driver for it. + +1. Use it to print the current time to the serial console. You can use the [`chrono`][2] crate for + date/time formatting. +2. Use the match register and raw interrupt status to busy-wait until a given time, e.g. 3 seconds + in the future. (Call [`core::hint::spin_loop`][3] inside the loop.) +3. _Extension if you have time:_ Enable and handle the interrupt generated by the RTC match. You can + use the driver provided in the [`arm-gic`][4] crate to configure the Arm Generic Interrupt Controller. + - Use the RTC interrupt, which is wired to the GIC as `IntId::spi(2)`. + - 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. + + +Download the [exercise template](../../comprehensive-rust-exercises.zip) and look in the `rtc` +directory for the following files. + +`src/main.rs`: + + + +```rust,compile_fail +{{#include rtc/src/main.rs:top}} + +{{#include rtc/src/main.rs:imports}} + +{{#include rtc/src/main.rs:main}} + + // TODO: Create instance of RTC driver and print current time. + + // TODO: Wait for 3 seconds. + +{{#include rtc/src/main.rs:main_end}} +``` + +`src/exceptions.rs` (you should only need to change this for the 3rd part of the exercise): + + + +```rust,compile_fail +{{#include rtc/src/exceptions.rs}} +``` + +`src/logger.rs` (you shouldn't need to change this): + + + +```rust,compile_fail +{{#include rtc/src/logger.rs}} +``` + +`src/pl011.rs` (you shouldn't need to change this): + + + +```rust,compile_fail +{{#include rtc/src/pl011.rs}} +``` + +`Cargo.toml` (you shouldn't need to change this): + + + +```toml +{{#include rtc/Cargo.toml}} +``` + +`build.rs` (you shouldn't need to change this): + + + +```rust,compile_fail +{{#include rtc/build.rs}} +``` + +`entry.S` (you shouldn't need to change this): + + + +```armasm +{{#include rtc/entry.S}} +``` + +`exceptions.S` (you shouldn't need to change this): + + + +```armasm +{{#include rtc/exceptions.S}} +``` + +`idmap.S` (you shouldn't need to change this): + + + +```armasm +{{#include rtc/idmap.S}} +``` + +`image.ld` (you shouldn't need to change this): + + + +```ld +{{#include rtc/image.ld}} +``` + +`Makefile` (you shouldn't need to change this): + + + +```makefile +{{#include rtc/Makefile}} +``` + +`.cargo/config.toml` (you shouldn't need to change this): + + + +```toml +{{#include rtc/.cargo/config.toml}} +``` + +Run the code in QEMU with `make qemu`. + +[1]: https://developer.arm.com/documentation/ddi0224/c +[2]: https://crates.io/crates/chrono +[3]: https://doc.rust-lang.org/core/hint/fn.spin_loop.html +[4]: https://docs.rs/arm-gic/ diff --git a/src/exercises/bare-metal/rtc/.cargo/config.toml b/src/exercises/bare-metal/rtc/.cargo/config.toml new file mode 100644 index 0000000..ffecab4 --- /dev/null +++ b/src/exercises/bare-metal/rtc/.cargo/config.toml @@ -0,0 +1,3 @@ +[build] +target = "aarch64-unknown-none" +rustflags = ["-C", "link-arg=-Timage.ld"] diff --git a/src/exercises/bare-metal/rtc/Cargo.lock b/src/exercises/bare-metal/rtc/Cargo.lock new file mode 100644 index 0000000..699de5a --- /dev/null +++ b/src/exercises/bare-metal/rtc/Cargo.lock @@ -0,0 +1,118 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arm-gic" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16805d71f41d1714a51ee34f40633c42980a2afaf8ae237bcba09d6e15494ef" +dependencies = [ + "bitflags", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c70beb79cbb5ce9c4f8e20849978f34225931f665bb49efa6982875a4d5facb3" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "rtc" +version = "0.1.0" +dependencies = [ + "arm-gic", + "bitflags", + "cc", + "chrono", + "log", + "smccc", + "spin", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "smccc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617d17f088ec733e5a6b86da6ce4cce1414e6e856d6061c16dda51cceae6f68c" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] diff --git a/src/exercises/bare-metal/rtc/Cargo.toml b/src/exercises/bare-metal/rtc/Cargo.toml new file mode 100644 index 0000000..b263c26 --- /dev/null +++ b/src/exercises/bare-metal/rtc/Cargo.toml @@ -0,0 +1,18 @@ +[workspace] + +[package] +name = "rtc" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +arm-gic = "0.1.0" +bitflags = "2.0.0" +chrono = { version = "0.4.24", default-features = false } +log = "0.4.17" +smccc = "0.1.1" +spin = "0.9.8" + +[build-dependencies] +cc = "1.0.73" diff --git a/src/exercises/bare-metal/rtc/Makefile b/src/exercises/bare-metal/rtc/Makefile new file mode 100644 index 0000000..b281bf1 --- /dev/null +++ b/src/exercises/bare-metal/rtc/Makefile @@ -0,0 +1,38 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +UNAME := $(shell uname -s) +ifeq ($(UNAME),Linux) + TARGET = aarch64-linux-gnu +else + TARGET = aarch64-none-elf +endif +OBJCOPY = $(TARGET)-objcopy + +.PHONY: build qemu_minimal qemu qemu_logger + +all: rtc.bin + +build: + cargo build + +rtc.bin: build + $(OBJCOPY) -O binary target/aarch64-unknown-none/debug/rtc $@ + +qemu: rtc.bin + qemu-system-aarch64 -machine virt,gic-version=3 -cpu max -serial mon:stdio -display none -kernel $< -s + +clean: + cargo clean + rm -f *.bin diff --git a/src/exercises/bare-metal/rtc/build.rs b/src/exercises/bare-metal/rtc/build.rs new file mode 100644 index 0000000..7a58b29 --- /dev/null +++ b/src/exercises/bare-metal/rtc/build.rs @@ -0,0 +1,29 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use cc::Build; +use std::env; + +fn main() { + #[cfg(target_os = "linux")] + env::set_var("CROSS_COMPILE", "aarch64-linux-gnu"); + #[cfg(not(target_os = "linux"))] + env::set_var("CROSS_COMPILE", "aarch64-none-elf"); + + Build::new() + .file("entry.S") + .file("exceptions.S") + .file("idmap.S") + .compile("empty") +} diff --git a/src/exercises/bare-metal/rtc/entry.S b/src/exercises/bare-metal/rtc/entry.S new file mode 100644 index 0000000..cd554f2 --- /dev/null +++ b/src/exercises/bare-metal/rtc/entry.S @@ -0,0 +1,142 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.macro adr_l, reg:req, sym:req + adrp \reg, \sym + add \reg, \reg, :lo12:\sym +.endm + +.macro mov_i, reg:req, imm:req + movz \reg, :abs_g3:\imm + movk \reg, :abs_g2_nc:\imm + movk \reg, :abs_g1_nc:\imm + movk \reg, :abs_g0_nc:\imm +.endm + +.set .L_MAIR_DEV_nGnRE, 0x04 +.set .L_MAIR_MEM_WBWA, 0xff +.set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8) + +/* 4 KiB granule size for TTBR0_EL1. */ +.set .L_TCR_TG0_4KB, 0x0 << 14 +/* 4 KiB granule size for TTBR1_EL1. */ +.set .L_TCR_TG1_4KB, 0x2 << 30 +/* Disable translation table walk for TTBR1_EL1, generating a translation fault instead. */ +.set .L_TCR_EPD1, 0x1 << 23 +/* Translation table walks for TTBR0_EL1 are inner sharable. */ +.set .L_TCR_SH_INNER, 0x3 << 12 +/* + * Translation table walks for TTBR0_EL1 are outer write-back read-allocate write-allocate + * cacheable. + */ +.set .L_TCR_RGN_OWB, 0x1 << 10 +/* + * Translation table walks for TTBR0_EL1 are inner write-back read-allocate write-allocate + * cacheable. + */ +.set .L_TCR_RGN_IWB, 0x1 << 8 +/* Size offset for TTBR0_EL1 is 2**39 bytes (512 GiB). */ +.set .L_TCR_T0SZ_512, 64 - 39 +.set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_TG1_4KB | .L_TCR_EPD1 | .L_TCR_RGN_OWB +.set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | .L_TCR_T0SZ_512 + +/* Stage 1 instruction access cacheability is unaffected. */ +.set .L_SCTLR_ELx_I, 0x1 << 12 +/* SP alignment fault if SP is not aligned to a 16 byte boundary. */ +.set .L_SCTLR_ELx_SA, 0x1 << 3 +/* Stage 1 data access cacheability is unaffected. */ +.set .L_SCTLR_ELx_C, 0x1 << 2 +/* EL0 and EL1 stage 1 MMU enabled. */ +.set .L_SCTLR_ELx_M, 0x1 << 0 +/* Privileged Access Never is unchanged on taking an exception to EL1. */ +.set .L_SCTLR_EL1_SPAN, 0x1 << 23 +/* SETEND instruction disabled at EL0 in aarch32 mode. */ +.set .L_SCTLR_EL1_SED, 0x1 << 8 +/* Various IT instructions are disabled at EL0 in aarch32 mode. */ +.set .L_SCTLR_EL1_ITD, 0x1 << 7 +.set .L_SCTLR_EL1_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29) +.set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | .L_SCTLR_EL1_ITD | .L_SCTLR_EL1_SED +.set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL1_SPAN | .L_SCTLR_EL1_RES1 + +/** + * This is a generic entry point for an image. It carries out the operations required to prepare the + * loaded image to be run. Specifically, it zeroes the bss section using registers x25 and above, + * prepares the stack, enables floating point, and sets up the exception vector. It preserves x0-x3 + * for the Rust entry point, as these may contain boot parameters. + */ +.section .init.entry, "ax" +.global entry +entry: + /* Load and apply the memory management configuration, ready to enable MMU and caches. */ + adrp x30, idmap + msr ttbr0_el1, x30 + + mov_i x30, .Lmairval + msr mair_el1, x30 + + mov_i x30, .Ltcrval + /* Copy the supported PA range into TCR_EL1.IPS. */ + mrs x29, id_aa64mmfr0_el1 + bfi x30, x29, #32, #4 + + msr tcr_el1, x30 + + mov_i x30, .Lsctlrval + + /* + * Ensure everything before this point has completed, then invalidate any potentially stale + * local TLB entries before they start being used. + */ + isb + tlbi vmalle1 + ic iallu + dsb nsh + isb + + /* + * Configure sctlr_el1 to enable MMU and cache and don't proceed until this has completed. + */ + msr sctlr_el1, x30 + isb + + /* Disable trapping floating point access in EL1. */ + mrs x30, cpacr_el1 + orr x30, x30, #(0x3 << 20) + msr cpacr_el1, x30 + isb + + /* Zero out the bss section. */ + adr_l x29, bss_begin + adr_l x30, bss_end +0: cmp x29, x30 + b.hs 1f + stp xzr, xzr, [x29], #16 + b 0b + +1: /* Prepare the stack. */ + adr_l x30, boot_stack_end + mov sp, x30 + + /* Set up exception vector. */ + adr x30, vector_table_el1 + msr vbar_el1, x30 + + /* Call into Rust code. */ + bl main + + /* Loop forever waiting for interrupts. */ +2: wfi + b 2b diff --git a/src/exercises/bare-metal/rtc/exceptions.S b/src/exercises/bare-metal/rtc/exceptions.S new file mode 100644 index 0000000..434b050 --- /dev/null +++ b/src/exercises/bare-metal/rtc/exceptions.S @@ -0,0 +1,178 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Saves the volatile registers onto the stack. This currently takes 14 + * instructions, so it can be used in exception handlers with 18 instructions + * left. + * + * On return, x0 and x1 are initialised to elr_el2 and spsr_el2 respectively, + * which can be used as the first and second arguments of a subsequent call. + */ +.macro save_volatile_to_stack + /* Reserve stack space and save registers x0-x18, x29 & x30. */ + stp x0, x1, [sp, #-(8 * 24)]! + stp x2, x3, [sp, #8 * 2] + stp x4, x5, [sp, #8 * 4] + stp x6, x7, [sp, #8 * 6] + stp x8, x9, [sp, #8 * 8] + stp x10, x11, [sp, #8 * 10] + stp x12, x13, [sp, #8 * 12] + stp x14, x15, [sp, #8 * 14] + stp x16, x17, [sp, #8 * 16] + str x18, [sp, #8 * 18] + stp x29, x30, [sp, #8 * 20] + + /* + * Save elr_el1 & spsr_el1. This such that we can take nested exception + * and still be able to unwind. + */ + mrs x0, elr_el1 + mrs x1, spsr_el1 + stp x0, x1, [sp, #8 * 22] +.endm + +/** + * Restores the volatile registers from the stack. This currently takes 14 + * instructions, so it can be used in exception handlers while still leaving 18 + * instructions left; if paired with save_volatile_to_stack, there are 4 + * instructions to spare. + */ +.macro restore_volatile_from_stack + /* Restore registers x2-x18, x29 & x30. */ + ldp x2, x3, [sp, #8 * 2] + ldp x4, x5, [sp, #8 * 4] + ldp x6, x7, [sp, #8 * 6] + ldp x8, x9, [sp, #8 * 8] + ldp x10, x11, [sp, #8 * 10] + ldp x12, x13, [sp, #8 * 12] + ldp x14, x15, [sp, #8 * 14] + ldp x16, x17, [sp, #8 * 16] + ldr x18, [sp, #8 * 18] + ldp x29, x30, [sp, #8 * 20] + + /* Restore registers elr_el1 & spsr_el1, using x0 & x1 as scratch. */ + ldp x0, x1, [sp, #8 * 22] + msr elr_el1, x0 + msr spsr_el1, x1 + + /* Restore x0 & x1, and release stack space. */ + ldp x0, x1, [sp], #8 * 24 +.endm + +/** + * This is a generic handler for exceptions taken at the current EL while using + * SP0. It behaves similarly to the SPx case by first switching to SPx, doing + * the work, then switching back to SP0 before returning. + * + * Switching to SPx and calling the Rust handler takes 16 instructions. To + * restore and return we need an additional 16 instructions, so we can implement + * the whole handler within the allotted 32 instructions. + */ +.macro current_exception_sp0 handler:req + msr spsel, #1 + save_volatile_to_stack + bl \handler + restore_volatile_from_stack + msr spsel, #0 + eret +.endm + +/** + * This is a generic handler for exceptions taken at the current EL while using + * SPx. It saves volatile registers, calls the Rust handler, restores volatile + * registers, then returns. + * + * This also works for exceptions taken from EL0, if we don't care about + * non-volatile registers. + * + * Saving state and jumping to the Rust handler takes 15 instructions, and + * restoring and returning also takes 15 instructions, so we can fit the whole + * handler in 30 instructions, under the limit of 32. + */ +.macro current_exception_spx handler:req + save_volatile_to_stack + bl \handler + restore_volatile_from_stack + eret +.endm + +.section .text.vector_table_el1, "ax" +.global vector_table_el1 +.balign 0x800 +vector_table_el1: +sync_cur_sp0: + current_exception_sp0 sync_exception_current + +.balign 0x80 +irq_cur_sp0: + current_exception_sp0 irq_current + +.balign 0x80 +fiq_cur_sp0: + current_exception_sp0 fiq_current + +.balign 0x80 +serr_cur_sp0: + current_exception_sp0 serr_current + +.balign 0x80 +sync_cur_spx: + current_exception_spx sync_exception_current + +.balign 0x80 +irq_cur_spx: + current_exception_spx irq_current + +.balign 0x80 +fiq_cur_spx: + current_exception_spx fiq_current + +.balign 0x80 +serr_cur_spx: + current_exception_spx serr_current + +.balign 0x80 +sync_lower_64: + current_exception_spx sync_lower + +.balign 0x80 +irq_lower_64: + current_exception_spx irq_lower + +.balign 0x80 +fiq_lower_64: + current_exception_spx fiq_lower + +.balign 0x80 +serr_lower_64: + current_exception_spx serr_lower + +.balign 0x80 +sync_lower_32: + current_exception_spx sync_lower + +.balign 0x80 +irq_lower_32: + current_exception_spx irq_lower + +.balign 0x80 +fiq_lower_32: + current_exception_spx fiq_lower + +.balign 0x80 +serr_lower_32: + current_exception_spx serr_lower diff --git a/src/exercises/bare-metal/rtc/idmap.S b/src/exercises/bare-metal/rtc/idmap.S new file mode 100644 index 0000000..a79f3af --- /dev/null +++ b/src/exercises/bare-metal/rtc/idmap.S @@ -0,0 +1,42 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.set .L_TT_TYPE_BLOCK, 0x1 +.set .L_TT_TYPE_PAGE, 0x3 +.set .L_TT_TYPE_TABLE, 0x3 + +/* Access flag. */ +.set .L_TT_AF, 0x1 << 10 +/* Not global. */ +.set .L_TT_NG, 0x1 << 11 +.set .L_TT_XN, 0x3 << 53 + +.set .L_TT_MT_DEV, 0x0 << 2 // MAIR #0 (DEV_nGnRE) +.set .L_TT_MT_MEM, (0x1 << 2) | (0x3 << 8) // MAIR #1 (MEM_WBWA), inner shareable + +.set .L_BLOCK_DEV, .L_TT_TYPE_BLOCK | .L_TT_MT_DEV | .L_TT_AF | .L_TT_XN +.set .L_BLOCK_MEM, .L_TT_TYPE_BLOCK | .L_TT_MT_MEM | .L_TT_AF | .L_TT_NG + +.section ".rodata.idmap", "a", %progbits +.global idmap +.align 12 +idmap: + /* level 1 */ + .quad .L_BLOCK_DEV | 0x0 // 1 GiB of device mappings + .quad .L_BLOCK_MEM | 0x40000000 // 1 GiB of DRAM + .fill 254, 8, 0x0 // 254 GiB of unmapped VA space + .quad .L_BLOCK_DEV | 0x4000000000 // 1 GiB of device mappings + .fill 255, 8, 0x0 // 255 GiB of remaining VA space diff --git a/src/exercises/bare-metal/rtc/image.ld b/src/exercises/bare-metal/rtc/image.ld new file mode 100644 index 0000000..59c7752 --- /dev/null +++ b/src/exercises/bare-metal/rtc/image.ld @@ -0,0 +1,104 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Code will start running at this symbol which is placed at the start of the + * image. + */ +ENTRY(entry) + +MEMORY +{ + image : ORIGIN = 0x40080000, LENGTH = 2M +} + +SECTIONS +{ + /* + * Collect together the code. + */ + .init : ALIGN(4096) { + text_begin = .; + *(.init.entry) + *(.init.*) + } >image + .text : { + *(.text.*) + } >image + text_end = .; + + /* + * Collect together read-only data. + */ + .rodata : ALIGN(4096) { + rodata_begin = .; + *(.rodata.*) + } >image + .got : { + *(.got) + } >image + rodata_end = .; + + /* + * Collect together the read-write data including .bss at the end which + * will be zero'd by the entry code. + */ + .data : ALIGN(4096) { + data_begin = .; + *(.data.*) + /* + * The entry point code assumes that .data is a multiple of 32 + * bytes long. + */ + . = ALIGN(32); + data_end = .; + } >image + + /* Everything beyond this point will not be included in the binary. */ + bin_end = .; + + /* The entry point code assumes that .bss is 16-byte aligned. */ + .bss : ALIGN(16) { + bss_begin = .; + *(.bss.*) + *(COMMON) + . = ALIGN(16); + bss_end = .; + } >image + + .stack (NOLOAD) : ALIGN(4096) { + boot_stack_begin = .; + . += 40 * 4096; + . = ALIGN(4096); + boot_stack_end = .; + } >image + + . = ALIGN(4K); + PROVIDE(dma_region = .); + + /* + * Remove unused sections from the image. + */ + /DISCARD/ : { + /* The image loads itself so doesn't need these sections. */ + *(.gnu.hash) + *(.hash) + *(.interp) + *(.eh_frame_hdr) + *(.eh_frame) + *(.note.gnu.build-id) + } +} diff --git a/src/exercises/bare-metal/rtc/src/exceptions.rs b/src/exercises/bare-metal/rtc/src/exceptions.rs new file mode 100644 index 0000000..9dd3c7e --- /dev/null +++ b/src/exercises/bare-metal/rtc/src/exceptions.rs @@ -0,0 +1,67 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use arm_gic::gicv3::GicV3; +use log::{error, info, trace}; +use smccc::psci::system_off; +use smccc::Hvc; + +#[no_mangle] +extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) { + error!("sync_exception_current"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn irq_current(_elr: u64, _spsr: u64) { + trace!("irq_current"); + let intid = GicV3::get_and_acknowledge_interrupt().expect("No pending interrupt"); + info!("IRQ {intid:?}"); +} + +#[no_mangle] +extern "C" fn fiq_current(_elr: u64, _spsr: u64) { + error!("fiq_current"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn serr_current(_elr: u64, _spsr: u64) { + error!("serr_current"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn sync_lower(_elr: u64, _spsr: u64) { + error!("sync_lower"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn irq_lower(_elr: u64, _spsr: u64) { + error!("irq_lower"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn fiq_lower(_elr: u64, _spsr: u64) { + error!("fiq_lower"); + system_off::().unwrap(); +} + +#[no_mangle] +extern "C" fn serr_lower(_elr: u64, _spsr: u64) { + error!("serr_lower"); + system_off::().unwrap(); +} diff --git a/src/exercises/bare-metal/rtc/src/logger.rs b/src/exercises/bare-metal/rtc/src/logger.rs new file mode 100644 index 0000000..8151949 --- /dev/null +++ b/src/exercises/bare-metal/rtc/src/logger.rs @@ -0,0 +1,54 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: main +use crate::pl011::Uart; +use core::fmt::Write; +use log::{LevelFilter, Log, Metadata, Record, SetLoggerError}; +use spin::mutex::SpinMutex; + +static LOGGER: Logger = Logger { + uart: SpinMutex::new(None), +}; + +struct Logger { + uart: SpinMutex>, +} + +impl Log for Logger { + fn enabled(&self, _metadata: &Metadata) -> bool { + true + } + + fn log(&self, record: &Record) { + writeln!( + self.uart.lock().as_mut().unwrap(), + "[{}] {}", + record.level(), + record.args() + ) + .unwrap(); + } + + fn flush(&self) {} +} + +/// Initialises UART logger. +pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), SetLoggerError> { + LOGGER.uart.lock().replace(uart); + + log::set_logger(&LOGGER)?; + log::set_max_level(max_level); + Ok(()) +} diff --git a/src/exercises/bare-metal/rtc/src/main.rs b/src/exercises/bare-metal/rtc/src/main.rs new file mode 100644 index 0000000..d3ace2b --- /dev/null +++ b/src/exercises/bare-metal/rtc/src/main.rs @@ -0,0 +1,137 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: top +#![no_main] +#![no_std] + +mod exceptions; +mod logger; +mod pl011; +// ANCHOR_END: top +mod pl031; + +use crate::pl031::Rtc; +use arm_gic::gicv3::{IntId, Trigger}; +use arm_gic::{irq_enable, wfi}; +use chrono::{TimeZone, Utc}; +use core::hint::spin_loop; +// ANCHOR: imports +use crate::pl011::Uart; +use arm_gic::gicv3::GicV3; +use core::panic::PanicInfo; +use log::{error, info, trace, LevelFilter}; +use smccc::psci::system_off; +use smccc::Hvc; + +/// Base addresses of the GICv3. +const GICD_BASE_ADDRESS: *mut u64 = 0x800_0000 as _; +const GICR_BASE_ADDRESS: *mut u64 = 0x80A_0000 as _; + +/// Base address of the primary PL011 UART. +const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _; +// ANCHOR_END: imports + +/// Base address of the PL031 RTC. +const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _; +/// The IRQ used by the PL031 RTC. +const PL031_IRQ: IntId = IntId::spi(2); + +// ANCHOR: main +#[no_mangle] +extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { + // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device, + // and nothing else accesses that address range. + let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) }; + logger::init(uart, LevelFilter::Trace).unwrap(); + + info!("main({:#x}, {:#x}, {:#x}, {:#x})", x0, x1, x2, x3); + + // Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base + // addresses of a GICv3 distributor and redistributor respectively, and + // nothing else accesses those address ranges. + let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, GICR_BASE_ADDRESS) }; + gic.setup(); + // ANCHOR_END: main + + // Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 device, + // and nothing else accesses that address range. + let mut rtc = unsafe { Rtc::new(PL031_BASE_ADDRESS) }; + let timestamp = rtc.read(); + let time = Utc.timestamp_opt(timestamp.into(), 0).unwrap(); + info!("RTC: {time}"); + + GicV3::set_priority_mask(0xff); + gic.set_interrupt_priority(PL031_IRQ, 0x80); + gic.set_trigger(PL031_IRQ, Trigger::Level); + irq_enable(); + gic.enable_interrupt(PL031_IRQ, true); + + // Wait for 3 seconds, without interrupts. + let target = timestamp + 3; + rtc.set_match(target); + info!( + "Waiting for {}", + Utc.timestamp_opt(target.into(), 0).unwrap() + ); + trace!( + "matched={}, interrupt_pending={}", + rtc.matched(), + rtc.interrupt_pending() + ); + while !rtc.matched() { + spin_loop(); + } + trace!( + "matched={}, interrupt_pending={}", + rtc.matched(), + rtc.interrupt_pending() + ); + info!("Finished waiting"); + + // Wait another 3 seconds for an interrupt. + let target = timestamp + 6; + info!( + "Waiting for {}", + Utc.timestamp_opt(target.into(), 0).unwrap() + ); + rtc.set_match(target); + rtc.clear_interrupt(); + rtc.enable_interrupt(true); + trace!( + "matched={}, interrupt_pending={}", + rtc.matched(), + rtc.interrupt_pending() + ); + while !rtc.interrupt_pending() { + wfi(); + } + trace!( + "matched={}, interrupt_pending={}", + rtc.matched(), + rtc.interrupt_pending() + ); + info!("Finished waiting"); + + // ANCHOR: main_end + system_off::().unwrap(); +} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + error!("{info}"); + system_off::().unwrap(); + loop {} +} +// ANCHOR_END: main_end diff --git a/src/exercises/bare-metal/rtc/src/pl011.rs b/src/exercises/bare-metal/rtc/src/pl011.rs new file mode 100644 index 0000000..6c8467f --- /dev/null +++ b/src/exercises/bare-metal/rtc/src/pl011.rs @@ -0,0 +1,168 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![allow(unused)] + +use core::fmt::{self, Write}; +use core::ptr::{addr_of, addr_of_mut}; + +// ANCHOR: Flags +use bitflags::bitflags; + +bitflags! { + /// Flags from the UART flag register. + #[repr(transparent)] + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + struct Flags: u16 { + /// Clear to send. + const CTS = 1 << 0; + /// Data set ready. + const DSR = 1 << 1; + /// Data carrier detect. + const DCD = 1 << 2; + /// UART busy transmitting data. + const BUSY = 1 << 3; + /// Receive FIFO is empty. + const RXFE = 1 << 4; + /// Transmit FIFO is full. + const TXFF = 1 << 5; + /// Receive FIFO is full. + const RXFF = 1 << 6; + /// Transmit FIFO is empty. + const TXFE = 1 << 7; + /// Ring indicator. + const RI = 1 << 8; + } +} +// ANCHOR_END: Flags + +bitflags! { + /// Flags from the UART Receive Status Register / Error Clear Register. + #[repr(transparent)] + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + struct ReceiveStatus: u16 { + /// Framing error. + const FE = 1 << 0; + /// Parity error. + const PE = 1 << 1; + /// Break error. + const BE = 1 << 2; + /// Overrun error. + const OE = 1 << 3; + } +} + +// ANCHOR: Registers +#[repr(C, align(4))] +struct Registers { + dr: u16, + _reserved0: [u8; 2], + rsr: ReceiveStatus, + _reserved1: [u8; 19], + fr: Flags, + _reserved2: [u8; 6], + ilpr: u8, + _reserved3: [u8; 3], + ibrd: u16, + _reserved4: [u8; 2], + fbrd: u8, + _reserved5: [u8; 3], + lcr_h: u8, + _reserved6: [u8; 3], + cr: u16, + _reserved7: [u8; 3], + ifls: u8, + _reserved8: [u8; 3], + imsc: u16, + _reserved9: [u8; 2], + ris: u16, + _reserved10: [u8; 2], + mis: u16, + _reserved11: [u8; 2], + icr: u16, + _reserved12: [u8; 2], + dmacr: u8, + _reserved13: [u8; 3], +} +// ANCHOR_END: Registers + +// ANCHOR: Uart +/// Driver for a PL011 UART. +#[derive(Debug)] +pub struct Uart { + registers: *mut Registers, +} + +impl Uart { + /// Constructs a new instance of the UART driver for a PL011 device at the + /// given base address. + /// + /// # Safety + /// + /// The given base address must point to the MMIO control registers of a + /// PL011 device, which must be mapped into the address space of the process + /// as device memory and not have any other aliases. + pub unsafe fn new(base_address: *mut u32) -> Self { + Self { + registers: base_address as *mut Registers, + } + } + + /// Writes a single byte to the UART. + pub fn write_byte(&self, byte: u8) { + // Wait until there is room in the TX buffer. + while self.read_flag_register().contains(Flags::TXFF) {} + + // Safe because we know that self.registers points to the control + // registers of a PL011 device which is appropriately mapped. + unsafe { + // Write to the TX buffer. + addr_of_mut!((*self.registers).dr).write_volatile(byte.into()); + } + + // Wait until the UART is no longer busy. + while self.read_flag_register().contains(Flags::BUSY) {} + } + + /// Reads and returns a pending byte, or `None` if nothing has been received. + pub fn read_byte(&self) -> Option { + if self.read_flag_register().contains(Flags::RXFE) { + None + } else { + let data = unsafe { addr_of!((*self.registers).dr).read_volatile() }; + // TODO: Check for error conditions in bits 8-11. + Some(data as u8) + } + } + + fn read_flag_register(&self) -> Flags { + // Safe because we know that self.registers points to the control + // registers of a PL011 device which is appropriately mapped. + unsafe { addr_of!((*self.registers).fr).read_volatile() } + } +} +// ANCHOR_END: Uart + +impl Write for Uart { + fn write_str(&mut self, s: &str) -> fmt::Result { + for c in s.as_bytes() { + self.write_byte(*c); + } + Ok(()) + } +} + +// Safe because it just contains a pointer to device memory, which can be +// accessed from any context. +unsafe impl Send for Uart {} diff --git a/src/exercises/bare-metal/rtc/src/pl031.rs b/src/exercises/bare-metal/rtc/src/pl031.rs new file mode 100644 index 0000000..4654511 --- /dev/null +++ b/src/exercises/bare-metal/rtc/src/pl031.rs @@ -0,0 +1,119 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::ptr::{addr_of, addr_of_mut}; + +#[repr(C, align(4))] +struct Registers { + /// Data register + dr: u32, + /// Match register + mr: u32, + /// Load register + lr: u32, + /// Control register + cr: u8, + _reserved0: [u8; 3], + /// Interrupt Mask Set or Clear register + imsc: u8, + _reserved1: [u8; 3], + /// Raw Interrupt Status + ris: u8, + _reserved2: [u8; 3], + /// Masked Interrupt Status + mis: u8, + _reserved3: [u8; 3], + /// Interrupt Clear Register + icr: u8, + _reserved4: [u8; 3], +} + +/// Driver for a PL031 real-time clock. +#[derive(Debug)] +pub struct Rtc { + registers: *mut Registers, +} + +impl Rtc { + /// Constructs a new instance of the RTC driver for a PL031 device at the + /// given base address. + /// + /// # Safety + /// + /// The given base address must point to the MMIO control registers of a + /// PL031 device, which must be mapped into the address space of the process + /// as device memory and not have any other aliases. + pub unsafe fn new(base_address: *mut u32) -> Self { + Self { + registers: base_address as *mut Registers, + } + } + + /// Reads the current RTC value. + pub fn read(&self) -> u32 { + // Safe because we know that self.registers points to the control + // registers of a PL031 device which is appropriately mapped. + unsafe { addr_of!((*self.registers).dr).read_volatile() } + } + + /// Writes a match value. When the RTC value matches this then an interrupt + /// will be generated (if it is enabled). + pub fn set_match(&mut self, value: u32) { + // Safe because we know that self.registers points to the control + // registers of a PL031 device which is appropriately mapped. + unsafe { addr_of_mut!((*self.registers).mr).write_volatile(value) } + } + + /// Returns whether the match register matches the RTC value, whether or not + /// the interrupt is enabled. + pub fn matched(&self) -> bool { + // Safe because we know that self.registers points to the control + // registers of a PL031 device which is appropriately mapped. + let ris = unsafe { addr_of!((*self.registers).ris).read_volatile() }; + (ris & 0x01) != 0 + } + + /// Returns whether there is currently an interrupt pending. + /// + /// This should be true iff `matched` returns true and the interrupt is + /// masked. + pub fn interrupt_pending(&self) -> bool { + // Safe because we know that self.registers points to the control + // registers of a PL031 device which is appropriately mapped. + let ris = unsafe { addr_of!((*self.registers).mis).read_volatile() }; + (ris & 0x01) != 0 + } + + /// Sets or clears the interrupt mask. + /// + /// When the mask is true the interrupt is enabled; when it is false the + /// interrupt is disabled. + pub fn enable_interrupt(&mut self, mask: bool) { + let imsc = if mask { 0x01 } else { 0x00 }; + // Safe because we know that self.registers points to the control + // registers of a PL031 device which is appropriately mapped. + unsafe { addr_of_mut!((*self.registers).imsc).write_volatile(imsc) } + } + + /// Clears a pending interrupt, if any. + pub fn clear_interrupt(&mut self) { + // Safe because we know that self.registers points to the control + // registers of a PL031 device which is appropriately mapped. + unsafe { addr_of_mut!((*self.registers).icr).write_volatile(0x01) } + } +} + +// Safe because it just contains a pointer to device memory, which can be +// accessed from any context. +unsafe impl Send for Rtc {} diff --git a/src/exercises/bare-metal/solutions-afternoon.md b/src/exercises/bare-metal/solutions-afternoon.md new file mode 100644 index 0000000..cc403ea --- /dev/null +++ b/src/exercises/bare-metal/solutions-afternoon.md @@ -0,0 +1,17 @@ +# Bare Metal Rust Afternoon + +## RTC driver + +([back to exercise](rtc.md)) + +`main.rs`: + +```rust,compile_fail +{{#include rtc/src/main.rs}} +``` + +`pl031.rs`: + +```rust +{{#include rtc/src/pl031.rs}} +``` diff --git a/src/exercises/bare-metal/solutions-morning.md b/src/exercises/bare-metal/solutions-morning.md new file mode 100644 index 0000000..f11e830 --- /dev/null +++ b/src/exercises/bare-metal/solutions-morning.md @@ -0,0 +1,9 @@ +# Bare Metal Rust Morning Exercise + +## Compass + +([back to exercise](compass.md)) + +```rust,compile_fail +{{#include compass/src/main.rs}} +``` diff --git a/src/exercises/concurrency/afternoon.md b/src/exercises/concurrency/afternoon.md new file mode 100644 index 0000000..281c61e --- /dev/null +++ b/src/exercises/concurrency/afternoon.md @@ -0,0 +1,17 @@ +# Exercises + +To practice your Async Rust skills, we have again two exercises for you: + +* Dining philosophers: we already saw this problem in the morning. This time + you are going to implement it with Async Rust. + +* A Broadcast Chat Application: this is a larger project that allows you + experiment with more advanced Async Rust features. + +
+ +After looking at the exercises, you can look at the [solutions] provided. + +[solutions]: solutions-afternoon.md + +
diff --git a/src/exercises/concurrency/chat-app.md b/src/exercises/concurrency/chat-app.md new file mode 100644 index 0000000..e630754 --- /dev/null +++ b/src/exercises/concurrency/chat-app.md @@ -0,0 +1,109 @@ +# Broadcast Chat Application + +In this exercise, we want to use our new knowledge to implement a broadcast +chat application. We have a chat server that the clients connect to and publish +their messages. The client reads user messages from the standard input, and +sends them to the server. The chat server broadcasts each message that it +receives to all the clients. + +For this, we use [a broadcast channel][1] on the server, and +[`tokio_websockets`][2] for the communication between the client and the +server. + +Create a new Cargo project and add the following dependencies: + +`Cargo.toml`: + + + +```toml +{{#include chat-async/Cargo.toml}} +``` + +## The required APIs +You are going to need the following functions from `tokio` and +[`tokio_websockets`][2]. Spend a few minutes to familiarize yourself with the +API. + +- [WebsocketStream::next()][3]: for asynchronously reading messages from a + Websocket Stream. +- [SinkExt::send()][4] implemented by `WebsocketStream`: for asynchronously + sending messages on a Websocket Stream. +- [BufReader::read_line()][5]: for asynchronously reading user messages + from the standard input. +- [Sender::subscribe()][6]: for subscribing to a broadcast channel. + + +## Two binaries + +Normally in a Cargo project, you can have only one binary, and one +`src/main.rs` file. In this project, we need two binaries. One for the client, +and one for the server. You could potentially make them two separate Cargo +projects, but we are going to put them in a single Cargo project with two +binaries. For this to work, the client and the server code should go under +`src/bin` (see the [documentation][7]). + +Copy the following server and client code into `src/bin/server.rs` and +`src/bin/client.rs`, respectively. Your task is to complete these files as +described below. + +`src/bin/server.rs`: + + + +```rust,compile_fail +{{#include chat-async/src/bin/server.rs:setup}} + +{{#include chat-async/src/bin/server.rs:handle_connection}} + + // TODO: For a hint, see the description of the task below. + +{{#include chat-async/src/bin/server.rs:main}} +``` + +`src/bin/client.rs`: + + + +```rust,compile_fail +{{#include chat-async/src/bin/client.rs:setup}} + + // TODO: For a hint, see the description of the task below. + +} +``` + +## Running the binaries +Run the server with: + +```shell +$ cargo run --bin server +``` + +and the client with: + +```shell +$ cargo run --bin client +``` + +## Tasks + +* Implement the `handle_connection` function in `src/bin/server.rs`. + * Hint: Use `tokio::select!` for concurrently performing two tasks in a + continuous loop. One task receives messages from the client and broadcasts + them. The other sends messages received by the server to the client. +* Complete the main function in `src/bin/client.rs`. + * Hint: As before, use `tokio::select!` in a continuous loop for concurrently + performing two tasks: (1) reading user messages from standard input and + sending them to the server, and (2) receiving messages from the server, and + displaying them for the user. +* Optional: Once you are done, change the code to broadcast messages to all + clients, but the sender of the message. + +[1]: https://docs.rs/tokio/latest/tokio/sync/broadcast/fn.channel.html +[2]: https://docs.rs/tokio-websockets/0.3.2/tokio_websockets/ +[3]: https://docs.rs/tokio-websockets/0.3.2/tokio_websockets/proto/struct.WebsocketStream.html#method.next +[4]: https://docs.rs/futures-util/0.3.28/futures_util/sink/trait.SinkExt.html#method.send +[5]: https://docs.rs/tokio/latest/tokio/io/trait.AsyncBufReadExt.html#method.read_line +[6]: https://docs.rs/tokio/latest/tokio/sync/broadcast/struct.Sender.html#method.subscribe +[7]: https://doc.rust-lang.org/cargo/reference/cargo-targets.html#binaries diff --git a/src/exercises/concurrency/chat-async/Cargo.toml b/src/exercises/concurrency/chat-async/Cargo.toml new file mode 100644 index 0000000..fd3ada9 --- /dev/null +++ b/src/exercises/concurrency/chat-async/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "chat-async" +version = "0.1.0" +edition = "2021" + +[dependencies] +futures-util = "0.3.28" +http = "0.2.9" +tokio = { version = "1.28.1", features = ["full"] } +tokio-websockets = "0.3.2" diff --git a/src/exercises/concurrency/chat-async/src/bin/client.rs b/src/exercises/concurrency/chat-async/src/bin/client.rs new file mode 100644 index 0000000..51aaf9f --- /dev/null +++ b/src/exercises/concurrency/chat-async/src/bin/client.rs @@ -0,0 +1,52 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: setup +use futures_util::SinkExt; +use http::Uri; +use tokio::io::{AsyncBufReadExt, BufReader}; +use tokio_websockets::{ClientBuilder, Message}; + +#[tokio::main] +async fn main() -> Result<(), tokio_websockets::Error> { + let mut ws_stream = ClientBuilder::from_uri(Uri::from_static("ws://127.0.0.1:2000")) + .connect() + .await?; + + let stdin = tokio::io::stdin(); + let mut stdin = BufReader::new(stdin); + + // ANCHOR_END: setup + // Continuous loop for concurrently sending and receiving messages. + loop { + let mut line = String::new(); + tokio::select! { + incoming = ws_stream.next() => { + match incoming { + Some(Ok(msg)) => println!("From server: {}", msg.as_text()?), + Some(Err(err)) => return Err(err.into()), + None => return Ok(()), + } + } + res = stdin.read_line(&mut line) => { + match res { + Ok(0) => return Ok(()), + Ok(_) => ws_stream.send(Message::text(line.trim_end().to_string())).await?, + Err(err) => return Err(err.into()), + } + } + + } + } +} diff --git a/src/exercises/concurrency/chat-async/src/bin/server.rs b/src/exercises/concurrency/chat-async/src/bin/server.rs new file mode 100644 index 0000000..9899b4b --- /dev/null +++ b/src/exercises/concurrency/chat-async/src/bin/server.rs @@ -0,0 +1,80 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: setup +use futures_util::sink::SinkExt; +use std::error::Error; +use std::net::SocketAddr; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::broadcast::{channel, Sender}; +use tokio_websockets::{Message, ServerBuilder, WebsocketStream}; +// ANCHOR_END: setup + +// ANCHOR: handle_connection +async fn handle_connection( + addr: SocketAddr, + mut ws_stream: WebsocketStream, + bcast_tx: Sender, +) -> Result<(), Box> { + // ANCHOR_END: handle_connection + + ws_stream + .send(Message::text("Welcome to chat! Type a message".into())) + .await?; + let mut bcast_rx = bcast_tx.subscribe(); + + // A continuous loop for concurrently performing two tasks: (1) receiving + // messages from `ws_stream` and broadcasting them, and (2) receiving + // messages on `bcast_rx` and sending them to the client. + loop { + tokio::select! { + incoming = ws_stream.next() => { + match incoming { + Some(Ok(msg)) => { + let msg = msg.as_text()?; + println!("From client {addr:?} {msg:?}"); + bcast_tx.send(msg.into())?; + } + Some(Err(err)) => return Err(err.into()), + None => return Ok(()), + } + } + msg = bcast_rx.recv() => { + ws_stream.send(Message::text(msg?)).await?; + } + } + } + // ANCHOR: main +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let (bcast_tx, _) = channel(16); + + let listener = TcpListener::bind("127.0.0.1:2000").await?; + println!("listening on port 2000"); + + loop { + let (socket, addr) = listener.accept().await?; + println!("New connection from {addr:?}"); + let bcast_tx = bcast_tx.clone(); + tokio::spawn(async move { + // Wrap the raw TCP stream into a websocket. + let ws_stream = ServerBuilder::new().accept(socket).await?; + + handle_connection(addr, ws_stream, bcast_tx).await + }); + } +} +// ANCHOR_END: main diff --git a/src/exercises/concurrency/dining-philosophers-async.md b/src/exercises/concurrency/dining-philosophers-async.md new file mode 100644 index 0000000..611c1c9 --- /dev/null +++ b/src/exercises/concurrency/dining-philosophers-async.md @@ -0,0 +1,57 @@ +# Dining Philosophers - Async + +See [dining philosophers](dining-philosophers.md) for a description of the +problem. + +As before, you will need a local +[Cargo installation](../../cargo/running-locally.md) for this exercise. Copy +the code below to a file called `src/main.rs`, fill out the blanks, and test +that `cargo run` does not deadlock: + + + +```rust,compile_fail +{{#include dining-philosophers-async.rs:Philosopher}} + // left_fork: ... + // right_fork: ... + // thoughts: ... +} + +{{#include dining-philosophers-async.rs:Philosopher-think}} + +{{#include dining-philosophers-async.rs:Philosopher-eat}} +{{#include dining-philosophers-async.rs:Philosopher-eat-body}} +{{#include dining-philosophers-async.rs:Philosopher-eat-end}} + // Create forks + + // Create philosophers + + // Make them think and eat + + // Output their thoughts +} +``` + +Since this time you are using Async Rust, you'll need a `tokio` dependency. +You can use the following `Cargo.toml`: + + + +```toml +[package] +name = "dining-philosophers-async-dine" +version = "0.1.0" +edition = "2021" + +[dependencies] +tokio = {version = "1.26.0", features = ["sync", "time", "macros", "rt-multi-thread"]} +``` + +Also note that this time you have to use the `Mutex` and the `mpsc` module +from the `tokio` crate. + +
+ +* Can you make your implementation single-threaded? + +
diff --git a/src/exercises/concurrency/dining-philosophers-async.rs b/src/exercises/concurrency/dining-philosophers-async.rs new file mode 100644 index 0000000..f5a3176 --- /dev/null +++ b/src/exercises/concurrency/dining-philosophers-async.rs @@ -0,0 +1,103 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: Philosopher +use std::sync::Arc; +use tokio::time; +use tokio::sync::mpsc::{self, Sender}; +use tokio::sync::Mutex; + +struct Fork; + +struct Philosopher { + name: String, + // ANCHOR_END: Philosopher + left_fork: Arc>, + right_fork: Arc>, + thoughts: Sender, +} + +// ANCHOR: Philosopher-think +impl Philosopher { + async fn think(&self) { + self.thoughts + .send(format!("Eureka! {} has a new idea!", &self.name)).await + .unwrap(); + } + // ANCHOR_END: Philosopher-think + + // ANCHOR: Philosopher-eat + async fn eat(&self) { + // Pick up forks... + // ANCHOR_END: Philosopher-eat + let _first_lock = self.left_fork.lock().await; + // Add a delay before picking the second fork to allow the execution + // to transfer to another task + time::sleep(time::Duration::from_millis(1)).await; + let _second_lock = self.right_fork.lock().await; + + // ANCHOR: Philosopher-eat-body + println!("{} is eating...", &self.name); + time::sleep(time::Duration::from_millis(5)).await; + // ANCHOR_END: Philosopher-eat-body + + // The locks are dropped here + // ANCHOR: Philosopher-eat-end + } +} + +static PHILOSOPHERS: &[&str] = + &["Socrates", "Plato", "Aristotle", "Thales", "Pythagoras"]; + +#[tokio::main] +async fn main() { + // ANCHOR_END: Philosopher-eat-end + // Create forks + let mut forks = vec![]; + (0..PHILOSOPHERS.len()).for_each(|_| forks.push(Arc::new(Mutex::new(Fork)))); + + // Create philosophers + let (philosophers, mut rx) = { + let mut philosophers = vec![]; + let (tx, rx) = mpsc::channel(10); + for (i, name) in PHILOSOPHERS.iter().enumerate() { + let left_fork = forks[i].clone(); + let right_fork = forks[(i + 1) % PHILOSOPHERS.len()].clone(); + philosophers.push(Philosopher { + name: name.to_string(), + left_fork: if i % 2 == 0 { left_fork.clone() } else { right_fork.clone() }, + right_fork: if i % 2 == 0 { right_fork } else { left_fork }, + thoughts: tx.clone(), + }); + } + (philosophers, rx) + // tx is dropped here, so we don't need to explicitly drop it later + }; + + // Make them think and eat + for phil in philosophers { + tokio::spawn(async move { + for _ in 0..100 { + phil.think().await; + phil.eat().await; + } + }); + + } + + // Output their thoughts + while let Some(thought) = rx.recv().await { + println!("Here is a thought: {thought}"); + } +} diff --git a/src/exercises/day-4/dining-philosophers.md b/src/exercises/concurrency/dining-philosophers.md similarity index 78% rename from src/exercises/day-4/dining-philosophers.md rename to src/exercises/concurrency/dining-philosophers.md index 04387b3..9b864b5 100644 --- a/src/exercises/day-4/dining-philosophers.md +++ b/src/exercises/concurrency/dining-philosophers.md @@ -11,8 +11,10 @@ The dining philosophers problem is a classic problem in concurrency: > an individual philosopher finishes eating, they will put down both forks. You will need a local [Cargo installation](../../cargo/running-locally.md) for -this exercise. Copy the code below to `src/main.rs` file, fill out the blanks, -and test that `cargo run` does not deadlock: +this exercise. Copy the code below to a file called `src/main.rs`, fill out the +blanks, and test that `cargo run` does not deadlock: + + ```rust,compile_fail {{#include dining-philosophers.rs:Philosopher}} @@ -35,3 +37,14 @@ and test that `cargo run` does not deadlock: // Output their thoughts } ``` + +You can use the following `Cargo.toml`: + + + +```toml +[package] +name = "dining-philosophers" +version = "0.1.0" +edition = "2021" +``` diff --git a/src/exercises/day-4/dining-philosophers.rs b/src/exercises/concurrency/dining-philosophers.rs similarity index 98% rename from src/exercises/day-4/dining-philosophers.rs rename to src/exercises/concurrency/dining-philosophers.rs index 28807b6..2322a80 100644 --- a/src/exercises/day-4/dining-philosophers.rs +++ b/src/exercises/concurrency/dining-philosophers.rs @@ -13,8 +13,7 @@ // limitations under the License. // ANCHOR: Philosopher -use std::sync::mpsc; -use std::sync::{Arc, Mutex}; +use std::sync::{mpsc, Arc, Mutex}; use std::thread; use std::time::Duration; diff --git a/src/exercises/day-4/link-checker.md b/src/exercises/concurrency/link-checker.md similarity index 94% rename from src/exercises/day-4/link-checker.md rename to src/exercises/concurrency/link-checker.md index 9922c90..48896c2 100644 --- a/src/exercises/day-4/link-checker.md +++ b/src/exercises/concurrency/link-checker.md @@ -32,7 +32,15 @@ $ cargo add thiserror The `cargo add` calls will update the `Cargo.toml` file to look like this: + + ```toml +[package] +name = "link-checker" +version = "0.1.0" +edition = "2021" +publish = false + [dependencies] reqwest = { version = "0.11.12", features = ["blocking", "rustls-tls"] } scraper = "0.13.0" @@ -44,6 +52,8 @@ You can now download the start page. Try with a small site such as Your `src/main.rs` file should look something like this: + + ```rust,compile_fail {{#include link-checker.rs:setup}} diff --git a/src/exercises/day-4/link-checker.rs b/src/exercises/concurrency/link-checker.rs similarity index 100% rename from src/exercises/day-4/link-checker.rs rename to src/exercises/concurrency/link-checker.rs diff --git a/src/exercises/day-4/morning.md b/src/exercises/concurrency/morning.md similarity index 100% rename from src/exercises/day-4/morning.md rename to src/exercises/concurrency/morning.md diff --git a/src/exercises/concurrency/solutions-afternoon.md b/src/exercises/concurrency/solutions-afternoon.md new file mode 100644 index 0000000..3ccf76b --- /dev/null +++ b/src/exercises/concurrency/solutions-afternoon.md @@ -0,0 +1,26 @@ +# Concurrency Afternoon Exercise + +## Dining Philosophers - Async + +([back to exercise](dining-philosophers-async.md)) + +```rust,compile_fail +{{#include dining-philosophers-async.rs}} +``` + +## Broadcast Chat Application + +([back to exercise](chat-app.md)) + +`src/bin/server.rs`: + +```rust,compile_fail +{{#include chat-async/src/bin/server.rs}} +``` + +`src/bin/client.rs`: + +```rust,compile_fail +{{#include chat-async/src/bin/client.rs}} +``` + diff --git a/src/exercises/day-4/solutions-morning.md b/src/exercises/concurrency/solutions-morning.md similarity index 79% rename from src/exercises/day-4/solutions-morning.md rename to src/exercises/concurrency/solutions-morning.md index e495b04..ba74e3c 100644 --- a/src/exercises/day-4/solutions-morning.md +++ b/src/exercises/concurrency/solutions-morning.md @@ -1,4 +1,4 @@ -# Day 4 Morning Exercise +# Concurrency Morning Exercise ## Dining Philosophers diff --git a/src/exercises/day-1/book-library.md b/src/exercises/day-1/book-library.md index 3623e6a..3d78f36 100644 --- a/src/exercises/day-1/book-library.md +++ b/src/exercises/day-1/book-library.md @@ -7,8 +7,9 @@ you just need to know part of its API: fn main() { let mut vec = vec![10, 20]; vec.push(30); - println!("middle value: {}", vec[vec.len() / 2]); - for item in vec.iter() { + let midpoint = vec.len() / 2; + println!("middle value: {}", vec[midpoint]); + for item in &vec { println!("item: {item}"); } } @@ -18,11 +19,9 @@ Use this to create a library application. Copy the code below to and update the types to make it compile: ```rust,should_panic - {{#include book-library.rs:setup}} - {{#include book-library.rs:Library_new}} - unimplemented!() + todo!("Initialize and return a `Library` value") } {{#include book-library.rs:Library_len}} diff --git a/src/exercises/day-1/book-library.rs b/src/exercises/day-1/book-library.rs index 9b6c67b..c6efe17 100644 --- a/src/exercises/day-1/book-library.rs +++ b/src/exercises/day-1/book-library.rs @@ -32,16 +32,16 @@ impl Book { } } -// This makes it possible to print Book values with {}. -impl std::fmt::Display for Book { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{} ({})", self.title, self.year) - } -} -// ANCHOR_END: setup - -// ANCHOR: Library_new +// Implement the methods below. Update the `self` parameter to +// indicate the method's required level of ownership over the object: +// +// - `&self` for shared read-only access, +// - `&mut self` for unique and mutable access, +// - `self` for unique access by value. impl Library { + // ANCHOR_END: setup + + // ANCHOR: Library_new fn new() -> Library { // ANCHOR_END: Library_new Library { books: Vec::new() } @@ -49,7 +49,7 @@ impl Library { // ANCHOR: Library_len //fn len(self) -> usize { - // unimplemented!() + // todo!("Return the length of `self.books`") //} // ANCHOR_END: Library_len fn len(&self) -> usize { @@ -58,7 +58,7 @@ impl Library { // ANCHOR: Library_is_empty //fn is_empty(self) -> bool { - // unimplemented!() + // todo!("Return `true` if `self.books` is empty") //} // ANCHOR_END: Library_is_empty fn is_empty(&self) -> bool { @@ -67,7 +67,7 @@ impl Library { // ANCHOR: Library_add_book //fn add_book(self, book: Book) { - // unimplemented!() + // todo!("Add a new book to `self.books`") //} // ANCHOR_END: Library_add_book fn add_book(&mut self, book: Book) { @@ -76,22 +76,33 @@ impl Library { // ANCHOR: Library_print_books //fn print_books(self) { - // unimplemented!() + // todo!("Iterate over `self.books` and each book's title and year") //} // ANCHOR_END: Library_print_books fn print_books(&self) { for book in &self.books { - println!("{}", book); + println!("{}, published in {}", book.title, book.year); } } // ANCHOR: Library_oldest_book //fn oldest_book(self) -> Option<&Book> { - // unimplemented!() + // todo!("Return a reference to the oldest book (if any)") //} // ANCHOR_END: Library_oldest_book fn oldest_book(&self) -> Option<&Book> { - self.books.iter().min_by_key(|book| book.year) + // Using a closure and a built-in method: + // self.books.iter().min_by_key(|book| book.year) + + // Longer hand-written solution: + let mut oldest: Option<&Book> = None; + for book in self.books.iter() { + if oldest.is_none() || book.year < oldest.unwrap().year { + oldest = Some(book); + } + } + + oldest } } @@ -103,24 +114,23 @@ impl Library { fn main() { let library = Library::new(); - //println!("Our library is empty: {}", library.is_empty()); - - let favorite_book = Book::new("Lord of the Rings", 1954); - println!("Our favorite book {favorite_book} should go in the library"); - //library.add_book(favorite_book); + //println!("The library is empty: {}", library.is_empty()); + // + //library.add_book(Book::new("Lord of the Rings", 1954)); //library.add_book(Book::new("Alice's Adventures in Wonderland", 1865)); // + //println!("The library is no longer empty: {}", library.is_empty()); + // + // //library.print_books(); // //match library.oldest_book() { - // Some(book) => println!("My oldest book is {book}"), - // None => println!("My library is empty!"), + // Some(book) => println!("The oldest book is {}", book.title), + // None => println!("The library is empty!"), //} // - //println!("Our library has {} books", library.len()); - for book in library.books { - println!("{book}"); - } + //println!("The library has {} books", library.len()); + //library.print_books(); } // ANCHOR_END: main diff --git a/src/exercises/day-2/luhn.rs b/src/exercises/day-2/luhn.rs index 420e4d8..ce2c6ba 100644 --- a/src/exercises/day-2/luhn.rs +++ b/src/exercises/day-2/luhn.rs @@ -42,8 +42,7 @@ pub fn luhn(cc_number: &str) -> bool { fn main() { let cc_number = "1234 5678 1234 5670"; println!( - "Is {} a valid credit card number? {}", - cc_number, + "Is {cc_number} a valid credit card number? {}", if luhn(cc_number) { "yes" } else { "no" } ); } diff --git a/src/exercises/day-3/safe-ffi-wrapper.md b/src/exercises/day-3/safe-ffi-wrapper.md index 7965add..9ee5bd5 100644 --- a/src/exercises/day-3/safe-ffi-wrapper.md +++ b/src/exercises/day-3/safe-ffi-wrapper.md @@ -10,13 +10,36 @@ You will want to consult the manual pages: * [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html) * [`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html) -You will also want to browse the [`std::ffi`] module, particular for [`CStr`] -and [`CString`] types which are used to hold NUL-terminated strings coming from -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 +string types which you need for the exercise: + +| Types | Encoding | Use | +|----------------------------|----------------|--------------------------------| +| [`str`] and [`String`] | UTF-8 | Text processing in Rust | +| [`CStr`] and [`CString`] | NUL-terminated | Communicating with C functions | +| [`OsStr`] and [`OsString`] | OS-specific | Communicating with the OS | + +You will convert between all these types: + +- `&str` to `CString`: you need to allocate space for a trailing `\0` character, +- `CString` to `*const i8`: you need a pointer to call C functions, +- `*const i8` to `&CStr`: you need something which can find the trailing `\0` character, +- `&CStr` to `&[u8]`: a slice of bytes is the universal interface for "some unknow data", +- `&[u8]` to `&OsStr`: `&OsStr` is a step towards `OsString`, use + [`OsStrExt`](https://doc.rust-lang.org/std/os/unix/ffi/trait.OsStrExt.html) + to create it, +- `&OsStr` to `OsString`: you need to clone the data in `&OsStr` to be able to return it and call + `readdir` again. + +The [Nomicon] also has a very useful chapter about FFI. [`std::ffi`]: https://doc.rust-lang.org/std/ffi/ +[`str`]: https://doc.rust-lang.org/std/primitive.str.html +[`String`]: https://doc.rust-lang.org/std/string/struct.String.html [`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html [`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html +[`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html +[`OsString`]: https://doc.rust-lang.org/std/ffi/struct.OsString.html [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html Copy the code below to and fill in the missing diff --git a/src/exercises/day-3/safe-ffi-wrapper.rs b/src/exercises/day-3/safe-ffi-wrapper.rs index 5f3b50a..6746fea 100644 --- a/src/exercises/day-3/safe-ffi-wrapper.rs +++ b/src/exercises/day-3/safe-ffi-wrapper.rs @@ -14,7 +14,9 @@ // ANCHOR: ffi mod ffi { - use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ushort}; + use std::os::raw::{c_char, c_int}; + #[cfg(not(target_os = "macos"))] + use std::os::raw::{c_long, c_ulong, c_ushort}; // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html. #[repr(C)] @@ -24,6 +26,7 @@ mod ffi { } // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-gnu. + #[cfg(not(target_os = "macos"))] #[repr(C)] pub struct dirent { pub d_ino: c_long, @@ -33,6 +36,18 @@ mod ffi { pub d_name: [c_char; 256], } + // Layout as per man entry for dirent + #[cfg(target_os = "macos")] + #[repr(C)] + pub struct dirent { + pub d_ino: u64, + pub d_seekoff: u64, + pub d_reclen: u16, + pub d_namlen: u16, + pub d_type: u8, + pub d_name: [c_char; 1024], + } + extern "C" { pub fn opendir(s: *const c_char) -> *mut DIR; pub fn readdir(s: *mut DIR) -> *const dirent; @@ -108,3 +123,42 @@ fn main() -> Result<(), String> { Ok(()) } // ANCHOR_END: main + +#[cfg(test)] +mod tests { + use super::*; + use std::error::Error; + + #[test] + fn test_nonexisting_directory() { + let iter = DirectoryIterator::new("no-such-directory"); + assert!(iter.is_err()); + } + + #[test] + fn test_empty_directory() -> Result<(), Box> { + let tmp = tempfile::TempDir::new()?; + let iter = DirectoryIterator::new( + tmp.path().to_str().ok_or("Non UTF-8 character in path")?, + )?; + let mut entries = iter.collect::>(); + entries.sort(); + assert_eq!(entries, &[".", ".."]); + Ok(()) + } + + #[test] + fn test_nonempty_directory() -> Result<(), Box> { + let tmp = tempfile::TempDir::new()?; + std::fs::write(tmp.path().join("foo.txt"), "The Foo Diaries\n")?; + std::fs::write(tmp.path().join("bar.png"), "\n")?; + std::fs::write(tmp.path().join("crab.rs"), "//! Crab\n")?; + let iter = DirectoryIterator::new( + tmp.path().to_str().ok_or("Non UTF-8 character in path")?, + )?; + let mut entries = iter.collect::>(); + entries.sort(); + assert_eq!(entries, &[".", "..", "bar.png", "crab.rs", "foo.txt"]); + Ok(()) + } +} diff --git a/src/exercises/day-3/simple-gui.rs b/src/exercises/day-3/simple-gui.rs index 3bcd72c..a74cd0d 100644 --- a/src/exercises/day-3/simple-gui.rs +++ b/src/exercises/day-3/simple-gui.rs @@ -70,6 +70,13 @@ impl Window { fn add_widget(&mut self, widget: Box) { self.widgets.push(widget); } + + fn inner_width(&self) -> usize { + std::cmp::max( + self.title.chars().count(), + self.widgets.iter().map(|w| w.width()).max().unwrap_or(0), + ) + } } // ANCHOR_END: setup @@ -78,10 +85,8 @@ impl Window { impl Widget for Window { fn width(&self) -> usize { // ANCHOR_END: Window-width - std::cmp::max( - self.title.chars().count(), - self.widgets.iter().map(|w| w.width()).max().unwrap_or(0), - ) + // Add 4 paddings for borders + self.inner_width() + 4 } // ANCHOR: Window-draw_into @@ -92,18 +97,18 @@ impl Widget for Window { widget.draw_into(&mut inner); } - let window_width = self.width(); + let inner_width = self.inner_width(); // TODO: after learning about error handling, you can change // draw_into to return Result<(), std::fmt::Error>. Then use // the ?-operator here instead of .unwrap(). - writeln!(buffer, "+-{:- + +* Try declaring a new variable `let p = Point { x: 5, y: 10.0 };`. + +* Fix the code to allow points that have elements of different types. + + \ No newline at end of file diff --git a/src/generics/trait-objects.md b/src/generics/trait-objects.md deleted file mode 100644 index 4104dc7..0000000 --- a/src/generics/trait-objects.md +++ /dev/null @@ -1,86 +0,0 @@ -# Trait Objects - -We've seen how a function can take arguments which implement a trait: - -```rust,editable -use std::fmt::Display; - -fn print(x: T) { - println!("Your value: {x}"); -} - -fn main() { - print(123); - print("Hello"); -} -``` - -However, how can we store a collection of mixed types which implement `Display`? - -```rust,editable,compile_fail -fn main() { - let xs = vec![123, "Hello"]; -} -``` - -For this, we need _trait objects_: - -```rust,editable -use std::fmt::Display; - -fn main() { - let xs: Vec> = vec![Box::new(123), Box::new("Hello")]; - for x in xs { - println!("x: {x}"); - } -} -``` - -Memory layout after allocating `xs`: - -```bob - Stack Heap -.- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -. -: : : : -: xs : : : -: +-----------+-------+ : : +-----+-----+ : -: | ptr | o---+---+-----+-->| o o | o o | : -: | len | 2 | : : +-|-|-+-|-|-+ : -: | capacity | 2 | : : | | | | +----+----+----+----+----+ : -: +-----------+-------+ : : | | | '-->| H | e | l | l | o | : -: : : | | | +----+----+----+----+----+ : -`- - - - - - - - - - - - - -' : | | | : - : | | | +-------------------------+ : - : | | '---->| "::fmt" | : - : | | +-------------------------+ : - : | | : - : | | +----+----+----+----+ : - : | '-->| 7b | 00 | 00 | 00 | : - : | +----+----+----+----+ : - : | : - : | +-------------------------+ : - : '---->| "::fmt" | : - : +-------------------------+ : - : : - : : - '- - - - - - - - - - - - - - - - - - - - - - - -' -``` - -Similarly, you need a trait object if you want to return different types -implementing a trait: - -```rust,editable -fn numbers(n: i32) -> Box> { - if n > 0 { - Box::new(0..n) - } else { - Box::new((n..0).rev()) - } -} - -fn main() { - println!("{:?}", numbers(-5).collect::>()); - println!("{:?}", numbers(5).collect::>()); -} - -``` diff --git a/src/hello-world.md b/src/hello-world.md index e1c94f5..0a13dde 100644 --- a/src/hello-world.md +++ b/src/hello-world.md @@ -3,7 +3,7 @@ Let us jump into the simplest possible Rust program, a classic Hello World program: -```rust +```rust,editable fn main() { println!("Hello 🌍!"); } diff --git a/src/memory-management/stack.md b/src/memory-management/stack.md index bf92549..ab33239 100644 --- a/src/memory-management/stack.md +++ b/src/memory-management/stack.md @@ -31,20 +31,20 @@ fn main() { * We can inspect the memory layout with `unsafe` code. However, you should point out that this is rightfully unsafe! -```rust,editable -fn main() { - let mut s1 = String::from("Hello"); - s1.push(' '); - s1.push_str("world"); - // DON'T DO THIS AT HOME! For educational purposes only. - // String provides no guarantees about its layout, so this could lead to - // undefined behavior. - unsafe { - let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1); - println!("ptr = {ptr:#x}, len = {len}, capacity = {capacity}"); + ```rust,editable + fn main() { + let mut s1 = String::from("Hello"); + s1.push(' '); + s1.push_str("world"); + // DON'T DO THIS AT HOME! For educational purposes only. + // String provides no guarantees about its layout, so this could lead to + // undefined behavior. + unsafe { + let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1); + println!("ptr = {ptr:#x}, len = {len}, capacity = {capacity}"); + } } -} -``` + ``` diff --git a/src/modules/filesystem.md b/src/modules/filesystem.md index 51f22d7..1afad01 100644 --- a/src/modules/filesystem.md +++ b/src/modules/filesystem.md @@ -21,6 +21,24 @@ The `crate` root is in: * `src/lib.rs` (for a library crate) * `src/main.rs` (for a binary crate) +Modules defined in files can be documented, too, using "inner doc comments". +These document the item that contains them -- in this case, a module. + +```rust,editable,compile_fail +//! This module implements the garden, including a highly performant germination +//! implementation. + +// Re-export types from this module. +pub use seeds::SeedPacket; +pub use garden::Garden; + +/// Sow the given seed packets. +pub fn sow(seeds: Vec) { todo!() } + +/// Harvest the produce in the garden that is ready. +pub fn harvest(garden: &mut Garden) { todo!() } +``` +
* The change from `module/mod.rs` to `module.rs` doesn't preclude the use of submodules in Rust 2018. diff --git a/src/modules/paths.md b/src/modules/paths.md index 2a6f3d0..bf4b954 100644 --- a/src/modules/paths.md +++ b/src/modules/paths.md @@ -9,3 +9,11 @@ Paths are resolved as follows: 2. As an absolute path: * `crate::foo` refers to `foo` in the root of the current crate, * `bar::foo` refers to `foo` in the `bar` crate. + +A module can bring symbols from another module into scope with `use`. +You will typically see something like this at the top of each module: + +```rust,editable +use std::collections::HashSet; +use std::mem::transmute; +``` diff --git a/src/ownership/borrowing.md b/src/ownership/borrowing.md index ce4ec06..a5ed290 100644 --- a/src/ownership/borrowing.md +++ b/src/ownership/borrowing.md @@ -25,7 +25,7 @@ fn main() {
Notes on stack returns: -* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy operation. Change the above code to print stack addresses and run it on the [Playground]. In the "DEBUG" optimization level, the addresses should change, while the stay the same when changing to the "RELEASE" setting: +* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy operation. Change the above code to print stack addresses and run it on the [Playground]. In the "DEBUG" optimization level, the addresses should change, while they stay the same when changing to the "RELEASE" setting: ```rust,editable #[derive(Debug)] diff --git a/src/pattern-matching/destructuring-arrays.md b/src/pattern-matching/destructuring-arrays.md index 6474a68..fdf7ec2 100644 --- a/src/pattern-matching/destructuring-arrays.md +++ b/src/pattern-matching/destructuring-arrays.md @@ -12,22 +12,22 @@ You can destructure arrays, tuples, and slices by matching on their elements: * Destructuring of slices of unknown length also works with patterns of fixed length. -```rust,editable -fn main() { - inspect(&[0, -2, 3]); - inspect(&[0, -2, 3, 4]); -} - -#[rustfmt::skip] -fn inspect(slice: &[i32]) { - println!("Tell me about {slice:?}"); - match slice { - &[0, y, z] => println!("First is 0, y = {y}, and z = {z}"), - &[1, ..] => println!("First is 1 and the rest were ignored"), - _ => println!("All elements were ignored"), - } -} -``` + ```rust,editable + fn main() { + inspect(&[0, -2, 3]); + inspect(&[0, -2, 3, 4]); + } + + #[rustfmt::skip] + fn inspect(slice: &[i32]) { + println!("Tell me about {slice:?}"); + match slice { + &[0, y, z] => println!("First is 0, y = {y}, and z = {z}"), + &[1, ..] => println!("First is 1 and the rest were ignored"), + _ => println!("All elements were ignored"), + } + } + ``` * Create a new pattern using `_` to represent an element. * Add more values to the array. diff --git a/src/pattern-matching/destructuring-structs.md b/src/pattern-matching/destructuring-structs.md index ceaef1d..67fbb21 100644 --- a/src/pattern-matching/destructuring-structs.md +++ b/src/pattern-matching/destructuring-structs.md @@ -9,4 +9,8 @@ You can also destructure `structs`: * Change the literal values in `foo` to match with the other patterns. * Add a new field to `Foo` and make changes to the pattern as needed. +* The distinction between a capture and a constant expression can be hard to + spot. Try changing the `2` in the second arm to a variable, and see that it subtly + doesn't work. Change it to a `const` and see it working again. +
diff --git a/src/running-the-course.md b/src/running-the-course.md index 258a65f..c539c36 100644 --- a/src/running-the-course.md +++ b/src/running-the-course.md @@ -5,55 +5,48 @@ Here is a bit of background information about how we've been running the course internally at Google. -To run the course, you need to: +Before you run the course, you will want to: 1. Make yourself familiar with the course material. We've included speaker notes - to help highlight the key points (please help us by - contributing more speaker notes!). You should make sure to open the speaker - notes in a popup (click the link with a little arrow next to "Speaker - Notes"). This way you have a clean screen to present to the class. + to help highlight the key points (please help us by contributing more speaker + notes!). When presenting, you should make sure to open the speaker notes in a + popup (click the link with a little arrow next to "Speaker Notes"). This way + you have a clean screen to present to the class. -2. Decide on the dates. Since the course is large, we recommend that you - schedule the four days over two weeks. Course participants have said that +1. Decide on the dates. Since the course takes at least three full days, we recommend that you + schedule the days over two weeks. Course participants have said that they find it helpful to have a gap in the course since it helps them process all the information we give them. -3. Find a room large enough for your in-person participants. We recommend a - class size of 15-20 people. That's small enough that people are comfortable +1. Find a room large enough for your in-person participants. We recommend a + class size of 15-25 people. That's small enough that people are comfortable asking questions --- it's also small enough that one instructor will have - time to answer the questions. + time to answer the questions. Make sure the room has _desks_ for yourself and for the + students: you will all need to be able to sit and work with your laptops. + In particular, you will be doing a lot of live-coding as an instructor, so a lectern won't + be very helpful for you. -4. On the day of your course, show up to the room a little early to set things +1. On the day of your course, show up to the room a little early to set things up. We recommend presenting directly using `mdbook serve` running on your - laptop (see the [installation instructions][5]). This ensures optimal performance with no lag as you change pages. + laptop (see the [installation instructions][3]). This ensures optimal performance with no lag as you change pages. Using your laptop will also allow you to fix typos as you or the course participants spot them. -5. Let people solve the exercises by themselves or in small groups. Make sure to +1. Let people solve the exercises by themselves or in small groups. + We typically spend 30-45 minutes on exercises in the morning and in the afternoon (including time to review the solutions). + Make sure to ask people if they're stuck or if there is anything you can help with. When you see that several people have the same problem, call it out to the class and offer a solution, e.g., by showing people where to find the relevant information in the standard library. -6. If you don't skip the Android specific parts on Day 4, you will need an [AOSP - checkout][1]. Make a checkout of the [course repository][2] on the same - machine and move the `src/android/` directory into the root of your AOSP - checkout. This will ensure that the Android build system sees the - `Android.bp` files in `src/android/`. - - Ensure that `adb sync` works with your emulator or real device and pre-build - all Android examples using `src/android/build_all.sh`. Read the script to see - the commands it runs and make sure they work when you run them by hand. - That is all, good luck running the course! We hope it will be as much fun for you as it has been for us! -Please [provide feedback][3] afterwards so that we can keep improving the +Please [provide feedback][1] afterwards so that we can keep improving the course. We would love to hear what worked well for you and what can be made -better. Your students are also very welcome to [send us feedback][4]! +better. Your students are also very welcome to [send us feedback][2]! -[1]: https://source.android.com/docs/setup/download/downloading -[2]: https://github.com/google/comprehensive-rust -[3]: https://github.com/google/comprehensive-rust/discussions/86 -[4]: https://github.com/google/comprehensive-rust/discussions/100 -[5]: https://github.com/google/comprehensive-rust#building +[1]: https://github.com/google/comprehensive-rust/discussions/86 +[2]: https://github.com/google/comprehensive-rust/discussions/100 +[3]: https://github.com/google/comprehensive-rust#building diff --git a/src/running-the-course/course-structure.md b/src/running-the-course/course-structure.md index f87f1d4..e75da3f 100644 --- a/src/running-the-course/course-structure.md +++ b/src/running-the-course/course-structure.md @@ -7,11 +7,56 @@ The course is fast paced and covers a lot of ground: * Day 1: Basic Rust, ownership and the borrow checker. * Day 2: Compound data types, pattern matching, the standard library. * Day 3: Traits and generics, error handling, testing, unsafe Rust. -* Day 4: Concurrency in Rust and interoperability with other languages -> **Exercise for Day 4:** Do you interface with some C/C++ code in your project -> which we could attempt to move to Rust? The fewer dependencies the better. -> Parsing code would be ideal. +## Deep Dives + +In addition to the 3-day class on Rust Fundamentals, we cover some more +specialized topics: + +### Android + +The [Android Deep Dive](../android.md) is a half-day course on using Rust for +Android platform development. This includes interoperability wtih C, C++, and +Java. + +You will need an [AOSP checkout][1]. Make a checkout of the [course +repository][2] on the same machine and move the `src/android/` directory into +the root of your AOSP checkout. This will ensure that the Android build system +sees the `Android.bp` files in `src/android/`. + +Ensure that `adb sync` works with your emulator or real device and pre-build all +Android examples using `src/android/build_all.sh`. Read the script to see the +commands it runs and make sure they work when you run them by hand. + +[1]: https://source.android.com/docs/setup/download/downloading +[2]: https://github.com/google/comprehensive-rust + +### Bare-Metal + +The [Bare-Metal Deep Dive](../bare-metal.md): a full day class on using Rust for +bare-metal (embedded) development. Both microcontrollers and application +processors are covered. + +For the microcontroller part, you will need to buy the [BBC +micro:bit](https://microbit.org/) v2 development board ahead of time. Everybody +will need to install a number of packages as described on the [welcome +page](../bare-metal.md). + +### Concurrency + +The [Concurrency Deep Dive](../concurrency.md) is a full day class on classical +as well as `async`/`await` concurrency. + +You will need a fresh crate set up and the dependencies downloaded and ready to +go. You can then copy/paste the examples into `src/main.rs` to experiment with +them: + +```shell +cargo init concurrency +cd concurrency +cargo add tokio --features full +cargo run +``` ## Format diff --git a/src/std/hashmap.md b/src/std/hashmap.md index 6fa499b..c1552a0 100644 --- a/src/std/hashmap.md +++ b/src/std/hashmap.md @@ -38,23 +38,23 @@ fn main() { * `HashMap` is not defined in the prelude and needs to be brought into scope. * Try the following lines of code. The first line will see if a book is in the hashmap and if not return an alternative value. The second line will insert the alternative value in the hashmap if the book is not found. - ```rust,ignore - let pc1 = page_counts - .get("Harry Potter and the Sorcerer's Stone ") - .unwrap_or(&336); - let pc2 = page_counts - .entry("The Hunger Games".to_string()) - .or_insert(374); - ``` + ```rust,ignore + let pc1 = page_counts + .get("Harry Potter and the Sorcerer's Stone ") + .unwrap_or(&336); + let pc2 = page_counts + .entry("The Hunger Games".to_string()) + .or_insert(374); + ``` * Unlike `vec!`, there is unfortunately no standard `hashmap!` macro. * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], which allows us to easily initialize a hash map from a literal array: - ```rust,ignore - let page_counts = HashMap::from([ - ("Harry Potter and the Sorcerer's Stone".to_string(), 336), - ("The Hunger Games".to_string(), 374), - ]); - ``` + ```rust,ignore + let page_counts = HashMap::from([ + ("Harry Potter and the Sorcerer's Stone".to_string(), 336), + ("The Hunger Games".to_string(), 374), + ]); + ``` * Alternatively HashMap can be built from any `Iterator` which yields key-value tuples. * We are showing `HashMap`, and avoid using `&str` as key to make examples easier. Using references in collections can, of course, be done, diff --git a/src/std/rc.md b/src/std/rc.md index 5f581c9..5ea51da 100644 --- a/src/std/rc.md +++ b/src/std/rc.md @@ -8,7 +8,7 @@ use std::rc::Rc; fn main() { let mut a = Rc::new(10); - let mut b = a.clone(); + let mut b = Rc::clone(&a); println!("a: {a}"); println!("b: {b}"); @@ -28,13 +28,13 @@ fn main() {
-* `Rc`'s Count ensures that its contained value is valid for as long as there are references. +* `Rc`'s count ensures that its contained value is valid for as long as there are references. * Like C++'s `std::shared_ptr`. -* `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. +* `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. * `make_mut` actually clones the inner value if necessary ("clone-on-write") and returns a mutable reference. * Use `Rc::strong_count` to check the reference count. * 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. -* You can `downgrade()` a `Rc` into a *weakly reference-counted* object to +* `Rc::downgrade` gives you a *weakly reference-counted* object to create cycles that will be dropped properly (likely in combination with `RefCell`). diff --git a/src/std/string.md b/src/std/string.md index c44fb7c..9128ee1 100644 --- a/src/std/string.md +++ b/src/std/string.md @@ -35,6 +35,8 @@ fn main() { * `String` implements `Deref` which transparently gives it access to `str`'s methods. * Write and compare `let s3 = s1.deref();` and `let s3 = &*s1`;. * `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. -* 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`: + * To a character by using `s3.chars().nth(i).unwrap()` where `i` is in-bound, out-of-bounds. + * To a substring by using `s3[0..4]`, where that slice is on character boundaries or not.
diff --git a/src/structs/field-shorthand.md b/src/structs/field-shorthand.md index a3830d6..6828ad5 100644 --- a/src/structs/field-shorthand.md +++ b/src/structs/field-shorthand.md @@ -26,13 +26,44 @@ fn main() { * The `new` function could be written using `Self` as a type, as it is interchangeable with the struct type name -```rust,ignore -impl Person { - fn new(name: String, age: u8) -> Self { - Self { name, age } - } -} -``` + ```rust,editable + #[derive(Debug)] + struct Person { + name: String, + age: u8, + } + impl Person { + fn new(name: String, age: u8) -> Self { + Self { name, age } + } + } + ``` +* Implement the `Default` trait for the struct. Define some fields and use the default values for the other fields. + + ```rust,editable + #[derive(Debug)] + struct Person { + name: String, + age: u8, + } + impl Default for Person { + fn default() -> Person { + Person { + name: "Bot".to_string(), + age: 0, + } + } + } + fn create_default() { + let tmp = Person { + ..Default::default() + }; + let tmp = Person { + name: "Sam".to_string(), + ..Default::default() + }; + } + ``` * Methods are defined in the `impl` block. * Use struct update syntax to define a new structure using `peter`. Note that the variable `peter` will no longer be accessible afterwards. diff --git a/src/structs/tuple-structs.md b/src/structs/tuple-structs.md index 1ffc1a4..9524a2a 100644 --- a/src/structs/tuple-structs.md +++ b/src/structs/tuple-structs.md @@ -14,10 +14,10 @@ fn main() { This is often used for single-field wrappers (called newtypes): ```rust,editable,compile_fail -struct PoundOfForce(f64); +struct PoundsOfForce(f64); struct Newtons(f64); -fn compute_thruster_force() -> PoundOfForce { +fn compute_thruster_force() -> PoundsOfForce { todo!("Ask a rocket scientist at NASA") } diff --git a/src/testing/unit-tests.md b/src/testing/unit-tests.md index 95fb2e9..130899c 100644 --- a/src/testing/unit-tests.md +++ b/src/testing/unit-tests.md @@ -2,7 +2,7 @@ Mark unit tests with `#[test]`: -```rust,editable +```rust,editable,ignore fn first_word(text: &str) -> &str { match text.find(' ') { Some(idx) => &text[..idx], diff --git a/src/testing/useful-crates.md b/src/testing/useful-crates.md new file mode 100644 index 0000000..7435643 --- /dev/null +++ b/src/testing/useful-crates.md @@ -0,0 +1,9 @@ +## Useful crates for writing tests + +Rust comes with only basic support for writing tests. + +Here are some additional crates which we recommend for writing tests: + +* [googletest](https://docs.rs/googletest): Comprehensive test assertion library in the tradition of GoogleTest for C++. +* [proptest](https://docs.rs/proptest): Property-based testing for Rust. +* [rstest](https://docs.rs/rstest): Support for fixtures and parameterised tests. diff --git a/src/traits.md b/src/traits.md index dd43e6a..1fc7231 100644 --- a/src/traits.md +++ b/src/traits.md @@ -3,52 +3,37 @@ Rust lets you abstract over types with traits. They're similar to interfaces: ```rust,editable -trait Greet { - fn say_hello(&self); +trait Pet { + fn name(&self) -> String; } struct Dog { name: String, } -struct Cat; // No name, cats won't respond to it anyway. +struct Cat; -impl Greet for Dog { - fn say_hello(&self) { - println!("Wuf, my name is {}!", self.name); +impl Pet for Dog { + fn name(&self) -> String { + self.name.clone() } } -impl Greet for Cat { - fn say_hello(&self) { - println!("Miau!"); +impl Pet for Cat { + fn name(&self) -> String { + String::from("The cat") // No name, cats won't respond to it anyway. } } -fn main() { - let pets: Vec> = vec![ - Box::new(Dog { name: String::from("Fido") }), - Box::new(Cat), - ]; - for pet in pets { - pet.say_hello(); - } +fn greet(pet: &P) { + println!("Who's a cutie? {} is!", pet.name()); } -``` - -
-* Traits may specify pre-implemented (default) methods and methods that users are required to implement themselves. Methods with default implementations can rely on required methods. -* Types that implement a given trait may be of different sizes. This makes it impossible to have things like `Vec` in the example above. -* `dyn Greet` is a way to tell the compiler about a dynamically sized type that implements `Greet`. -* In the example, `pets` holds Fat Pointers to objects that implement `Greet`. The Fat Pointer consists of two components, a pointer to the actual object and a pointer to the virtual method table for the `Greet` implementation of that particular object. +fn main() { + let fido = Dog { name: "Fido".into() }; + greet(&fido); -Compare these outputs in the above example: -```rust,ignore - println!("{} {}", std::mem::size_of::(), std::mem::size_of::()); - println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>()); - println!("{}", std::mem::size_of::<&dyn Greet>()); - println!("{}", std::mem::size_of::>()); + let captain_floof = Cat; + greet(&captain_floof); +} ``` - -
diff --git a/src/generics/closures.md b/src/traits/closures.md similarity index 100% rename from src/generics/closures.md rename to src/traits/closures.md diff --git a/src/traits/default-methods.md b/src/traits/default-methods.md index 66bd92e..1e03513 100644 --- a/src/traits/default-methods.md +++ b/src/traits/default-methods.md @@ -26,3 +26,35 @@ fn main() { println!("{a:?} not_equals {b:?}: {}", a.not_equal(&b)); } ``` + +
+ +* Traits may specify pre-implemented (default) methods and methods that users are required to + implement themselves. Methods with default implementations can rely on required methods. + +* Move method `not_equal` to a new trait `NotEqual`. + +* Make `NotEqual` a super trait for `Equal`. + ```rust,editable,compile_fail + trait NotEqual: Equals { + fn not_equal(&self, other: &Self) -> bool { + !self.equal(other) + } + } + ``` + +* Provide a blanket implementation of `NotEqual` for `Equal`. + ```rust,editable,compile_fail + trait NotEqual { + fn not_equal(&self, other: &Self) -> bool; + } + + impl NotEqual for T where T: Equals { + fn not_equal(&self, other: &Self) -> bool { + !self.equal(other) + } + } + ``` + * With the blanket implementation, you no longer need `NotEqual` as a super trait for `Equal`. + +
\ No newline at end of file diff --git a/src/generics/impl-trait.md b/src/traits/impl-trait.md similarity index 76% rename from src/generics/impl-trait.md rename to src/traits/impl-trait.md index e4e4105..c48348d 100644 --- a/src/generics/impl-trait.md +++ b/src/traits/impl-trait.md @@ -16,7 +16,6 @@ fn main() { } ``` -* `impl Trait` cannot be used with the `::<>` turbo fish syntax. * `impl Trait` allows you to work with types which you cannot name.
@@ -24,15 +23,22 @@ fn main() { The meaning of `impl Trait` is a bit different in the different positions. * For a parameter, `impl Trait` is like an anonymous generic parameter with a trait bound. + * For a return type, it means that the return type is some concrete type that implements the trait, without naming the type. This can be useful when you don't want to expose the concrete type in a public API. + Inference is hard in return position. A function returning `impl Foo` picks + the concrete type it returns, without writing it out in the source. A function + returning a generic type like `collect() -> B` can return any type + satisfying `B`, and the caller may need to choose one, such as with `let x: + Vec<_> = foo.collect()` or with the turbofish, `foo.collect::>()`. + This example is great, because it uses `impl Display` twice. It helps to explain that nothing here enforces that it is _the same_ `impl Display` type. If we used a single `T: Display`, it would enforce the constraint that input `T` and return `T` type are the same type. It would not work for this particular function, as the type we expect as input is likely not what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two independent generic parameters. - +
diff --git a/src/traits/iterator.md b/src/traits/iterator.md index c4108f9..b730c35 100644 --- a/src/traits/iterator.md +++ b/src/traits/iterator.md @@ -29,13 +29,16 @@ fn main() {
-* `IntoIterator` is the trait that makes for loops work. It is implemented by collection types such as - `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also implement it. * The `Iterator` trait implements many common functional programming operations over collections (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can find all the documentation about them. In Rust these functions should produce the code as efficient as equivalent imperative implementations. +* `IntoIterator` is the trait that makes for loops work. It is implemented by collection types such as + `Vec` and references to them such as `&Vec` and `&[T]`. Ranges also implement it. This is why + you can iterate over a vector with `for i in some_vec { .. }` but + `some_vec.next()` doesn't exist. +
[1]: https://doc.rust-lang.org/std/iter/trait.Iterator.html diff --git a/src/generics/trait-bounds.md b/src/traits/trait-bounds.md similarity index 100% rename from src/generics/trait-bounds.md rename to src/traits/trait-bounds.md diff --git a/src/traits/trait-objects.md b/src/traits/trait-objects.md new file mode 100644 index 0000000..584c819 --- /dev/null +++ b/src/traits/trait-objects.md @@ -0,0 +1,83 @@ +# Trait Objects + +Trait objects allow for values of different types, for instance in a collection: + +```rust,editable +trait Pet { + fn name(&self) -> String; +} + +struct Dog { + name: String, +} + +struct Cat; + +impl Pet for Dog { + fn name(&self) -> String { + self.name.clone() + } +} + +impl Pet for Cat { + fn name(&self) -> String { + String::from("The cat") // No name, cats won't respond to it anyway. + } +} + +fn main() { + let pets: Vec> = vec![ + Box::new(Cat), + Box::new(Dog { name: String::from("Fido") }), + ]; + for pet in pets { + println!("Hello {}!", pet.name()); + } +} +``` + + +Memory layout after allocating `pets`: + +```bob + Stack Heap +.- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -. +: : : : +: pets : : : +: +-----------+-------+ : : +-----+-----+ : +: | ptr | o---+---+-----+-->| o o | o o | : +: | len | 2 | : : +-|-|-+-|-|-+ : +: | capacity | 2 | : : | | | | +---------------+ : +: +-----------+-------+ : : | | | '-->| name: "Fido" | : +: : : | | | +---------------+ : +`- - - - - - - - - - - - - -' : | | | : + : | | | +----------------------+ : + : | | '---->| "::name" | : + : | | +----------------------+ : + : | | : + : | | +-+ : + : | '-->|\| : + : | +-+ : + : | : + : | +----------------------+ : + : '---->| "::name" | : + : +----------------------+ : + : : + '- - - - - - - - - - - - - - - - - - - - - - -' + +``` + +
+ +* Types that implement a given trait may be of different sizes. This makes it impossible to have things like `Vec` in the example above. +* `dyn Pet` is a way to tell the compiler about a dynamically sized type that implements `Pet`. +* In the example, `pets` holds *fat pointers* to objects that implement `Pet`. The fat pointer consists of two components, a pointer to the actual object and a pointer to the virtual method table for the `Pet` implementation of that particular object. +* Compare these outputs in the above example: + ```rust,ignore + println!("{} {}", std::mem::size_of::(), std::mem::size_of::()); + println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>()); + println!("{}", std::mem::size_of::<&dyn Pet>()); + println!("{}", std::mem::size_of::>()); + ``` + +
diff --git a/src/unsafe/raw-pointers.md b/src/unsafe/raw-pointers.md index c5340e2..f217566 100644 --- a/src/unsafe/raw-pointers.md +++ b/src/unsafe/raw-pointers.md @@ -7,11 +7,12 @@ fn main() { let mut num = 5; let r1 = &mut num as *mut i32; - let r2 = &num as *const i32; + let r2 = r1 as *const i32; - // Safe because r1 and r2 were obtained from references and so are guaranteed to be non-null and - // properly aligned, the objects underlying the references from which they were obtained are - // live throughout the whole unsafe block, and they are not accessed either through the + // Safe because r1 and r2 were obtained from references and so are + // guaranteed to be non-null and properly aligned, the objects underlying + // the references from which they were obtained are live throughout the + // whole unsafe block, and they are not accessed either through the // references or concurrently through any other pointers. unsafe { println!("r1 is: {}", *r1); diff --git a/src/welcome-day-4.md b/src/welcome-day-4.md deleted file mode 100644 index a087cc8..0000000 --- a/src/welcome-day-4.md +++ /dev/null @@ -1,13 +0,0 @@ -# Welcome to Day 4 - -Today we will look at two main topics: - -* Concurrency: threads, channels, shared state, `Send` and `Sync`. - -* Android: building binaries and libraries, using AIDL, logging, and - interoperability with C, C++, and Java. - -> We will attempt to call Rust from one of your own projects today. So try to -> find a little corner of your code base where we can move some lines of code to -> Rust. The fewer dependencies and "exotic" types the better. Something that -> parses some raw bytes would be ideal. diff --git a/src/welcome.md b/src/welcome.md index 8de310d..7142cae 100644 --- a/src/welcome.md +++ b/src/welcome.md @@ -1,6 +1,10 @@ # Welcome to Comprehensive Rust 🦀 -This is a four day Rust course developed by the Android team. The course covers +[![Build workflow](https://img.shields.io/github/actions/workflow/status/google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/google/comprehensive-rust/actions/workflows/build.yml?query=branch%3Amain) +[![GitHub contributors](https://img.shields.io/github/contributors/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/graphs/contributors) +[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-rust?style=flat-square)](https://github.com/google/comprehensive-rust/stargazers) + +This is a three day Rust course developed by the Android team. The course covers the full spectrum of Rust, from basic syntax to advanced topics like generics and error handling. It also includes Android-specific content on the last day. @@ -11,25 +15,25 @@ about Rust and hope to: * Enable you to modify existing programs and write new programs in Rust. * Show you common Rust idioms. -On Day 4, we will cover Android-specific things such as: +The first three days show you the fundamentals of Rust. Following this, you're +invited to dive into one or more spezialized topics: -* Building Android components in Rust. -* AIDL servers and clients. -* Interoperability with C, C++, and Java. +* [Android](android.md): a half-day course on using Rust for Android platform + development (AOSP). This includes interoperability wtih C, C++, and Java. +* [Bare-metal](bare-metal.md): a full day class on using Rust for bare-metal + (embedded) development. Both microcontrollers and application processors are + covered. +* [Concurrency](concurrency.md): a full day class on concurrency in Rust. We + cover both classical concurrency (preemptively scheduling using threads and + mutextes) and async/await concurrency (cooperative multitasking using + futures). -It is important to note that this course does not cover Android **application** -development in Rust, and that the Android-specific parts are specifically about -writing code for Android itself, the operating system. ## Non-Goals Rust is a large language and we won't be able to cover all of it in a few days. Some non-goals of this course are: -* Learn how to use async Rust --- we'll only mention async Rust when - covering traditional concurrency primitives. Please see [Asynchronous - Programming in Rust](https://rust-lang.github.io/async-book/) instead for - details on this topic. * Learn how to develop macros, please see [Chapter 19.5 in the Rust Book](https://doc.rust-lang.org/book/ch19-06-macros.html) and [Rust by Example](https://doc.rust-lang.org/rust-by-example/macros.html) instead. diff --git a/theme/index.hbs b/theme/index.hbs index 4541da8..1381b49 100644 --- a/theme/index.hbs +++ b/theme/index.hbs @@ -163,9 +163,6 @@
  • -