### Install Texlive and Pandoc for PDF Building Source: https://github.com/rust-unofficial/patterns/blob/main/README.md Installs Texlive and its related packages, along with downloading a specific version of Pandoc for PDF rendering. This is a prerequisite for building the book in PDF format. ```sh # Source the .env file to get the PANDOC_VERSION . ./.env sudo apt-get update sudo apt-get install -y texlive texlive-latex-extra texlive-luatex texlive-lang-cjk librsvg2-bin fonts-noto curl -LsSf https://github.com/jgm/pandoc/releases/download/$PANDOC_VERSION/pandoc-$PANDOC_VERSION-linux-amd64.tar.gz | tar zxf - ``` -------------------------------- ### Install mdbook and Dependencies Source: https://github.com/rust-unofficial/patterns/blob/main/README.md Installs the mdbook tool and additional plugins for features like last-changed dates, PDF rendering via pandoc, and i18n support. Requires Rust and Cargo to be installed. ```sh cargo install mdbook cargo install mdbook-last-changed cargo install mdbook-pandoc cargo install mdbook-i18n-helpers ``` -------------------------------- ### Rust Example of Serde Serialization and Deserialization Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/optics.md Demonstrates the usage of the `Serde` trait and generated visitor types for serializing a `TestStruct` to JSON and then deserializing it back. This example highlights the workflow enabled by Serde's derive macros and visitor pattern. ```rust fn main() { let a = TestStruct { a: 5, b: "hello".to_string() }; let a_data = a.serialize().to_json(); println!("Our Test Struct as JSON: {a_data}"); let b = TestStruct::deserialize( generated_visitor_for!(TestStruct)::from_json(a_data)); } ``` -------------------------------- ### Rust Struct Initialization with Boilerplate for Docs Source: https://github.com/rust-unofficial/patterns/blob/main/src/idioms/rustdoc-init.md Demonstrates a common scenario in Rust documentation where a struct requires significant boilerplate code for initialization in each example. This can lead to repetitive and verbose documentation examples. ```rust struct Connection { name: String, stream: TcpStream, } impl Connection { /// Sends a request over the connection. /// /// # Example /// ```no_run /// # // Boilerplate are required to get an example working. /// # let stream = TcpStream::connect("127.0.0.1:34254"); /// # let connection = Connection { name: "foo".to_owned(), stream }; /// # let request = Request::new("RequestId", RequestType::Get, "payload"); /// let response = connection.send_request(request); /// assert!(response.is_ok()); /// ``` fn send_request(&self, request: Request) -> Result { // ... } /// Oh no, all that boilerplate needs to be repeated here! fn check_status(&self) -> Status { // ... } } ``` -------------------------------- ### Install and Use markdownlint-CLI for Markdown Linting Source: https://github.com/rust-unofficial/patterns/blob/main/CONTRIBUTING.md Instructions for installing and using the markdownlint-CLI tool to check and automatically fix Markdown files. This helps ensure consistency and compliance with style guidelines before submitting changes. ```shell npm install -g markdownlint-cli # Check all markdown files (unix): markdownlint "**/*.md" # Check all markdown files (windows): markdownlint **/*.md # Automatically fix basic errors (unix): markdownlint -f "**/*.md" # Automatically fix basic errors (windows): markdownlint -f **/*.md ``` -------------------------------- ### Rust Pattern Example Source: https://github.com/rust-unofficial/patterns/blob/main/template.md Demonstrates a specific programming pattern in Rust. This example is intended to be runnable and well-commented. If the example is not runnable, it should be marked with `ignore`. ```rust // An example of the pattern in action, should be mostly code, // liberally commented. ``` ```rust // A non-runnable example of the pattern in action, should be mostly code, // liberally commented. ``` -------------------------------- ### Rust Struct Initialization with Helper Function for Docs Source: https://github.com/rust-unofficial/patterns/blob/main/src/idioms/rustdoc-init.md Presents a pattern in Rust documentation where a helper function is used to wrap complex struct initialization, making documentation examples more concise and avoiding repetition. This pattern is particularly useful for `no_run` examples. ```rust struct Connection { name: String, stream: TcpStream, } impl Connection { /// Sends a request over the connection. /// /// # Example /// ``` /// # fn call_send(connection: Connection, request: Request) { /// let response = connection.send_request(request); /// assert!(response.is_ok()); /// # } /// ``` fn send_request(&self, request: Request) -> Result { // ... } } ``` -------------------------------- ### Build and Test Rust Patterns Book Locally Source: https://github.com/rust-unofficial/patterns/blob/main/CONTRIBUTING.md Commands to build the book locally and test code examples. This ensures that the book compiles correctly and that all embedded code snippets are valid before creating a pull request. ```shell mdbook build mdbook test ``` -------------------------------- ### Build Rust Design Patterns Book Source: https://github.com/rust-unofficial/patterns/blob/main/README.md Commands to build the Rust Design Patterns book locally. 'mdbook build' creates static HTML files, while 'mdbook serve' starts a local web server for live preview. ```sh mdbook build ``` ```sh mdbook serve ``` -------------------------------- ### Rust Implementation of FromStr and ToString for a Struct Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/optics.md Provides an example of implementing the `FromStr` and `ToString` traits for a custom `TestStruct`. This illustrates how to manually define serialization and deserialization logic, highlighting the need for a more standardized approach for complex scenarios. ```rust use anyhow; use std::str::FromStr; struct TestStruct { a: usize, b: String, } impl FromStr for TestStruct { type Err = anyhow::Error; fn from_str(s: &str) -> Result { todo!() } } impl ToString for TestStruct { fn to_string(&self) -> String { todo!() } } fn main() { let a = TestStruct { a: 5, b: "hello".to_string(), }; println!("Our Test Struct as JSON: {}", a.to_string()); } ``` -------------------------------- ### Concatenate strings using `format!` in Rust Source: https://github.com/rust-unofficial/patterns/blob/main/src/idioms/concat-format.md This example shows how to use the `format!` macro in Rust to create a formatted string by embedding a variable. It contrasts this with a commented-out manual string construction approach. ```rust fn say_hello(name: &str) -> String { // We could construct the result string manually. // let mut result = "Hello ".to_owned(); // result.push_str(name); // result.push('!'); // result // But using format! is better. format!("Hello {name}!") } ``` -------------------------------- ### Build with All Warnings Denied via RUSTFLAGS Source: https://github.com/rust-unofficial/patterns/blob/main/src/anti_patterns/deny-warnings.md This command-line example shows how to configure Cargo to build with all warnings treated as errors without modifying the source code. This is useful for CI environments or for developers who want to enforce linting rules externally. ```bash RUSTFLAGS="-D warnings" cargo build ``` -------------------------------- ### Compile-Time Error Example with Incorrect Type (Rust) Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/generics-type-classes.md This Rust code demonstrates how the generic type solution prevents incorrect usage. Attempting to call `mount_point()` on a `FileDownloadRequest` results in a compile-time error because that method is only implemented for `FileDownloadRequest`. ```rust fn main() { let mut socket = crate::bootp::listen()?; while let Some(request) = socket.next_request()? { match request.mount_point().as_ref() { "/secure" => socket.send("Access denied"), _ => {} // continue on... } // Rest of the code here } } ``` -------------------------------- ### DBM API Definition (C) Source: https://github.com/rust-unofficial/patterns/blob/main/src/patterns/ffi/export.md This C code defines the DBM (Database Manager) API, which serves as an example of an object-based API. It includes structures for opaque database handles (DBM) and transparent data elements (datum), along with functions for database operations. ```c struct DBM; typedef struct { void *dptr, size_t dsize } datum; int dbm_clearerr(DBM *); void dbm_close(DBM *); int dbm_delete(DBM *, datum); int dbm_error(DBM *); datum dbm_fetch(DBM *, datum); datum dbm_firstkey(DBM *); datum dbm_nextkey(DBM *); DBM *dbm_open(const char *, int, mode_t); int dbm_store(DBM *, datum, datum, int); ``` -------------------------------- ### Strategy Pattern in Rust Source: https://context7.com/rust-unofficial/patterns/llms.txt The Strategy pattern enables runtime selection of algorithms by defining a family of algorithms and making them interchangeable. This example uses traits and closures to implement different formatting strategies for generating reports based on data stored in a HashMap. ```rust use std::collections::HashMap; type Data = HashMap; // Strategy trait trait Formatter { fn format(&self, data: &Data, buf: &mut String); } struct Report; impl Report { fn generate(formatter: T, data: &Data) -> String { let mut output = String::new(); formatter.format(data, &mut output); output } } // Concrete strategies struct TextFormatter; impl Formatter for TextFormatter { fn format(&self, data: &Data, buf: &mut String) { for (k, v) in data { buf.push_str(&format!("{}: {}\n", k, v)); } } } struct JsonFormatter; impl Formatter for JsonFormatter { fn format(&self, data: &Data, buf: &mut String) { buf.push_str("{\n"); let entries: Vec<_> = data.iter() .map(|(k, v)| format!(" \"{}\": {}", k, v)) .collect(); buf.push_str(&entries.join(",\n")); buf.push_str("\n}"); } } fn main() { let mut data = HashMap::new(); data.insert("users".to_string(), 100); data.insert("posts".to_string(), 250); // Use different strategies at runtime let text_report = Report::generate(TextFormatter, &data); println!("Text Report:\n{}", text_report); let json_report = Report::generate(JsonFormatter, &data); println!("JSON Report:\n{}", json_report); // Strategy with closures (alternative approach) let custom_format = |data: &Data| -> String { data.iter() .map(|(k, v)| format!("[{}={}]", k, v)) .collect::>() .join(" ") }; println!("Custom: {}", custom_format(&data)); } ``` -------------------------------- ### Rust Visitor Trait Example Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/optics.md Defines the `Visitor` trait in Rust, used in conjunction with `Deserializer`. It specifies methods for visiting different data types and returning a `Value`. The trait involves associated types and error handling, contributing to the complexity of deserialization APIs. ```rust pub trait Visitor<'de>: Sized { type Value; fn visit_bool(self, v: bool) -> Result where E: Error; fn visit_u64(self, v: u64) -> Result where E: Error; fn visit_str(self, v: &str) -> Result where E: Error; // remainder omitted } ``` -------------------------------- ### Strategy Pattern with Option's map Method in Rust Source: https://github.com/rust-unofficial/patterns/blob/main/src/patterns/behavioural/strategy.md This example demonstrates how Rust's `Option::map` method inherently uses the Strategy pattern. The `map` method takes a closure (the strategy) and applies it to the contained value if the `Option` is `Some`. The code shows applying different length and byte extraction strategies to an `Option<&str>`. ```rust fn main() { let val = Some("Rust"); let len_strategy = |s: &str| s.len(); assert_eq!(4, val.map(len_strategy).unwrap()); let first_byte_strategy = |s: &str| s.bytes().next().unwrap(); assert_eq!(82, val.map(first_byte_strategy).unwrap()); } ``` -------------------------------- ### Swap Enum Variants using mem::take (Rust) Source: https://github.com/rust-unofficial/patterns/blob/main/src/idioms/mem-replace.md This example shows how to swap between `MultiVariateEnum::A` and `MultiVariateEnum::B` variants, and also between `C` and `D`, using `mem::take` to move the `name` String. This avoids cloning the String when switching between A and B. ```rust use std::mem; enum MultiVariateEnum { A { name: String }, B { name: String }, C, D, } fn swizzle(e: &mut MultiVariateEnum) { use MultiVariateEnum::*; *e = match e { // Ownership rules do not allow taking `name` by value, but we cannot // take the value out of a mutable reference, unless we replace it: A { name } => B { name: mem::take(name), }, B { name } => A { name: mem::take(name), }, C => D, D => C, } } ``` -------------------------------- ### Rust Fold Pattern Example: AST Transformation Source: https://github.com/rust-unofficial/patterns/blob/main/src/patterns/creational/fold.md Demonstrates the Fold pattern in Rust using an Abstract Syntax Tree (AST). It defines a `Folder` trait with methods to traverse and transform AST nodes, and a concrete `Renamer` implementation to change all names to 'foo'. This example highlights how the pattern separates traversal from node operations. ```rust mod ast { pub enum Stmt { Expr(Box), Let(Box, Box), } pub struct Name { value: String, } pub enum Expr { IntLit(i64), Add(Box, Box), Sub(Box, Box), } } mod fold { use ast::*; pub trait Folder { fn fold_name(&mut self, n: Box) -> Box { n } fn fold_stmt(&mut self, s: Box) -> Box { match *s { Stmt::Expr(e) => Box::new(Stmt::Expr(self.fold_expr(e))), Stmt::Let(n, e) => Box::new(Stmt::Let(self.fold_name(n), self.fold_expr(e))), } } fn fold_expr(&mut self, e: Box) -> Box { e } } } use fold::*; use ast::*; struct Renamer; impl Folder for Renamer { fn fold_name(&mut self, n: Box) -> Box { Box::new(Name { value: "foo".to_owned() }) } } ``` -------------------------------- ### Java Inheritance Example Source: https://github.com/rust-unofficial/patterns/blob/main/src/anti_patterns/deref.md This Java code snippet illustrates a typical inheritance pattern found in object-oriented languages, where class `Bar` extends class `Foo` and inherits its methods. ```java class Foo { void m() { ... } } class Bar extends Foo {} public static void main(String[] args) { Bar b = new Bar(); b.m(); } ``` -------------------------------- ### Initial Struct Design for File Download Requests (Rust) Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/generics-type-classes.md This initial Rust struct design uses an enum to handle different authentication types for file download requests. It lacks compile-time safety for protocol-specific metadata, requiring runtime checks. ```rust enum AuthInfo { Nfs(crate::nfs::AuthInfo), Bootp(crate::bootp::AuthInfo), } struct FileDownloadRequest { file_name: PathBuf, authentication: AuthInfo, } ``` -------------------------------- ### For Loop Iteration over Option in Rust Source: https://github.com/rust-unofficial/patterns/blob/main/src/idioms/option-iter.md Shows how to directly iterate over an Option using a for loop. This is functionally similar to using 'if let Some(..)' but is generally less preferred for clarity. ```rust let my_option = Some(5); for value in my_option { println!("The value is: {}", value); } // This is equivalent to: // if let Some(value) = my_option { // println!("The value is: {}", value); // } ``` -------------------------------- ### Adding Protocol-Specific Metadata (Rust) Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/generics-type-classes.md This Rust code snippet shows an updated struct design that includes protocol-specific fields like `mount_point` for NFS requests. It highlights the need for runtime checks when accessing this metadata. ```rust struct FileDownloadRequest { file_name: PathBuf, authentication: AuthInfo, mount_point: Option, } impl FileDownloadRequest { // ... other methods ... /// Gets an NFS mount point if this is an NFS request. Otherwise, /// return None. pub fn mount_point(&self) -> Option<&Path> { self.mount_point.as_ref() } } ``` -------------------------------- ### Rust Newtype Pattern for Custom Display Implementation Source: https://github.com/rust-unofficial/patterns/blob/main/src/patterns/behavioural/newtype.md Demonstrates the Newtype pattern in Rust to create a custom Display implementation for a String, enhancing type safety and encapsulation. This example shows how to wrap a String in a `Password` struct to override its default display behavior. ```rust use std::fmt::Display; // Create Newtype Password to override the Display trait for String struct Password(String); impl Display for Password { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "****************") } } fn main() { let unsecured_password: String = "ThisIsMyPassword".to_string(); let secured_password: Password = Password(unsecured_password.clone()); println!("unsecured_password: {unsecured_password}"); println!("secured_password: {secured_password}"); } ``` -------------------------------- ### Rust Schema Migrations with Fn Trait Objects Source: https://github.com/rust-unofficial/patterns/blob/main/src/patterns/behavioural/command.md Implements a schema migration system in Rust using `Fn` trait objects. It defines a `Schema` struct that holds vectors of functions (or closures) for executing and rolling back migrations. This allows for dynamic dispatch of migration logic. ```rust type Migration<'a> = Box &'a str>; struct Schema<'a> { executes: Vec>, rollbacks: Vec>, } impl<'a> Schema<'a> { fn new() -> Self { Self { executes: vec![], rollbacks: vec![], } } fn add_migration(&mut self, execute: E, rollback: R) where E: Fn() -> &'a str + 'static, R: Fn() -> &'a str + 'static, { self.executes.push(Box::new(execute)); self.rollbacks.push(Box::new(rollback)); } fn execute(&self) -> Vec<&str> { self.executes.iter().map(|cmd| cmd()).collect() } fn rollback(&self) -> Vec<&str> { self.rollbacks.iter().rev().map(|cmd| cmd()).collect() } } fn add_field() -> &'static str { "add field" } fn remove_field() -> &'static str { "remove field" } fn main() { let mut schema = Schema::new(); schema.add_migration(|| "create table", || "drop table"); schema.add_migration(add_field, remove_field); assert_eq!(vec!["create table", "add field"], schema.execute()); assert_eq!(vec!["remove field", "drop table"], schema.rollback()); } ``` -------------------------------- ### Rust Traits for String Conversion (FromStr, ToString) Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/optics.md Demonstrates Rust's standard library traits `FromStr` and `ToString` for converting between string slices and other types. These traits are fundamental for basic serialization and deserialization but lack specific format indication and can be cumbersome for complex types. ```rust pub trait FromStr: Sized { type Err; fn from_str(s: &str) -> Result; } pub trait ToString { fn to_string(&self) -> String; } ``` -------------------------------- ### Rust: Clone variable to satisfy borrow checker Source: https://github.com/rust-unofficial/patterns/blob/main/src/anti_patterns/borrow_clone.md Demonstrates how cloning a variable can resolve borrow checker conflicts by creating a separate copy, thus avoiding borrowing issues. This example shows a mutable borrow being created after cloning the original variable. ```rust let mut x = 5; let y = &mut (x.clone()); println!("{x}"); *y += 1; ``` -------------------------------- ### Imperative Summation in Rust Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/paradigms.md Demonstrates an imperative approach to summing numbers from 1 to 10 in Rust. This method explicitly details each step of the computation, including variable initialization and loop iteration. It requires mutable state and a loop construct. ```rust let mut sum = 0; for i in 1..11 { sum += i; } println!("{sum}"); ``` -------------------------------- ### Rust Deserializer Trait Example Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/optics.md Illustrates the `Deserializer` trait in Rust, commonly used in data parsing libraries. It defines methods for deserializing various data types, taking a generic `Visitor` as an argument. This pattern is complex due to associated types and type erasure. ```rust pub trait Deserializer<'de>: Sized { type Error: Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>; fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>; // remainder omitted } ``` -------------------------------- ### Implement Strategy Pattern with Closures in Rust Source: https://github.com/rust-unofficial/patterns/blob/main/src/patterns/behavioural/strategy.md This snippet shows how to implement the Strategy pattern in Rust using closures. It defines an `Adder` struct with a generic `add` method that accepts a closure `f` to perform the addition logic. The `main` function demonstrates using different closures for arithmetic, boolean, and custom addition strategies. ```rust struct Adder; impl Adder { pub fn add(x: u8, y: u8, f: F) -> u8 where F: Fn(u8, u8) -> u8, { f(x, y) } } fn main() { let arith_adder = |x, y| x + y; let bool_adder = |x, y| { if x == 1 || y == 1 { 1 } else { 0 } }; let custom_adder = |x, y| 2 * x + y; assert_eq!(9, Adder::add(4, 5, arith_adder)); assert_eq!(0, Adder::add(0, 0, bool_adder)); assert_eq!(5, Adder::add(1, 3, custom_adder)); } ``` -------------------------------- ### RAII Guards Pattern in Rust Source: https://context7.com/rust-unofficial/patterns/llms.txt The RAII (Resource Acquisition Is Initialization) pattern uses guard objects to manage resource lifecycles, ensuring proper acquisition and release. This example demonstrates a `Mutex` and `MutexGuard` to manage a lock, ensuring the lock is released when the guard goes out of scope. ```rust use std::ops::Deref; struct Mutex { data: T, locked: std::cell::Cell, } struct MutexGuard<'a, T> { mutex: &'a Mutex, } impl Mutex { pub fn new(data: T) -> Self { Mutex { data, locked: std::cell::Cell::new(false), } } pub fn lock(&self) -> MutexGuard { self.locked.set(true); println!("Lock acquired"); MutexGuard { mutex: self } } } // Guard automatically releases lock when dropped impl<'a, T> Drop for MutexGuard<'a, T> { fn drop(&mut self) { self.mutex.locked.set(false); println!("Lock released"); } } // Deref allows transparent access to inner data impl<'a, T> Deref for MutexGuard<'a, T> { type Target = T; fn deref(&self) -> &T { &self.mutex.data } } fn main() { let mutex = Mutex::new(vec![1, 2, 3]); { let guard = mutex.lock(); // Output: Lock acquired println!("Data length: {}", guard.len()); // Access via Deref // guard is dropped here } // Output: Lock released println!("Outside scope - lock is released"); } ``` -------------------------------- ### Rust Unsafe MySet Store Function Source: https://github.com/rust-unofficial/patterns/blob/main/src/patterns/ffi/wrappers.md An example of an unsafe Rust function 'myset_store' that manipulates a 'MySetWrapper'. This function demonstrates a common pitfall where mutable access to the underlying 'MySet' violates Rust's aliasing rules if an iterator is active, leading to undefined behavior. ```rust pub mod unsafe_module { // other module content pub fn myset_store(myset: *mut MySetWrapper, key: datum, value: datum) -> libc::c_int { // DO NOT USE THIS CODE. IT IS UNSAFE TO DEMONSTRATE A PROBLEM. let myset: &mut MySet = unsafe { // SAFETY: whoops, UB occurs in here! &mut (*myset).myset }; /* ...check and cast key and value data... */ match myset.store(casted_key, casted_value) { Ok(_) => 0, Err(e) => e.into(), } } } ``` -------------------------------- ### Rust Struct with Serde Derive and Visitor Generation Source: https://github.com/rust-unofficial/patterns/blob/main/src/functional/optics.md Illustrates using Rust's derive macros (`#[derive(Default, Serde)]`) to automatically implement the `Serde` trait for a `TestStruct`. It also shows a conceptual macro (`generate_visitor!`) for creating the associated visitor type, simplifying the serialization process. ```rust #[derive(Default, Serde)] // the "Serde" derive creates the trait impl block struct TestStruct { a: usize, b: String, } // user writes this macro to generate an associated visitor type generate_visitor!(TestStruct); ```