From 5666925d654a933d3fcb2c96306659adc2a321a6 Mon Sep 17 00:00:00 2001 From: Jan Walter Date: Tue, 9 Jan 2024 17:26:37 +0100 Subject: [PATCH] Source code for chapter 1 of the Rust by Example (online) book. --- rust/rust_by_example/Makefile | 64 +++++++++++++ rust/rust_by_example/comments/Cargo.toml | 8 ++ rust/rust_by_example/comments/src/main.rs | 29 ++++++ .../rust_by_example/debug_printing/Cargo.toml | 8 ++ .../debug_printing/src/main.rs | 41 +++++++++ .../format_printing/Cargo.toml | 8 ++ .../format_printing/src/main.rs | 80 ++++++++++++++++ rust/rust_by_example/formatted/Cargo.toml | 8 ++ rust/rust_by_example/formatted/src/main.rs | 64 +++++++++++++ rust/rust_by_example/formatting/Cargo.toml | 8 ++ rust/rust_by_example/formatting/src/main.rs | 91 +++++++++++++++++++ rust/rust_by_example/hello/Cargo.toml | 8 ++ rust/rust_by_example/hello/src/main.rs | 9 ++ rust/rust_by_example/list_printing/Cargo.toml | 8 ++ .../rust_by_example/list_printing/src/main.rs | 33 +++++++ 15 files changed, 467 insertions(+) create mode 100644 rust/rust_by_example/Makefile create mode 100644 rust/rust_by_example/comments/Cargo.toml create mode 100644 rust/rust_by_example/comments/src/main.rs create mode 100644 rust/rust_by_example/debug_printing/Cargo.toml create mode 100644 rust/rust_by_example/debug_printing/src/main.rs create mode 100644 rust/rust_by_example/format_printing/Cargo.toml create mode 100644 rust/rust_by_example/format_printing/src/main.rs create mode 100644 rust/rust_by_example/formatted/Cargo.toml create mode 100644 rust/rust_by_example/formatted/src/main.rs create mode 100644 rust/rust_by_example/formatting/Cargo.toml create mode 100644 rust/rust_by_example/formatting/src/main.rs create mode 100644 rust/rust_by_example/hello/Cargo.toml create mode 100644 rust/rust_by_example/hello/src/main.rs create mode 100644 rust/rust_by_example/list_printing/Cargo.toml create mode 100644 rust/rust_by_example/list_printing/src/main.rs diff --git a/rust/rust_by_example/Makefile b/rust/rust_by_example/Makefile new file mode 100644 index 0000000..bc7d1a7 --- /dev/null +++ b/rust/rust_by_example/Makefile @@ -0,0 +1,64 @@ +target: all + +all: hello comments formatted debug_printing format_printing list_printing formatting + +# hello + +hello: hello/target/debug/hello + +hello/target/debug/hello: hello/src/main.rs + cd hello; cargo run; cd .. + +# comments + +comments: comments/target/debug/comments + +comments/target/debug/comments: comments/src/main.rs + cd comments; cargo run; cd .. + +# formatted + +formatted: formatted/target/debug/formatted + +formatted/target/debug/formatted: formatted/src/main.rs + cd formatted; cargo run; cd .. + +# debug_printing + +debug_printing: debug_printing/target/debug/debug_printing + +debug_printing/target/debug/debug_printing: debug_printing/src/main.rs + cd debug_printing; cargo run; cd .. + +# format_printing + +format_printing: format_printing/target/debug/format_printing + +format_printing/target/debug/format_printing: format_printing/src/main.rs + cd format_printing; cargo run; cd .. + +# list_printing + +list_printing: list_printing/target/debug/list_printing + +list_printing/target/debug/list_printing: list_printing/src/main.rs + cd list_printing; cargo run; cd .. + +# formatting + +formatting: formatting/target/debug/formatting + +formatting/target/debug/formatting: formatting/src/main.rs + cd formatting; cargo run; cd .. + +# clean + +clean: + -rm -fr hello/target + -rm -fr comments/target + -rm -fr formatted/target + -rm -fr debug_printing/target + -rm -fr format_printing/target + -rm -fr list_printing/target + -rm -fr formatting/target + diff --git a/rust/rust_by_example/comments/Cargo.toml b/rust/rust_by_example/comments/Cargo.toml new file mode 100644 index 0000000..476474d --- /dev/null +++ b/rust/rust_by_example/comments/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "comments" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rust/rust_by_example/comments/src/main.rs b/rust/rust_by_example/comments/src/main.rs new file mode 100644 index 0000000..b8c08e3 --- /dev/null +++ b/rust/rust_by_example/comments/src/main.rs @@ -0,0 +1,29 @@ +fn main() { + // This is an example of a line comment. + // There are two slashes at the beginning of the line. + // And nothing written after these will be read by the compiler. + + println!("Hello, world!"); + + // Run it. See? Now try deleting the two slashes, and run it again. + + /* + * This is another type of comment, a block comment. In general, + * line comments are the recommended comment style. But block comments + * are extremely useful for temporarily disabling chunks of code. + * /* Block comments can be /* nested, */ */ so it takes only a few + * keystrokes to comment out everything in this main() function. + * /*/*/* Try it yourself! */*/*/ + */ + + /* + Note: The previous column of `*` was entirely for style. There's + no actual need for it. + */ + + // You can manipulate expressions more easily with block comments + // than with line comments. Try deleting the comment delimiters + // to change the result: + let x = 5 + 90 + 5; + println!("Is `x` 10 or 100? x = {}", x); +} diff --git a/rust/rust_by_example/debug_printing/Cargo.toml b/rust/rust_by_example/debug_printing/Cargo.toml new file mode 100644 index 0000000..afaa5fb --- /dev/null +++ b/rust/rust_by_example/debug_printing/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "debug_printing" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rust/rust_by_example/debug_printing/src/main.rs b/rust/rust_by_example/debug_printing/src/main.rs new file mode 100644 index 0000000..d1a2915 --- /dev/null +++ b/rust/rust_by_example/debug_printing/src/main.rs @@ -0,0 +1,41 @@ +// Derive the `fmt::Debug` implementation for `Structure`. `Structure` +// is a structure which contains a single `i32`. +#[derive(Debug)] +struct Structure(i32); + +// Put a `Structure` inside of the structure `Deep`. Make it printable +// also. +#[derive(Debug)] +struct Deep(Structure); + +#[derive(Debug)] +struct Person<'a> { + name: &'a str, + age: u8, +} + +fn main() { + // Printing with `{:?}` is similar to with `{}`. + println!("{:?} months in a year.", 12); + println!( + "{1:?} {0:?} is the {actor:?} name.", + "Slater", + "Christian", + actor = "actor's" + ); + + // `Structure` is printable! + println!("Now {:?} will print!", Structure(3)); + + // The problem with `derive` is there is no control over how + // the results look. What if I want this to just show a `7`? + println!("Now {:?} will print!", Deep(Structure(7))); + + // Input for pretty printing + let name = "Peter"; + let age = 27; + let peter = Person { name, age }; + + // Pretty print + println!("{:#?}", peter); +} diff --git a/rust/rust_by_example/format_printing/Cargo.toml b/rust/rust_by_example/format_printing/Cargo.toml new file mode 100644 index 0000000..5c2a021 --- /dev/null +++ b/rust/rust_by_example/format_printing/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "format_printing" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rust/rust_by_example/format_printing/src/main.rs b/rust/rust_by_example/format_printing/src/main.rs new file mode 100644 index 0000000..2b789b8 --- /dev/null +++ b/rust/rust_by_example/format_printing/src/main.rs @@ -0,0 +1,80 @@ +use std::fmt; // Import `fmt` + +// A structure holding two numbers. `Debug` will be derived so the results can +// be contrasted with `Display`. +#[derive(Debug)] +struct MinMax(i64, i64); + +// Implement `Display` for `MinMax`. +impl fmt::Display for MinMax { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Use `self.number` to refer to each positional data point. + write!(f, "({}, {})", self.0, self.1) + } +} + +// Define a structure where the fields are nameable for comparison. +#[derive(Debug)] +struct Point2D { + x: f64, + y: f64, +} + +// Similarly, implement `Display` for `Point2D`. +impl fmt::Display for Point2D { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Customize so only `x` and `y` are denoted. + write!(f, "x: {}, y: {}", self.x, self.y) + } +} + +// Define a structure where the fields are nameable for comparison. +#[derive(Debug)] +struct Complex { + real: f64, + imag: f64, +} + +// Similarly, implement `Display` for `Complex`. +impl fmt::Display for Complex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Customize so only `real` and `imag` are denoted. + write!(f, "{real} + {imag}i", real = self.real, imag = self.imag) + } +} + +fn main() { + let minmax = MinMax(0, 14); + + println!("Compare structures:"); + println!("Display: {}", minmax); + println!("Debug: {:?}", minmax); + + let big_range = MinMax(-300, 300); + let small_range = MinMax(-3, 3); + + println!( + "The big range is {big} and the small is {small}", + small = small_range, + big = big_range + ); + + let point = Point2D { x: 3.3, y: 7.2 }; + + println!("Compare points:"); + println!("Display: {}", point); + println!("Debug: {:?}", point); + + // Error. Both `Debug` and `Display` were implemented, but `{:b}` + // requires `fmt::Binary` to be implemented. This will not work. + // println!("What does Point2D look like in binary: {:b}?", point); + + let complex = Complex { + real: 3.3, + imag: 7.2, + }; + + println!("Compare complex numbers:"); + println!("Display: {}", complex); + println!("Debug: {:?}", complex); +} diff --git a/rust/rust_by_example/formatted/Cargo.toml b/rust/rust_by_example/formatted/Cargo.toml new file mode 100644 index 0000000..079b980 --- /dev/null +++ b/rust/rust_by_example/formatted/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "formatted" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rust/rust_by_example/formatted/src/main.rs b/rust/rust_by_example/formatted/src/main.rs new file mode 100644 index 0000000..7ee282d --- /dev/null +++ b/rust/rust_by_example/formatted/src/main.rs @@ -0,0 +1,64 @@ +fn main() { + // In general, the `{}` will be automatically replaced with any + // arguments. These will be stringified. + println!("{} days", 31); + + // Positional arguments can be used. Specifying an integer inside `{}` + // determines which additional argument will be replaced. Arguments start + // at 0 immediately after the format string. + println!("{0}, this is {1}. {1}, this is {0}.", "Alice", "Bob"); + + // As can named arguments. + println!( + "{subject} {verb} {object}", + object = "the lazy dog", + subject = "the quick brown fox", + verb = "jumps over" + ); + + // Different formatting can be invoked by specifying the format character + // after a `:`. + println!("Base 10: {}", 69420); // 69420 + println!("Base 2 (binary): {:b}", 69420); // 10000111100101100 + println!("Base 8 (octal): {:o}", 69420); // 207454 + println!("Base 16 (hexadecimal): {:x}", 69420); // 10f2c + println!("Base 16 (hexadecimal): {:X}", 69420); // 10F2C + + // You can right-justify text with a specified width. This will + // output " 1". (Four white spaces and a "1", for a total width of 5.) + println!("{number:>5}", number = 1); + + // You can pad numbers with extra zeroes, + println!("{number:0>5}", number = 1); // 00001 + // and left-adjust by flipping the sign. This will output "10000". + println!("{number:0<5}", number = 1); // 10000 + + // You can use named arguments in the format specifier by appending a `$`. + println!("{number:0>width$}", number = 1, width = 5); + + // Rust even checks to make sure the correct number of arguments are used. + println!("My name is {0}, {1} {0}", "Bond", "James"); + // FIXME ^ Add the missing argument: "James" + + // Only types that implement fmt::Display can be formatted with `{}`. User- + // defined types do not implement fmt::Display by default. + + #[allow(dead_code)] // disable `dead_code` which warn against unused module + struct Structure(i32); + + // This will not compile because `Structure` does not implement + // fmt::Display. + // println!("This struct `{}` won't print...", Structure(3)); + // TODO ^ Try uncommenting this line + + // For Rust 1.58 and above, you can directly capture the argument from a + // surrounding variable. Just like the above, this will output + // " 1", 4 white spaces and a "1". + let number: f64 = 1.0; + let width: usize = 5; + println!("{number:>width$}"); + + // Controlling the number of decimal places shown + let pi = 3.141592; + println!("Pi is roughly {0:.3}", pi); +} diff --git a/rust/rust_by_example/formatting/Cargo.toml b/rust/rust_by_example/formatting/Cargo.toml new file mode 100644 index 0000000..43be7bf --- /dev/null +++ b/rust/rust_by_example/formatting/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "formatting" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rust/rust_by_example/formatting/src/main.rs b/rust/rust_by_example/formatting/src/main.rs new file mode 100644 index 0000000..56fe31d --- /dev/null +++ b/rust/rust_by_example/formatting/src/main.rs @@ -0,0 +1,91 @@ +use std::fmt::{self, Display, Formatter}; + +struct City { + name: &'static str, + // Latitude + lat: f32, + // Longitude + lon: f32, +} + +impl Display for City { + // `f` is a buffer, and this method must write the formatted string into it. + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let lat_c = if self.lat >= 0.0 { 'N' } else { 'S' }; + let lon_c = if self.lon >= 0.0 { 'E' } else { 'W' }; + + // `write!` is like `format!`, but it will write the formatted string + // into a buffer (the first argument). + write!( + f, + "{}: {:.3}°{} {:.3}°{}", + self.name, + self.lat.abs(), + lat_c, + self.lon.abs(), + lon_c + ) + } +} + +#[derive(Debug)] +struct Color { + red: u8, + green: u8, + blue: u8, +} + +impl Display for Color { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let rgb: u32 = + (self.red as u32 * 65536_u32) + (self.green as u32 * 256_u32) + self.blue as u32; + write!( + f, + "RGB ({}, {}, {}) 0x{:0>6X}", + self.red, self.green, self.blue, rgb + ) + } +} + +fn main() { + for city in [ + City { + name: "Dublin", + lat: 53.347778, + lon: -6.259722, + }, + City { + name: "Oslo", + lat: 59.95, + lon: 10.75, + }, + City { + name: "Vancouver", + lat: 49.25, + lon: -123.1, + }, + ] { + println!("{}", city); + } + for color in [ + Color { + red: 128, + green: 255, + blue: 90, + }, + Color { + red: 0, + green: 3, + blue: 254, + }, + Color { + red: 0, + green: 0, + blue: 0, + }, + ] { + // Switch this to use {} once you've added an implementation + // for fmt::Display. + println!("{}", color); + } +} diff --git a/rust/rust_by_example/hello/Cargo.toml b/rust/rust_by_example/hello/Cargo.toml new file mode 100644 index 0000000..fb1ec2c --- /dev/null +++ b/rust/rust_by_example/hello/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "hello" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rust/rust_by_example/hello/src/main.rs b/rust/rust_by_example/hello/src/main.rs new file mode 100644 index 0000000..38649da --- /dev/null +++ b/rust/rust_by_example/hello/src/main.rs @@ -0,0 +1,9 @@ +// This is the main function. + +fn main() { + // Statements here are executed when the compiled binary is called. + + // Print text to console. + println!("Hello World!"); + println!("I'm a Rustacean!"); +} diff --git a/rust/rust_by_example/list_printing/Cargo.toml b/rust/rust_by_example/list_printing/Cargo.toml new file mode 100644 index 0000000..21351da --- /dev/null +++ b/rust/rust_by_example/list_printing/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "list_printing" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rust/rust_by_example/list_printing/src/main.rs b/rust/rust_by_example/list_printing/src/main.rs new file mode 100644 index 0000000..f15e15d --- /dev/null +++ b/rust/rust_by_example/list_printing/src/main.rs @@ -0,0 +1,33 @@ +use std::fmt; // Import the `fmt` module. + +// Define a structure named `List` containing a `Vec`. +struct List(Vec); + +impl fmt::Display for List { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Extract the value using tuple indexing, + // and create a reference to `vec`. + let vec = &self.0; + + write!(f, "[")?; + + // Iterate over `v` in `vec` while enumerating the iteration + // count in `count`. + for (count, v) in vec.iter().enumerate() { + // For every element except the first, add a comma. + // Use the ? operator to return on errors. + if count != 0 { + write!(f, ", ")?; + } + write!(f, "{}", v)?; + } + + // Close the opened bracket and return a fmt::Result value. + write!(f, "]") + } +} + +fn main() { + let v = List(vec![1, 2, 3]); + println!("{}", v); +} -- 2.45.2