From 7d68a0869f8f7c76b233b384ca67586edc331531 Mon Sep 17 00:00:00 2001 From: Martin Geisler Date: Sun, 10 Sep 2023 10:14:07 +0200 Subject: [PATCH] da: copy mostly trivial code blocks (#1123) Most of these code blocks don't have strings or comments to translate (but a few do). Part of #286. --- po/da.po | 1041 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1037 insertions(+), 4 deletions(-) diff --git a/po/da.po b/po/da.po index f3c8e89f..5b669310 100644 --- a/po/da.po +++ b/po/da.po @@ -1320,6 +1320,12 @@ msgid "" "cargo run\n" "```" msgstr "" +"```shell\n" +"cargo init concurrency\n" +"cd concurrency\n" +"cargo add tokio --features full\n" +"cargo run\n" +"```" #: src/running-the-course/course-structure.md:61 msgid "Format" @@ -1470,14 +1476,13 @@ msgid "" msgstr "" #: src/cargo.md:18 -#, fuzzy msgid "" "```shell\n" " sudo apt install cargo rust-src rustfmt\n" "```" msgstr "" "```shell\n" -"$ sudo apt install cargo rust-src rustfmt\n" +" sudo apt install cargo rust-src rustfmt\n" "```" #: src/cargo.md:22 @@ -1755,6 +1760,10 @@ msgid "" " Created binary (application) `exercise` package\n" "```" msgstr "" +"```shell\n" +"$ cargo new exercise\n" +" Created binary (application) `exercise` package\n" +"```" #: src/cargo/running-locally.md:29 msgid "" @@ -1772,6 +1781,14 @@ msgid "" "Hello, world!\n" "```" msgstr "" +"```shell\n" +"$ cd exercise\n" +"$ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +" Running `target/debug/exercise`\n" +"Hello, world!\n" +"```" #: src/cargo/running-locally.md:40 msgid "" @@ -1787,6 +1804,11 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"fn main() {\n" +" println!(\"Redigér mig!\");\n" +"}\n" +"```" #: src/cargo/running-locally.md:49 msgid "Use `cargo run` to build and run your updated binary:" @@ -1802,6 +1824,13 @@ msgid "" "Edit me!\n" "```" msgstr "" +"```shell\n" +"$ cargo run\n" +" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +" Running `target/debug/exercise`\n" +"Redigér mig!\n" +"```" #: src/cargo/running-locally.md:59 msgid "" @@ -2542,6 +2571,12 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" println!(r#\"link\"#);\n" +" println!(\"link\");\n" +"}\n" +"```" #: src/basic-syntax/scalar-types.md:34 msgid "Byte strings allow you to create a `&[u8]` value directly:" @@ -2556,6 +2591,12 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" println!(\"{:?}\", b\"abc\");\n" +" println!(\"{:?}\", &[97, 98, 99]);\n" +"}\n" +"```" #: src/basic-syntax/scalar-types.md:43 msgid "" @@ -2602,6 +2643,13 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let mut a: [i8; 10] = [42; 10];\n" +" a[5] = 0;\n" +" println!(\"a: {:?}\", a);\n" +"}\n" +"```" #: src/basic-syntax/compound-types.md:18 msgid "Tuple assignment and access:" @@ -2617,6 +2665,13 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let t: (i8, bool) = (7, true);\n" +" println!(\"1. indeks: {}\", t.0);\n" +" println!(\"2. indeks: {}\", t.1);\n" +"}\n" +"```" #: src/basic-syntax/compound-types.md:32 msgid "Arrays:" @@ -2695,6 +2750,14 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/basic-syntax/references.md:14 msgid "Some notes:" @@ -2743,6 +2806,16 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/basic-syntax/references-dangling.md:16 msgid "A reference is said to \"borrow\" the value it refers to." @@ -2775,6 +2848,16 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" +" println!(\"a: {a:?}\");\n" +"\n" +" let s: &[i32] = &a[2..4];\n" +"\n" +" println!(\"s: {s:?}\");\n" +"}\n" +"```" #: src/basic-syntax/slices.md:16 msgid "Slices borrow data from the sliced type." @@ -2856,6 +2939,20 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let s1: &str = \"Verden\";\n" +" println!(\"s1: {s1}\");\n" +"\n" +" let mut s2: String = String::from(\"Hallo \");\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:" @@ -2945,6 +3042,33 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/basic-syntax/functions.md:35 msgid "" @@ -3063,6 +3187,29 @@ msgid "" "}\n" "```" msgstr "" +"```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!(\"gammelt areal: {}\", rect.area());\n" +" rect.inc_width(5);\n" +" println!(\"nyt areal: {}\", rect.area());\n" +"}\n" +"```" #: src/basic-syntax/methods.md:30 msgid "" @@ -3082,6 +3229,11 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"fn new(width: u32, height: u32) -> Rectangle {\n" +" Rectangle { width, height }\n" +"}\n" +"```" #: src/basic-syntax/methods.md:42 msgid "" @@ -3146,6 +3298,16 @@ msgid "" "}\n" "```" msgstr "" +"```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!(\"mønt kast: {}\", pick_one(\"plat\", \"krone\"));\n" +" println!(\"pengepremie: {}\", pick_one(500, 1000));\n" +"}\n" +"```" #: src/basic-syntax/functions-interlude.md:27 msgid "" @@ -3221,6 +3383,18 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/exercises/day-1/implicit-conversions.md:19 msgid "" @@ -3280,6 +3454,9 @@ msgid "" "let array = [10, 20, 30];\n" "```" msgstr "" +"```rust\n" +"let array = [10, 20, 30];\n" +"```" #: src/exercises/day-1/for-loops.md:9 msgid "" @@ -3296,6 +3473,12 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let array = [10, 20, 30];\n" +" println!(\"array: {array:?}\");\n" +"}\n" +"```" #: src/exercises/day-1/for-loops.md:18 msgid "" @@ -11768,14 +11951,13 @@ msgid "The logs show up in `adb logcat`:" msgstr "" #: src/android/logging.md:52 -#, fuzzy msgid "" "```shell\n" "adb logcat -s rust\n" "```" msgstr "" "```shell\n" -"$ sudo apt install cargo rust-src rustfmt\n" +"adb logcat -s rust\n" "```" #: src/android/logging.md:56 @@ -11837,6 +12019,17 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/android/interoperability/with-c.md:20 msgid "" @@ -11996,6 +12189,22 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/android/interoperability/with-c/bindgen.md:100 msgid "" @@ -12064,6 +12273,22 @@ msgid "" "}\n" "```" msgstr "" +"```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}) er mindst!\");\n" +" } else {\n" +" println!(\"y ({y}) er muligvis større end x ({x})\");\n" +" }\n" +"}\n" +"```" #: src/android/interoperability/with-c/rust.md:24 msgid "_interoperability/rust/libanalyze/analyze.h_" @@ -12576,6 +12801,17 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/minimal.md:17 msgid "This will compile to an empty binary." @@ -12642,6 +12878,37 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/alloc.md:39 msgid "" @@ -12697,6 +12964,21 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/microcontrollers.md:21 msgid "" @@ -12784,6 +13066,67 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/microcontrollers/mmio.md:64 msgid "" @@ -12804,6 +13147,9 @@ msgid "" "cargo embed --bin mmio\n" "```" msgstr "" +"```sh\n" +"cargo embed --bin mmio\n" +"```" #: src/bare-metal/microcontrollers/pacs.md:1 msgid "Peripheral Access Crates" @@ -12858,6 +13204,45 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/microcontrollers/pacs.md:49 msgid "" @@ -12894,6 +13279,9 @@ msgid "" "cargo embed --bin pac\n" "```" msgstr "" +"```sh\n" +"cargo embed --bin pac\n" +"```" #: src/bare-metal/microcontrollers/hals.md:1 msgid "HAL crates" @@ -13051,6 +13439,35 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/microcontrollers/type-state.md:32 msgid "" @@ -14210,6 +14627,35 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/aps/better-uart/bitflags.md:37 msgid "" @@ -14262,6 +14708,39 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/aps/better-uart/registers.md:41 msgid "" @@ -14598,6 +15077,59 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"use log::error;\n" +"use smccc::psci::system_off;\n" +"use smccc::Hvc;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_exception_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"```" #: src/bare-metal/aps/exceptions.md:64 msgid "EL is exception level; all our examples this afternoon run in EL1." @@ -14745,6 +15277,39 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/useful-crates/zerocopy.md:40 msgid "" @@ -14905,6 +15470,18 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/useful-crates/tinyvec.md:23 msgid "" @@ -14948,6 +15525,17 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/bare-metal/useful-crates/spin.md:23 msgid "Be careful to avoid deadlock if you take locks in interrupt handlers." @@ -15044,6 +15632,18 @@ msgid "" "}\n" "```" msgstr "" +"```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!(\"Hej verden\");\n" +"}\n" +"```" #: src/bare-metal/android/vmbase.md:21 msgid "" @@ -15246,6 +15846,76 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/exercises/bare-metal/rtc.md:149 msgid "`src/logger.rs` (you shouldn't need to change this):" @@ -15311,6 +15981,63 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/exercises/bare-metal/rtc.md:210 msgid "`src/pl011.rs` (you shouldn't need to change this):" @@ -15494,6 +16221,181 @@ msgid "" "unsafe impl Send for Uart {}\n" "```" msgstr "" +"```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" +"```" #: src/exercises/bare-metal/rtc.md:389 msgid "" @@ -16445,6 +17347,24 @@ msgid "" "}\n" "```" msgstr "" +"```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!(\"Modtaget: {:?}\", rx.recv());\n" +" println!(\"Modtaget: {:?}\", rx.recv());\n" +"\n" +" let tx2 = tx.clone();\n" +" tx2.send(30).unwrap();\n" +" println!(\"Modtaget: {:?}\", rx.recv());\n" +"}\n" +"```" #: src/concurrency/channels.md:27 msgid "" @@ -16540,6 +17460,29 @@ msgid "" "}\n" "```" msgstr "" +"```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!(\"Besked {i}\")).unwrap();\n" +" println!(\"{thread_id:?}: sendte Besked {i}\");\n" +" }\n" +" println!(\"{thread_id:?}: færdig\");\n" +" });\n" +" thread::sleep(Duration::from_millis(100));\n" +"\n" +" for msg in rx.iter() {\n" +" println!(\"Hovedtråden: fik {msg}\");\n" +" }\n" +"}\n" +"```" #: src/concurrency/channels/bounded.md:31 msgid "" @@ -17776,6 +18719,32 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/async/control-flow/join.md:38 msgid "" @@ -17864,6 +18833,52 @@ msgid "" "}\n" "```" msgstr "" +"```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(\"Kunne ikke sende katten.\");\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(\"Kunne ikke sende hunden.\");\n" +" });\n" +"\n" +" let winner = first_animal_to_finish_race(cat_receiver, dog_receiver)\n" +" .await\n" +" .expect(\"Kunne ikke modtage vinderen\");\n" +"\n" +" println!(\"Vinderen er {winner:?}\");\n" +"}\n" +"```" #: src/async/control-flow/select.md:62 msgid "" @@ -18107,6 +19122,15 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/async/pitfalls/pin.md:88 msgid "" @@ -18127,6 +19151,15 @@ msgid "" "}\n" "```" msgstr "" +"```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" +"```" #: src/async/pitfalls/pin.md:102 msgid ""