You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
patterns/po/messages.pot

7256 lines
208 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

msgid ""
msgstr ""
"Project-Id-Version: Rust Design Patterns\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: en\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: src\SUMMARY.md:3
msgid "Introduction"
msgstr ""
#: src\SUMMARY.md:4
msgid "Translations"
msgstr ""
#: src\SUMMARY.md:5
msgid "Idioms"
msgstr ""
#: src\SUMMARY.md:6
msgid "Use borrowed types for arguments"
msgstr ""
#: src\SUMMARY.md:7
msgid "Concatenating Strings with format!"
msgstr ""
#: src\SUMMARY.md:8
msgid "Constructor"
msgstr ""
#: src\SUMMARY.md:9
msgid "The Default Trait"
msgstr ""
#: src\SUMMARY.md:10
msgid "Collections Are Smart Pointers"
msgstr ""
#: src\SUMMARY.md:11
msgid "Finalisation in Destructors"
msgstr ""
#: src\SUMMARY.md:12
msgid "mem::{take(_), replace(_)}"
msgstr ""
#: src\SUMMARY.md:13
msgid "On-Stack Dynamic Dispatch"
msgstr ""
#: src\SUMMARY.md:14
#: src\SUMMARY.md:40
msgid "Foreign function interface (FFI)"
msgstr ""
#: src\SUMMARY.md:15
msgid "Idiomatic Errors"
msgstr ""
#: src\SUMMARY.md:16
msgid "Accepting Strings"
msgstr ""
#: src\SUMMARY.md:17
msgid "Passing Strings"
msgstr ""
#: src\SUMMARY.md:18
msgid "Iterating over an Option"
msgstr ""
#: src\SUMMARY.md:19
msgid "Pass Variables to Closure"
msgstr ""
#: src\SUMMARY.md:20
msgid "Privacy For Extensibility"
msgstr ""
#: src\SUMMARY.md:21
msgid "Easy doc initialization"
msgstr ""
#: src\SUMMARY.md:22
msgid "Temporary mutability"
msgstr ""
#: src\SUMMARY.md:23
msgid "Return consumed arg on error"
msgstr ""
#: src\SUMMARY.md:25
msgid "Design Patterns"
msgstr ""
#: src\SUMMARY.md:26
msgid "Behavioural"
msgstr ""
#: src\SUMMARY.md:27
msgid "Command"
msgstr ""
#: src\SUMMARY.md:28
msgid "Interpreter"
msgstr ""
#: src\SUMMARY.md:29
msgid "Newtype"
msgstr ""
#: src\SUMMARY.md:30
msgid "RAII Guards"
msgstr ""
#: src\SUMMARY.md:31
msgid "Strategy"
msgstr ""
#: src\SUMMARY.md:32
msgid "Visitor"
msgstr ""
#: src\SUMMARY.md:33
msgid "Creational"
msgstr ""
#: src\SUMMARY.md:34
msgid "Builder"
msgstr ""
#: src\SUMMARY.md:35
msgid "Fold"
msgstr ""
#: src\SUMMARY.md:36
msgid "Structural"
msgstr ""
#: src\SUMMARY.md:37
msgid "Compose Structs"
msgstr ""
#: src\SUMMARY.md:38
msgid "Prefer Small Crates"
msgstr ""
#: src\SUMMARY.md:39
msgid "Contain unsafety in small modules"
msgstr ""
#: src\SUMMARY.md:41
msgid "Object-Based APIs"
msgstr ""
#: src\SUMMARY.md:42
msgid "Type Consolidation into Wrappers"
msgstr ""
#: src\SUMMARY.md:44
msgid "Anti-patterns"
msgstr ""
#: src\SUMMARY.md:45
msgid "Clone to satisfy the borrow checker"
msgstr ""
#: src\SUMMARY.md:46
msgid "#[deny(warnings)]"
msgstr ""
#: src\SUMMARY.md:47
msgid "Deref Polymorphism"
msgstr ""
#: src\SUMMARY.md:49
msgid "Functional Programming"
msgstr ""
#: src\SUMMARY.md:50
msgid "Programming paradigms"
msgstr ""
#: src\SUMMARY.md:51
msgid "Generics as Type Classes"
msgstr ""
#: src\SUMMARY.md:52
msgid "Lenses and Prisms"
msgstr ""
#: src\SUMMARY.md:54
msgid "Additional Resources"
msgstr ""
#: src\SUMMARY.md:55
msgid "Design principles"
msgstr ""
#: src\intro.md:1
msgid "# Introduction"
msgstr ""
#: src\intro.md:3
msgid "## Participation"
msgstr ""
#: src\intro.md:5
msgid ""
"If you are interested in contributing to this book, check out the\n"
"[contribution "
"guidelines](https://github.com/rust-unofficial/patterns/blob/master/CONTRIBUTING.md)."
msgstr ""
#: src\intro.md:8
msgid "## Design patterns"
msgstr ""
#: src\intro.md:10
msgid ""
"In software development, we often come across problems that share\n"
"similarities regardless of the environment they appear in. Although the\n"
"implementation details are crucial to solve the task at hand, we may\n"
"abstract from these particularities to find the common practices that\n"
"are generically applicable."
msgstr ""
#: src\intro.md:16
msgid ""
"Design patterns are a collection of reusable and tested solutions to\n"
"recurring problems in engineering. They make our software more modular,\n"
"maintainable, and extensible. Moreover, these patterns provide a common\n"
"language for developers, making them an excellent tool for effective\n"
"communication when problem-solving in teams."
msgstr ""
#: src\intro.md:22
#: src\patterns/index.md:14
msgid "## Design patterns in Rust"
msgstr ""
#: src\intro.md:24
msgid ""
"Rust is not object-oriented, and the combination of all its "
"characteristics,\n"
"such as functional elements, a strong type system, and the borrow checker,\n"
"makes it unique.\n"
"Because of this, Rust design patterns vary with respect to other\n"
"traditional object-oriented programming languages.\n"
"That's why we decided to write this book. We hope you enjoy reading it!\n"
"The book is divided in three main chapters:"
msgstr ""
#: src\intro.md:32
msgid ""
"- [Idioms](./idioms/index.md): guidelines to follow when coding.\n"
" They are the social norms of the community.\n"
" You should break them only if you have a good reason for it.\n"
"- [Design patterns](./patterns/index.md): methods to solve common problems\n"
" when coding.\n"
"- [Anti-patterns](./anti_patterns/index.md): methods to solve common "
"problems\n"
" when coding.\n"
" However, while design patterns give us benefits,\n"
" anti-patterns create more problems."
msgstr ""
#: src\translations.md:1
msgid "# Translations"
msgstr ""
#: src\translations.md:3
msgid ""
"We are utilizing "
"[mdbook-i18n-helper](https://github.com/google/mdbook-i18n-helpers).\n"
"Please read up on how to _add_ and _update_ translations in [their "
"repository](https://github.com/google/mdbook-i18n-helpers#creating-and-updating-translations)"
msgstr ""
#: src\translations.md:6
msgid "## External translations"
msgstr ""
#: src\translations.md:8
msgid "- [简体中文](https://fomalhauthmj.github.io/patterns/)"
msgstr ""
#: src\translations.md:10
msgid ""
"If you want to add a translation, please open an issue in the\n"
"[main repository](https://github.com/rust-unofficial/patterns)."
msgstr ""
#: src\idioms/index.md:1
msgid "# Idioms"
msgstr ""
#: src\idioms/index.md:3
msgid ""
"[Idioms](https://en.wikipedia.org/wiki/Programming_idiom) are commonly used\n"
"styles, guidelines and patterns largely agreed upon by a community.\n"
"Writing idiomatic code allows other developers to understand better what is\n"
"happening."
msgstr ""
#: src\idioms/index.md:8
msgid ""
"After all, the computer only cares about the machine code that is generated\n"
"by the compiler.\n"
"Instead, the source code is mainly beneficial to the developer.\n"
"So, since we have this abstraction layer, why not make it more readable?"
msgstr ""
#: src\idioms/index.md:13
msgid ""
"Remember the [KISS "
"principle](https://en.wikipedia.org/wiki/KISS_principle):\n"
"\"Keep It Simple, Stupid\". It claims that \"most systems work best if they "
"are\n"
"kept simple rather than made complicated; therefore, simplicity should be a "
"key\n"
"goal in design, and unnecessary complexity should be avoided\"."
msgstr ""
#: src\idioms/index.md:18
msgid "> Code is there for humans, not computers, to understand."
msgstr ""
#: src\idioms/coercion-arguments.md:1
msgid "# Use borrowed types for arguments"
msgstr ""
#: src\idioms/coercion-arguments.md:3
#: src\idioms/concat-format.md:3
#: src\idioms/default.md:3
#: src\idioms/deref.md:3
#: src\idioms/dtor-finally.md:3
#: src\idioms/mem-replace.md:3
#: src\idioms/on-stack-dyn-dispatch.md:3
#: src\idioms/ffi/errors.md:3
#: src\idioms/ffi/accepting-strings.md:3
#: src\idioms/ffi/passing-strings.md:3
#: src\idioms/option-iter.md:3
#: src\idioms/pass-var-to-closure.md:3
#: src\idioms/priv-extend.md:3
#: src\idioms/temporary-mutability.md:3
#: src\idioms/return-consumed-arg-on-error.md:3
#: src\patterns/behavioural/command.md:3
#: src\patterns/behavioural/interpreter.md:3
#: src\patterns/behavioural/newtype.md:13
#: src\patterns/behavioural/RAII.md:3
#: src\patterns/behavioural/strategy.md:3
#: src\patterns/behavioural/visitor.md:3
#: src\patterns/creational/builder.md:3
#: src\patterns/creational/fold.md:3
#: src\patterns/structural/compose-structs.md:5
#: src\patterns/structural/small-crates.md:3
#: src\patterns/structural/unsafe-mods.md:3
#: src\patterns/ffi/export.md:3
#: src\patterns/ffi/wrappers.md:3
#: src\anti_patterns/borrow_clone.md:3
#: src\anti_patterns/deny-warnings.md:3
#: src\anti_patterns/deref.md:3
#: src\functional/generics-type-classes.md:3
msgid "## Description"
msgstr ""
#: src\idioms/coercion-arguments.md:5
msgid ""
"Using a target of a deref coercion can increase the flexibility of your "
"code\n"
"when you are deciding which argument type to use for a function argument.\n"
"In this way, the function will accept more input types."
msgstr ""
#: src\idioms/coercion-arguments.md:9
msgid ""
"This is not limited to slice-able or fat pointer types.\n"
"In fact, you should always prefer using the **borrowed type** over\n"
"**borrowing the owned type**.\n"
"Such as `&str` over `&String`, `&[T]` over `&Vec<T>`, or `&T` over `&Box<T>`."
msgstr ""
#: src\idioms/coercion-arguments.md:14
msgid ""
"Using borrowed types you can avoid layers of indirection for those "
"instances\n"
"where the owned type already provides a layer of indirection. For instance, "
"a\n"
"`String` has a layer of indirection, so a `&String` will have two layers of\n"
"indirection. We can avoid this by using `&str` instead, and letting "
"`&String`\n"
"coerce to a `&str` whenever the function is invoked."
msgstr ""
#: src\idioms/coercion-arguments.md:20
#: src\idioms/concat-format.md:10
#: src\idioms/default.md:20
#: src\idioms/deref.md:9
#: src\idioms/dtor-finally.md:9
#: src\idioms/mem-replace.md:11
#: src\idioms/on-stack-dyn-dispatch.md:10
#: src\idioms/pass-var-to-closure.md:12
#: src\idioms/priv-extend.md:18
#: src\idioms/temporary-mutability.md:12
#: src\idioms/return-consumed-arg-on-error.md:8
#: src\patterns/behavioural/command.md:18
#: src\patterns/behavioural/newtype.md:18
#: src\patterns/behavioural/RAII.md:11
#: src\patterns/behavioural/strategy.md:28
#: src\patterns/behavioural/visitor.md:13
#: src\patterns/creational/builder.md:7
#: src\patterns/creational/fold.md:12
#: src\patterns/structural/compose-structs.md:17
#: src\anti_patterns/borrow_clone.md:11
#: src\anti_patterns/deny-warnings.md:8
#: src\anti_patterns/deref.md:8
#: src\functional/generics-type-classes.md:38
msgid "## Example"
msgstr ""
#: src\idioms/coercion-arguments.md:22
msgid ""
"For this example, we will illustrate some differences for using `&String` as "
"a\n"
"function argument versus using a `&str`, but the ideas apply as well to "
"using\n"
"`&Vec<T>` versus using a `&[T]` or using a `&Box<T>` versus a `&T`."
msgstr ""
#: src\idioms/coercion-arguments.md:26
msgid ""
"Consider an example where we wish to determine if a word contains three\n"
"consecutive vowels. We don't need to own the string to determine this, so "
"we\n"
"will take a reference."
msgstr ""
#: src\idioms/coercion-arguments.md:30
msgid "The code might look something like this:"
msgstr ""
#: src\idioms/coercion-arguments.md:32
msgid ""
"```rust\n"
"fn three_vowels(word: &String) -> bool {\n"
" let mut vowel_count = 0;\n"
" for c in word.chars() {\n"
" match c {\n"
" 'a' | 'e' | 'i' | 'o' | 'u' => {\n"
" vowel_count += 1;\n"
" if vowel_count >= 3 {\n"
" return true\n"
" }\n"
" }\n"
" _ => vowel_count = 0\n"
" }\n"
" }\n"
" false\n"
"}\n"
"\n"
"fn main() {\n"
" let ferris = \"Ferris\".to_string();\n"
" let curious = \"Curious\".to_string();\n"
" println!(\"{}: {}\", ferris, three_vowels(&ferris));\n"
" println!(\"{}: {}\", curious, three_vowels(&curious));\n"
"\n"
" // This works fine, but the following two lines would fail:\n"
" // println!(\"Ferris: {}\", three_vowels(\"Ferris\"));\n"
" // println!(\"Curious: {}\", three_vowels(\"Curious\"));\n"
"\n"
"}\n"
"```"
msgstr ""
#: src\idioms/coercion-arguments.md:62
msgid ""
"This works fine because we are passing a `&String` type as a parameter.\n"
"If we remove the comments on the last two lines, the example will fail. "
"This\n"
"is because a `&str` type will not coerce to a `&String` type. We can fix "
"this\n"
"by simply modifying the type for our argument."
msgstr ""
#: src\idioms/coercion-arguments.md:67
msgid "For instance, if we change our function declaration to:"
msgstr ""
#: src\idioms/coercion-arguments.md:69
msgid ""
"```rust, ignore\n"
"fn three_vowels(word: &str) -> bool {\n"
"```"
msgstr ""
#: src\idioms/coercion-arguments.md:73
msgid "then both versions will compile and print the same output."
msgstr ""
#: src\idioms/coercion-arguments.md:75
msgid ""
"```bash\n"
"Ferris: false\n"
"Curious: true\n"
"```"
msgstr ""
#: src\idioms/coercion-arguments.md:80
msgid ""
"But wait, that's not all! There is more to this story.\n"
"It's likely that you may say to yourself: that doesn't matter, I will never "
"be\n"
"using a `&'static str` as an input anyways (as we did when we used "
"`\"Ferris\"`).\n"
"Even ignoring this special example, you may still find that using `&str` "
"will\n"
"give you more flexibility than using a `&String`."
msgstr ""
#: src\idioms/coercion-arguments.md:86
msgid ""
"Let's now take an example where someone gives us a sentence, and we want to\n"
"determine if any of the words in the sentence contain three consecutive "
"vowels.\n"
"We probably should make use of the function we have already defined and "
"simply\n"
"feed in each word from the sentence."
msgstr ""
#: src\idioms/coercion-arguments.md:91
msgid "An example of this could look like this:"
msgstr ""
#: src\idioms/coercion-arguments.md:93
msgid ""
"```rust\n"
"fn three_vowels(word: &str) -> bool {\n"
" let mut vowel_count = 0;\n"
" for c in word.chars() {\n"
" match c {\n"
" 'a' | 'e' | 'i' | 'o' | 'u' => {\n"
" vowel_count += 1;\n"
" if vowel_count >= 3 {\n"
" return true\n"
" }\n"
" }\n"
" _ => vowel_count = 0\n"
" }\n"
" }\n"
" false\n"
"}\n"
"\n"
"fn main() {\n"
" let sentence_string =\n"
" \"Once upon a time, there was a friendly curious crab named "
"Ferris\".to_string();\n"
" for word in sentence_string.split(' ') {\n"
" if three_vowels(word) {\n"
" println!(\"{} has three consecutive vowels!\", word);\n"
" }\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/coercion-arguments.md:121
msgid ""
"Running this example using our function declared with an argument type "
"`&str`\n"
"will yield"
msgstr ""
#: src\idioms/coercion-arguments.md:124
msgid ""
"```bash\n"
"curious has three consecutive vowels!\n"
"```"
msgstr ""
#: src\idioms/coercion-arguments.md:128
msgid ""
"However, this example will not run when our function is declared with an\n"
"argument type `&String`. This is because string slices are a `&str` and not "
"a\n"
"`&String` which would require an allocation to be converted to `&String` "
"which\n"
"is not implicit, whereas converting from `String` to `&str` is cheap and "
"implicit."
msgstr ""
#: src\idioms/coercion-arguments.md:133
#: src\idioms/default.md:58
#: src\idioms/deref.md:76
#: src\idioms/dtor-finally.md:88
#: src\idioms/mem-replace.md:108
#: src\idioms/on-stack-dyn-dispatch.md:83
#: src\idioms/option-iter.md:46
#: src\idioms/priv-extend.md:120
#: src\patterns/behavioural/command.md:218
#: src\patterns/behavioural/interpreter.md:142
#: src\patterns/behavioural/newtype.md:104
#: src\patterns/behavioural/RAII.md:111
#: src\patterns/behavioural/strategy.md:174
#: src\patterns/behavioural/visitor.md:106
#: src\patterns/creational/builder.md:108
#: src\patterns/creational/fold.md:109
#: src\patterns/structural/small-crates.md:45
#: src\patterns/structural/unsafe-mods.md:32
#: src\anti_patterns/borrow_clone.md:68
#: src\anti_patterns/deny-warnings.md:96
#: src\anti_patterns/deref.md:123
#: src\functional/generics-type-classes.md:237
msgid "## See also"
msgstr ""
#: src\idioms/coercion-arguments.md:135
msgid ""
"- [Rust Language Reference on Type "
"Coercions](https://doc.rust-lang.org/reference/type-coercions.html)\n"
"- For more discussion on how to handle `String` and `&str` see\n"
" [this blog series "
"(2015)](https://web.archive.org/web/20201112023149/https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html)\n"
" by Herman J. Radtke III"
msgstr ""
#: src\idioms/concat-format.md:1
msgid "# Concatenating strings with `format!`"
msgstr ""
#: src\idioms/concat-format.md:5
msgid ""
"It is possible to build up strings using the `push` and `push_str` methods "
"on a\n"
"mutable `String`, or using its `+` operator. However, it is often more\n"
"convenient to use `format!`, especially where there is a mix of literal and\n"
"non-literal strings."
msgstr ""
#: src\idioms/concat-format.md:12
msgid ""
"```rust\n"
"fn say_hello(name: &str) -> String {\n"
" // We could construct the result string manually.\n"
" // let mut result = \"Hello \".to_owned();\n"
" // result.push_str(name);\n"
" // result.push('!');\n"
" // result\n"
"\n"
" // But using format! is better.\n"
" format!(\"Hello {}!\", name)\n"
"}\n"
"```"
msgstr ""
#: src\idioms/concat-format.md:25
#: src\idioms/deref.md:43
#: src\idioms/dtor-finally.md:42
#: src\idioms/mem-replace.md:83
#: src\idioms/on-stack-dyn-dispatch.md:48
#: src\idioms/ffi/errors.md:131
#: src\idioms/ffi/accepting-strings.md:68
#: src\idioms/ffi/passing-strings.md:68
#: src\idioms/pass-var-to-closure.md:48
#: src\idioms/temporary-mutability.md:38
#: src\idioms/return-consumed-arg-on-error.md:55
#: src\patterns/behavioural/newtype.md:66
#: src\patterns/behavioural/RAII.md:78
#: src\patterns/behavioural/strategy.md:96
#: src\patterns/creational/builder.md:68
#: src\patterns/structural/compose-structs.md:75
#: src\patterns/structural/small-crates.md:12
#: src\patterns/structural/unsafe-mods.md:11
#: src\patterns/ffi/export.md:111
#: src\patterns/ffi/wrappers.md:63
#: src\anti_patterns/deny-warnings.md:16
#: src\anti_patterns/deref.md:69
#: src\functional/generics-type-classes.md:210
msgid "## Advantages"
msgstr ""
#: src\idioms/concat-format.md:27
msgid ""
"Using `format!` is usually the most succinct and readable way to combine "
"strings."
msgstr ""
#: src\idioms/concat-format.md:29
#: src\idioms/deref.md:50
#: src\idioms/dtor-finally.md:47
#: src\idioms/mem-replace.md:87
#: src\idioms/on-stack-dyn-dispatch.md:54
#: src\idioms/ffi/errors.md:136
#: src\idioms/ffi/accepting-strings.md:141
#: src\idioms/ffi/passing-strings.md:103
#: src\idioms/pass-var-to-closure.md:57
#: src\idioms/temporary-mutability.md:42
#: src\idioms/return-consumed-arg-on-error.md:59
#: src\patterns/behavioural/newtype.md:77
#: src\patterns/behavioural/strategy.md:104
#: src\patterns/creational/builder.md:76
#: src\patterns/structural/compose-structs.md:81
#: src\patterns/structural/small-crates.md:22
#: src\patterns/structural/unsafe-mods.md:17
#: src\patterns/ffi/export.md:234
#: src\patterns/ffi/wrappers.md:69
#: src\anti_patterns/deref.md:81
#: src\functional/generics-type-classes.md:221
msgid "## Disadvantages"
msgstr ""
#: src\idioms/concat-format.md:31
msgid ""
"It is usually not the most efficient way to combine strings - a series of "
"`push`\n"
"operations on a mutable string is usually the most efficient (especially if "
"the\n"
"string has been pre-allocated to the expected size)."
msgstr ""
#: src\idioms/ctor.md:1
msgid "# Constructors\r"
msgstr ""
#: src\idioms/ctor.md:3
#: src\idioms/rustdoc-init.md:3
msgid "## Description\r"
msgstr ""
#: src\idioms/ctor.md:5
msgid ""
"Rust does not have constructors as a language construct. Instead, the\r\n"
"convention is to use an [associated function][associated function] `new` to "
"create an object:"
msgstr ""
#: src\idioms/ctor.md:8
msgid ""
"````rust\r\n"
"/// Time in seconds.\r\n"
"///\r\n"
"/// # Example\r\n"
"///\r\n"
"/// ```\r\n"
"/// let s = Second::new(42);\r\n"
"/// assert_eq!(42, s.value());\r\n"
"/// ```\r\n"
"pub struct Second {\r\n"
" value: u64\r\n"
"}\r\n"
"\r\n"
"impl Second {\r\n"
" // Constructs a new instance of [`Second`].\r\n"
" // Note this is an associated function - no self.\r\n"
" pub fn new(value: u64) -> Self {\r\n"
" Self { value }\r\n"
" }\r\n"
"\r\n"
" /// Returns the value in seconds.\r\n"
" pub fn value(&self) -> u64 {\r\n"
" self.value\r\n"
" }\r\n"
"}\r\n"
"````"
msgstr ""
#: src\idioms/ctor.md:35
msgid "## Default Constructors\r"
msgstr ""
#: src\idioms/ctor.md:37
msgid ""
"Rust supports default constructors with the [`Default`][std-default] trait:"
msgstr ""
#: src\idioms/ctor.md:39
msgid ""
"````rust\r\n"
"/// Time in seconds.\r\n"
"///\r\n"
"/// # Example\r\n"
"///\r\n"
"/// ```\r\n"
"/// let s = Second::default();\r\n"
"/// assert_eq!(0, s.value());\r\n"
"/// ```\r\n"
"pub struct Second {\r\n"
" value: u64\r\n"
"}\r\n"
"\r\n"
"impl Second {\r\n"
" /// Returns the value in seconds.\r\n"
" pub fn value(&self) -> u64 {\r\n"
" self.value\r\n"
" }\r\n"
"}\r\n"
"\r\n"
"impl Default for Second {\r\n"
" fn default() -> Self {\r\n"
" Self { value: 0 }\r\n"
" }\r\n"
"}\r\n"
"````"
msgstr ""
#: src\idioms/ctor.md:66
msgid ""
"`Default` can also be derived if all types of all fields implement "
"`Default`,\r\n"
"like they do with `Second`:"
msgstr ""
#: src\idioms/ctor.md:69
msgid ""
"````rust\r\n"
"/// Time in seconds.\r\n"
"///\r\n"
"/// # Example\r\n"
"///\r\n"
"/// ```\r\n"
"/// let s = Second::default();\r\n"
"/// assert_eq!(0, s.value());\r\n"
"/// ```\r\n"
"#[derive(Default)]\r\n"
"pub struct Second {\r\n"
" value: u64\r\n"
"}\r\n"
"\r\n"
"impl Second {\r\n"
" /// Returns the value in seconds.\r\n"
" pub fn value(&self) -> u64 {\r\n"
" self.value\r\n"
" }\r\n"
"}\r\n"
"````"
msgstr ""
#: src\idioms/ctor.md:91
msgid ""
"**Note:** It is common and expected for types to implement both\r\n"
"`Default` and an empty `new` constructor. `new` is the constructor\r\n"
"convention in Rust, and users expect it to exist, so if it is\r\n"
"reasonable for the basic constructor to take no arguments, then it\r\n"
"should, even if it is functionally identical to default."
msgstr ""
#: src\idioms/ctor.md:97
msgid ""
"**Hint:** The advantage of implementing or deriving `Default` is that your "
"type\r\n"
"can now be used where a `Default` implementation is required, most "
"prominently,\r\n"
"any of the [`*or_default` functions in the standard library][std-or-default]."
msgstr ""
#: src\idioms/ctor.md:101
msgid "## See also\r"
msgstr ""
#: src\idioms/ctor.md:103
msgid ""
"- The [default idiom](default.md) for a more in-depth description of the\r\n"
" `Default` trait.\r\n"
"\r\n"
"- The [builder pattern](../patterns/creational/builder.md) for "
"constructing\r\n"
" objects where there are multiple configurations.\r\n"
"\r\n"
"- [API Guidelines/C-COMMON-TRAITS][API Guidelines/C-COMMON-TRAITS] for\r\n"
" implementing both, `Default` and `new`.\r\n"
"\r"
msgstr ""
#: src\idioms/default.md:1
msgid "# The `Default` Trait"
msgstr ""
#: src\idioms/default.md:5
msgid ""
"Many types in Rust have a [constructor]. However, this is _specific_ to the\n"
"type; Rust cannot abstract over \"everything that has a `new()` method\". "
"To\n"
"allow this, the [`Default`] trait was conceived, which can be used with\n"
"containers and other generic types (e.g. see "
"[`Option::unwrap_or_default()`]).\n"
"Notably, some containers already implement it where applicable."
msgstr ""
#: src\idioms/default.md:11
msgid ""
"Not only do one-element containers like `Cow`, `Box` or `Arc` implement\n"
"`Default` for contained `Default` types, one can automatically\n"
"`#[derive(Default)]` for structs whose fields all implement it, so the more\n"
"types implement `Default`, the more useful it becomes."
msgstr ""
#: src\idioms/default.md:16
msgid ""
"On the other hand, constructors can take multiple arguments, while the\n"
"`default()` method does not. There can even be multiple constructors with\n"
"different names, but there can only be one `Default` implementation per type."
msgstr ""
#: src\idioms/default.md:22
msgid ""
"```rust\n"
"use std::{path::PathBuf, time::Duration};\n"
"\n"
"// note that we can simply auto-derive Default here.\n"
"#[derive(Default, Debug, PartialEq)]\n"
"struct MyConfiguration {\n"
" // Option defaults to None\n"
" output: Option<PathBuf>,\n"
" // Vecs default to empty vector\n"
" search_path: Vec<PathBuf>,\n"
" // Duration defaults to zero time\n"
" timeout: Duration,\n"
" // bool defaults to false\n"
" check: bool,\n"
"}\n"
"\n"
"impl MyConfiguration {\n"
" // add setters here\n"
"}\n"
"\n"
"fn main() {\n"
" // construct a new instance with default values\n"
" let mut conf = MyConfiguration::default();\n"
" // do something with conf here\n"
" conf.check = true;\n"
" println!(\"conf = {:#?}\", conf);\n"
" \n"
" // partial initialization with default values, creates the same "
"instance\n"
" let conf1 = MyConfiguration {\n"
" check: true,\n"
" ..Default::default()\n"
" };\n"
" assert_eq!(conf, conf1);\n"
"}\n"
"```"
msgstr ""
#: src\idioms/default.md:60
msgid ""
"- The [constructor] idiom is another way to generate instances that may or "
"may\n"
" not be \"default\"\n"
"- The [`Default`] documentation (scroll down for the list of implementors)\n"
"- [`Option::unwrap_or_default()`]\n"
"- [`derive(new)`]"
msgstr ""
#: src\idioms/deref.md:1
msgid "# Collections are smart pointers"
msgstr ""
#: src\idioms/deref.md:5
msgid ""
"Use the [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)\n"
"trait to treat collections like smart pointers, offering owning\n"
"and borrowed views of data."
msgstr ""
#: src\idioms/deref.md:11
msgid ""
"```rust,ignore\n"
"use std::ops::Deref;\n"
"\n"
"struct Vec<T> {\n"
" data: RawVec<T>,\n"
" //..\n"
"}\n"
"\n"
"impl<T> Deref for Vec<T> {\n"
" type Target = [T];\n"
"\n"
" fn deref(&self) -> &[T] {\n"
" //..\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/deref.md:28
msgid ""
"A `Vec<T>` is an owning collection of `T`s, while a slice (`&[T]`) is a "
"borrowed\n"
"collection of `T`s. Implementing `Deref` for `Vec` allows implicit "
"dereferencing\n"
"from `&Vec<T>` to `&[T]` and includes the relationship in auto-derefencing\n"
"searches. Most methods you might expect to be implemented for `Vec`s are "
"instead\n"
"implemented for slices."
msgstr ""
#: src\idioms/deref.md:34
msgid "Also `String` and `&str` have a similar relation."
msgstr ""
#: src\idioms/deref.md:36
#: src\idioms/dtor-finally.md:32
#: src\idioms/mem-replace.md:57
#: src\idioms/on-stack-dyn-dispatch.md:37
#: src\idioms/ffi/accepting-strings.md:12
#: src\idioms/ffi/passing-strings.md:14
#: src\idioms/return-consumed-arg-on-error.md:43
#: src\patterns/behavioural/command.md:8
#: src\patterns/behavioural/interpreter.md:16
#: src\patterns/behavioural/newtype.md:56
#: src\patterns/behavioural/RAII.md:72
#: src\patterns/behavioural/strategy.md:19
#: src\patterns/behavioural/visitor.md:72
#: src\patterns/creational/builder.md:63
#: src\patterns/creational/fold.md:73
#: src\patterns/structural/compose-structs.md:71
#: src\patterns/ffi/export.md:15
#: src\anti_patterns/borrow_clone.md:30
msgid "## Motivation"
msgstr ""
#: src\idioms/deref.md:38
msgid ""
"Ownership and borrowing are key aspects of the Rust language. Data "
"structures\n"
"must account for these semantics properly to give a good user\n"
"experience. When implementing a data structure that owns its data, offering "
"a\n"
"borrowed view of that data allows for more flexible APIs."
msgstr ""
#: src\idioms/deref.md:45
msgid ""
"Most methods can be implemented only for the borrowed view, they are then\n"
"implicitly available for the owning view."
msgstr ""
#: src\idioms/deref.md:48
msgid "Gives clients a choice between borrowing or taking ownership of data."
msgstr ""
#: src\idioms/deref.md:52
msgid ""
"Methods and traits only available via dereferencing are not taken into "
"account\n"
"when bounds checking, so generic programming with data structures using "
"this\n"
"pattern can get complex (see the `Borrow` and `AsRef` traits, etc.)."
msgstr ""
#: src\idioms/deref.md:56
#: src\idioms/dtor-finally.md:61
#: src\idioms/mem-replace.md:97
#: src\idioms/on-stack-dyn-dispatch.md:68
#: src\idioms/priv-extend.md:85
#: src\patterns/behavioural/command.md:203
#: src\patterns/behavioural/interpreter.md:103
#: src\patterns/behavioural/newtype.md:85
#: src\patterns/behavioural/RAII.md:83
#: src\patterns/behavioural/strategy.md:110
#: src\patterns/behavioural/visitor.md:79
#: src\patterns/creational/builder.md:81
#: src\patterns/creational/fold.md:85
#: src\patterns/structural/compose-structs.md:89
#: src\anti_patterns/deref.md:102
msgid "## Discussion"
msgstr ""
#: src\idioms/deref.md:58
msgid ""
"Smart pointers and collections are analogous: a smart pointer points to a "
"single\n"
"object, whereas a collection points to many objects. From the point of view "
"of\n"
"the type system, there is little difference between the two. A collection "
"owns\n"
"its data if the only way to access each datum is via the collection and the\n"
"collection is responsible for deleting the data (even in cases of shared\n"
"ownership, some kind of borrowed view may be appropriate). If a collection "
"owns\n"
"its data, it is usually useful to provide a view of the data as borrowed so "
"that\n"
"it can be referenced multiple times."
msgstr ""
#: src\idioms/deref.md:67
msgid ""
"Most smart pointers (e.g., `Foo<T>`) implement `Deref<Target=T>`. However,\n"
"collections will usually dereference to a custom type. `[T]` and `str` have "
"some\n"
"language support, but in the general case, this is not necessary. `Foo<T>` "
"can\n"
"implement `Deref<Target=Bar<T>>` where `Bar` is a dynamically sized type "
"and\n"
"`&Bar<T>` is a borrowed view of the data in `Foo<T>`."
msgstr ""
#: src\idioms/deref.md:73
msgid ""
"Commonly, ordered collections will implement `Index` for `Range`s to "
"provide\n"
"slicing syntax. The target will be the borrowed view."
msgstr ""
#: src\idioms/deref.md:78
msgid ""
"- [Deref polymorphism anti-pattern](../anti_patterns/deref.md).\n"
"- [Documentation for `Deref` "
"trait](https://doc.rust-lang.org/std/ops/trait.Deref.html)."
msgstr ""
#: src\idioms/dtor-finally.md:1
msgid "# Finalisation in destructors"
msgstr ""
#: src\idioms/dtor-finally.md:5
msgid ""
"Rust does not provide the equivalent to `finally` blocks - code that will "
"be\n"
"executed no matter how a function is exited. Instead, an object's destructor "
"can\n"
"be used to run code that must be run before exit."
msgstr ""
#: src\idioms/dtor-finally.md:11
msgid ""
"```rust,ignore\n"
"fn bar() -> Result<(), ()> {\n"
" // These don't need to be defined inside the function.\n"
" struct Foo;\n"
"\n"
" // Implement a destructor for Foo.\n"
" impl Drop for Foo {\n"
" fn drop(&mut self) {\n"
" println!(\"exit\");\n"
" }\n"
" }\n"
"\n"
" // The dtor of _exit will run however the function `bar` is exited.\n"
" let _exit = Foo;\n"
" // Implicit return with `?` operator.\n"
" baz()?;\n"
" // Normal return.\n"
" Ok(())\n"
"}\n"
"```"
msgstr ""
#: src\idioms/dtor-finally.md:34
msgid ""
"If a function has multiple return points, then executing code on exit "
"becomes\n"
"difficult and repetitive (and thus bug-prone). This is especially the case "
"where\n"
"return is implicit due to a macro. A common case is the `?` operator which\n"
"returns if the result is an `Err`, but continues if it is `Ok`. `?` is used "
"as\n"
"an exception handling mechanism, but unlike Java (which has `finally`), "
"there is\n"
"no way to schedule code to run in both the normal and exceptional cases.\n"
"Panicking will also exit a function early."
msgstr ""
#: src\idioms/dtor-finally.md:44
msgid ""
"Code in destructors will (nearly) always be run - copes with panics, early\n"
"returns, etc."
msgstr ""
#: src\idioms/dtor-finally.md:49
msgid ""
"It is not guaranteed that destructors will run. For example, if there is an\n"
"infinite loop in a function or if running a function crashes before exit.\n"
"Destructors are also not run in the case of a panic in an already panicking\n"
"thread. Therefore, destructors cannot be relied on as finalizers where it "
"is\n"
"absolutely essential that finalisation happens."
msgstr ""
#: src\idioms/dtor-finally.md:55
msgid ""
"This pattern introduces some hard to notice, implicit code. Reading a "
"function\n"
"gives no clear indication of destructors to be run on exit. This can make\n"
"debugging tricky."
msgstr ""
#: src\idioms/dtor-finally.md:59
msgid ""
"Requiring an object and `Drop` impl just for finalisation is heavy on "
"boilerplate."
msgstr ""
#: src\idioms/dtor-finally.md:63
msgid ""
"There is some subtlety about how exactly to store the object used as a\n"
"finalizer. It must be kept alive until the end of the function and must then "
"be\n"
"destroyed. The object must always be a value or uniquely owned pointer "
"(e.g.,\n"
"`Box<Foo>`). If a shared pointer (such as `Rc`) is used, then the finalizer "
"can\n"
"be kept alive beyond the lifetime of the function. For similar reasons, the\n"
"finalizer should not be moved or returned."
msgstr ""
#: src\idioms/dtor-finally.md:70
msgid ""
"The finalizer must be assigned into a variable, otherwise it will be "
"destroyed\n"
"immediately, rather than when it goes out of scope. The variable name must "
"start\n"
"with `_` if the variable is only used as a finalizer, otherwise the "
"compiler\n"
"will warn that the finalizer is never used. However, do not call the "
"variable\n"
"`_` with no suffix - in that case it will be destroyed immediately."
msgstr ""
#: src\idioms/dtor-finally.md:76
msgid ""
"In Rust, destructors are run when an object goes out of scope. This happens\n"
"whether we reach the end of block, there is an early return, or the program\n"
"panics. When panicking, Rust unwinds the stack running destructors for each\n"
"object in each stack frame. So, destructors get called even if the panic "
"happens\n"
"in a function being called."
msgstr ""
#: src\idioms/dtor-finally.md:82
msgid ""
"If a destructor panics while unwinding, there is no good action to take, so "
"Rust\n"
"aborts the thread immediately, without running further destructors. This "
"means\n"
"that destructors are not absolutely guaranteed to run. It also means that "
"you\n"
"must take extra care in your destructors not to panic, since it could leave\n"
"resources in an unexpected state."
msgstr ""
#: src\idioms/dtor-finally.md:90
msgid "[RAII guards](../patterns/behavioural/RAII.md)."
msgstr ""
#: src\idioms/mem-replace.md:1
msgid "# `mem::{take(_), replace(_)}` to keep owned values in changed enums"
msgstr ""
#: src\idioms/mem-replace.md:5
msgid ""
"Say we have a `&mut MyEnum` which has (at least) two variants,\n"
"`A { name: String, x: u8 }` and `B { name: String }`. Now we want to change\n"
"`MyEnum::A` to a `B` if `x` is zero, while keeping `MyEnum::B` intact."
msgstr ""
#: src\idioms/mem-replace.md:9
msgid "We can do this without cloning the `name`."
msgstr ""
#: src\idioms/mem-replace.md:13
msgid ""
"```rust\n"
"use std::mem;\n"
"\n"
"enum MyEnum {\n"
" A { name: String, x: u8 },\n"
" B { name: String }\n"
"}\n"
"\n"
"fn a_to_b(e: &mut MyEnum) {\n"
" if let MyEnum::A { name, x: 0 } = e {\n"
" // this takes out our `name` and put in an empty String instead\n"
" // (note that empty strings don't allocate).\n"
" // Then, construct the new enum variant (which will\n"
" // be assigned to `*e`).\n"
" *e = MyEnum::B { name: mem::take(name) }\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/mem-replace.md:32
msgid "This also works with more variants:"
msgstr ""
#: src\idioms/mem-replace.md:34
msgid ""
"```rust\n"
"use std::mem;\n"
"\n"
"enum MultiVariateEnum {\n"
" A { name: String },\n"
" B { name: String },\n"
" C,\n"
" D\n"
"}\n"
"\n"
"fn swizzle(e: &mut MultiVariateEnum) {\n"
" use MultiVariateEnum::*;\n"
" *e = match e {\n"
" // Ownership rules do not allow taking `name` by value, but we "
"cannot\n"
" // take the value out of a mutable reference, unless we replace it:\n"
" A { name } => B { name: mem::take(name) },\n"
" B { name } => A { name: mem::take(name) },\n"
" C => D,\n"
" D => C\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/mem-replace.md:59
msgid ""
"When working with enums, we may want to change an enum value in place, "
"perhaps\n"
"to another variant. This is usually done in two phases to keep the borrow\n"
"checker happy. In the first phase, we observe the existing value and look "
"at\n"
"its parts to decide what to do next. In the second phase we may "
"conditionally\n"
"change the value (as in the example above)."
msgstr ""
#: src\idioms/mem-replace.md:65
msgid ""
"The borrow checker won't allow us to take out `name` of the enum (because\n"
"_something_ must be there.) We could of course `.clone()` name and put the "
"clone\n"
"into our `MyEnum::B`, but that would be an instance of the [Clone to satisfy "
"the borrow checker](../anti_patterns/borrow_clone.md) anti-pattern. Anyway, "
"we\n"
"can avoid the extra allocation by changing `e` with only a mutable borrow."
msgstr ""
#: src\idioms/mem-replace.md:70
msgid ""
"`mem::take` lets us swap out the value, replacing it with it's default "
"value,\n"
"and returning the previous value. For `String`, the default value is an "
"empty\n"
"`String`, which does not need to allocate. As a result, we get the original\n"
"`name` _as an owned value_. We can then wrap this in another enum."
msgstr ""
#: src\idioms/mem-replace.md:75
msgid ""
"**NOTE:** `mem::replace` is very similar, but allows us to specify what to\n"
"replace the value with. An equivalent to our `mem::take` line would be\n"
"`mem::replace(name, String::new())`."
msgstr ""
#: src\idioms/mem-replace.md:79
msgid ""
"Note, however, that if we are using an `Option` and want to replace its\n"
"value with a `None`, `Option`s `take()` method provides a shorter and\n"
"more idiomatic alternative."
msgstr ""
#: src\idioms/mem-replace.md:85
msgid ""
"Look ma, no allocation! Also you may feel like Indiana Jones while doing it."
msgstr ""
#: src\idioms/mem-replace.md:89
msgid ""
"This gets a bit wordy. Getting it wrong repeatedly will make you hate the\n"
"borrow checker. The compiler may fail to optimize away the double store,\n"
"resulting in reduced performance as opposed to what you'd do in unsafe\n"
"languages."
msgstr ""
#: src\idioms/mem-replace.md:94
msgid ""
"Furthermore, the type you are taking needs to implement the [`Default` "
"trait](./default.md). However, if the type you're working with doesn't\n"
"implement this, you can instead use `mem::replace`."
msgstr ""
#: src\idioms/mem-replace.md:99
msgid ""
"This pattern is only of interest in Rust. In GC'd languages, you'd take the\n"
"reference to the value by default (and the GC would keep track of refs), and "
"in\n"
"other low-level languages like C you'd simply alias the pointer and fix "
"things\n"
"later."
msgstr ""
#: src\idioms/mem-replace.md:104
msgid ""
"However, in Rust, we have to do a little more work to do this. An owned "
"value\n"
"may only have one owner, so to take it out, we need to put something back in "
"\n"
"like Indiana Jones, replacing the artifact with a bag of sand."
msgstr ""
#: src\idioms/mem-replace.md:110
msgid ""
"This gets rid of the [Clone to satisfy the borrow "
"checker](../anti_patterns/borrow_clone.md)\n"
"anti-pattern in a specific case."
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:1
msgid "# On-Stack Dynamic Dispatch"
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:5
msgid ""
"We can dynamically dispatch over multiple values, however, to do so, we "
"need\n"
"to declare multiple variables to bind differently-typed objects. To extend "
"the\n"
"lifetime as necessary, we can use deferred conditional initialization, as "
"seen\n"
"below:"
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:12
msgid ""
"```rust\n"
"use std::io;\n"
"use std::fs;\n"
"\n"
"# fn main() -> Result<(), Box<dyn std::error::Error>> {\n"
"# let arg = \"-\";\n"
"\n"
"// These must live longer than `readable`, and thus are declared first:\n"
"let (mut stdin_read, mut file_read);\n"
"\n"
"// We need to ascribe the type to get dynamic dispatch.\n"
"let readable: &mut dyn io::Read = if arg == \"-\" {\n"
" stdin_read = io::stdin();\n"
" &mut stdin_read\n"
"} else {\n"
" file_read = fs::File::open(arg)?;\n"
" &mut file_read\n"
"};\n"
"\n"
"// Read from `readable` here.\n"
"\n"
"# Ok(())\n"
"# }\n"
"```"
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:39
msgid ""
"Rust monomorphises code by default. This means a copy of the code will be\n"
"generated for each type it is used with and optimized independently. While "
"this\n"
"allows for very fast code on the hot path, it also bloats the code in "
"places\n"
"where performance is not of the essence, thus costing compile time and "
"cache\n"
"usage."
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:45
msgid ""
"Luckily, Rust allows us to use dynamic dispatch, but we have to explicitly "
"ask\n"
"for it."
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:50
msgid ""
"We do not need to allocate anything on the heap. Neither do we need to\n"
"initialize something we won't use later, nor do we need to monomorphize the\n"
"whole code that follows to work with both `File` or `Stdin`."
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:56
msgid "The code needs more moving parts than the `Box`-based version:"
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:58
msgid ""
"```rust,ignore\n"
"// We still need to ascribe the type for dynamic dispatch.\n"
"let readable: Box<dyn io::Read> = if arg == \"-\" {\n"
" Box::new(io::stdin())\n"
"} else {\n"
" Box::new(fs::File::open(arg)?)\n"
"};\n"
"// Read from `readable` here.\n"
"```"
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:70
msgid ""
"Rust newcomers will usually learn that Rust requires all variables to be\n"
"initialized _before use_, so it's easy to overlook the fact that _unused_\n"
"variables may well be uninitialized. Rust works quite hard to ensure that "
"this\n"
"works out fine and only the initialized values are dropped at the end of "
"their\n"
"scope."
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:76
msgid "The example meets all the constraints Rust places on us:"
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:78
msgid ""
"- All variables are initialized before using (in this case borrowing) them\n"
"- Each variable only holds values of a single type. In our example, `stdin` "
"is\n"
" of type `Stdin`, `file` is of type `File` and `readable` is of type `&mut "
"dyn Read`\n"
"- Each borrowed value outlives all the references borrowed from it"
msgstr ""
#: src\idioms/on-stack-dyn-dispatch.md:85
msgid ""
"- [Finalisation in destructors](dtor-finally.md) and\n"
" [RAII guards](../patterns/behavioural/RAII.md) can benefit from tight "
"control over\n"
" lifetimes.\n"
"- For conditionally filled `Option<&T>`s of (mutable) references, one can\n"
" initialize an `Option<T>` directly and use its [`.as_ref()`] method to get "
"an\n"
" optional reference."
msgstr ""
#: src\idioms/ffi/intro.md:1
msgid "# FFI Idioms"
msgstr ""
#: src\idioms/ffi/intro.md:3
msgid ""
"Writing FFI code is an entire course in itself.\n"
"However, there are several idioms here that can act as pointers, and avoid\n"
"traps for inexperienced users of `unsafe` Rust."
msgstr ""
#: src\idioms/ffi/intro.md:7
msgid "This section contains idioms that may be useful when doing FFI."
msgstr ""
#: src\idioms/ffi/intro.md:9
msgid ""
"1. [Idiomatic Errors](./errors.md) - Error handling with integer codes and\n"
" sentinel return values (such as `NULL` pointers)\n"
"\n"
"2. [Accepting Strings](./accepting-strings.md) with minimal unsafe code\n"
"\n"
"3. [Passing Strings](./passing-strings.md) to FFI functions"
msgstr ""
#: src\idioms/ffi/errors.md:1
msgid "# Error Handling in FFI"
msgstr ""
#: src\idioms/ffi/errors.md:5
msgid ""
"In foreign languages like C, errors are represented by return codes.\n"
"However, Rust's type system allows much more rich error information to be\n"
"captured and propogated through a full type."
msgstr ""
#: src\idioms/ffi/errors.md:9
msgid ""
"This best practice shows different kinds of error codes, and how to expose "
"them\n"
"in a usable way:"
msgstr ""
#: src\idioms/ffi/errors.md:12
msgid ""
"1. Flat Enums should be converted to integers and returned as codes.\n"
"2. Structured Enums should be converted to an integer code with a string "
"error\n"
" message for detail.\n"
"3. Custom Error Types should become \"transparent\", with a C representation."
msgstr ""
#: src\idioms/ffi/errors.md:17
#: src\idioms/ffi/accepting-strings.md:29
#: src\idioms/ffi/passing-strings.md:26
#: src\patterns/ffi/export.md:40
#: src\patterns/ffi/wrappers.md:23
msgid "## Code Example"
msgstr ""
#: src\idioms/ffi/errors.md:19
msgid "### Flat Enums"
msgstr ""
#: src\idioms/ffi/errors.md:21
msgid ""
"```rust,ignore\n"
"enum DatabaseError {\n"
" IsReadOnly = 1, // user attempted a write operation\n"
" IOError = 2, // user should read the C errno() for what it was\n"
" FileCorrupted = 3, // user should run a repair tool to recover it\n"
"}\n"
"\n"
"impl From<DatabaseError> for libc::c_int {\n"
" fn from(e: DatabaseError) -> libc::c_int {\n"
" (e as i8).into()\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/ffi/errors.md:35
msgid "### Structured Enums"
msgstr ""
#: src\idioms/ffi/errors.md:37
msgid ""
"```rust,ignore\n"
"pub mod errors {\n"
" enum DatabaseError {\n"
" IsReadOnly,\n"
" IOError(std::io::Error),\n"
" FileCorrupted(String), // message describing the issue\n"
" }\n"
"\n"
" impl From<DatabaseError> for libc::c_int {\n"
" fn from(e: DatabaseError) -> libc::c_int {\n"
" match e {\n"
" DatabaseError::IsReadOnly => 1,\n"
" DatabaseError::IOError(_) => 2,\n"
" DatabaseError::FileCorrupted(_) => 3,\n"
" }\n"
" }\n"
" }\n"
"}\n"
"\n"
"pub mod c_api {\n"
" use super::errors::DatabaseError;\n"
"\n"
" #[no_mangle]\n"
" pub extern \"C\" fn db_error_description(\n"
" e: *const DatabaseError\n"
" ) -> *mut libc::c_char {\n"
"\n"
" let error: &DatabaseError = unsafe {\n"
" // SAFETY: pointer lifetime is greater than the current stack "
"frame\n"
" &*e\n"
" };\n"
"\n"
" let error_str: String = match error {\n"
" DatabaseError::IsReadOnly => {\n"
" format!(\"cannot write to read-only database\");\n"
" }\n"
" DatabaseError::IOError(e) => {\n"
" format!(\"I/O Error: {}\", e);\n"
" }\n"
" DatabaseError::FileCorrupted(s) => {\n"
" format!(\"File corrupted, run repair: {}\", &s);\n"
" }\n"
" };\n"
"\n"
" let c_error = unsafe {\n"
" // SAFETY: copying error_str to an allocated buffer with a NUL\n"
" // character at the end\n"
" let mut malloc: *mut u8 = libc::malloc(error_str.len() + 1) as "
"*mut _;\n"
"\n"
" if malloc.is_null() {\n"
" return std::ptr::null_mut();\n"
" }\n"
"\n"
" let src = error_str.as_bytes().as_ptr();\n"
"\n"
" std::ptr::copy_nonoverlapping(src, malloc, error_str.len());\n"
"\n"
" std::ptr::write(malloc.add(error_str.len()), 0);\n"
"\n"
" malloc as *mut libc::c_char\n"
" };\n"
"\n"
" c_error\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/ffi/errors.md:104
msgid "### Custom Error Types"
msgstr ""
#: src\idioms/ffi/errors.md:106
msgid ""
"```rust,ignore\n"
"struct ParseError {\n"
" expected: char,\n"
" line: u32,\n"
" ch: u16\n"
"}\n"
"\n"
"impl ParseError { /* ... */ }\n"
"\n"
"/* Create a second version which is exposed as a C structure */\n"
"#[repr(C)]\n"
"pub struct parse_error {\n"
" pub expected: libc::c_char,\n"
" pub line: u32,\n"
" pub ch: u16\n"
"}\n"
"\n"
"impl From<ParseError> for parse_error {\n"
" fn from(e: ParseError) -> parse_error {\n"
" let ParseError { expected, line, ch } = e;\n"
" parse_error { expected, line, ch }\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/ffi/errors.md:133
msgid ""
"This ensures that the foreign language has clear access to error "
"information\n"
"while not compromising the Rust code's API at all."
msgstr ""
#: src\idioms/ffi/errors.md:138
msgid ""
"It's a lot of typing, and some types may not be able to be converted easily\n"
"to C."
msgstr ""
#: src\idioms/ffi/accepting-strings.md:1
msgid "# Accepting Strings"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:5
msgid ""
"When accepting strings via FFI through pointers, there are two principles "
"that\n"
"should be followed:"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:8
msgid ""
"1. Keep foreign strings \"borrowed\", rather than copying them directly.\n"
"2. Minimize the amount of complexity and `unsafe` code involved in "
"converting\n"
" from a C-style string to native Rust strings."
msgstr ""
#: src\idioms/ffi/accepting-strings.md:14
msgid ""
"The strings used in C have different behaviours to those used in Rust, "
"namely:"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:16
msgid ""
"- C strings are null-terminated while Rust strings store their length\n"
"- C strings can contain any arbitrary non-zero byte while Rust strings must "
"be\n"
" UTF-8\n"
"- C strings are accessed and manipulated using `unsafe` pointer operations\n"
" while interactions with Rust strings go through safe methods"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:22
msgid ""
"The Rust standard library comes with C equivalents of Rust's `String` and "
"`&str`\n"
"called `CString` and `&CStr`, that allow us to avoid a lot of the "
"complexity\n"
"and `unsafe` code involved in converting between C strings and Rust strings."
msgstr ""
#: src\idioms/ffi/accepting-strings.md:26
msgid ""
"The `&CStr` type also allows us to work with borrowed data, meaning passing\n"
"strings between Rust and C is a zero-cost operation."
msgstr ""
#: src\idioms/ffi/accepting-strings.md:31
msgid ""
"```rust,ignore\n"
"pub mod unsafe_module {\n"
"\n"
" // other module content\n"
"\n"
" /// Log a message at the specified level.\n"
" ///\n"
" /// # Safety\n"
" ///\n"
" /// It is the caller's guarantee to ensure `msg`:\n"
" ///\n"
" /// - is not a null pointer\n"
" /// - points to valid, initialized data\n"
" /// - points to memory ending in a null byte\n"
" /// - won't be mutated for the duration of this function call\n"
" #[no_mangle]\n"
" pub unsafe extern \"C\" fn mylib_log(\n"
" msg: *const libc::c_char,\n"
" level: libc::c_int\n"
" ) {\n"
" let level: crate::LogLevel = match level { /* ... */ };\n"
"\n"
" // SAFETY: The caller has already guaranteed this is okay (see the\n"
" // `# Safety` section of the doc-comment).\n"
" let msg_str: &str = match std::ffi::CStr::from_ptr(msg).to_str() {\n"
" Ok(s) => s,\n"
" Err(e) => {\n"
" crate::log_error(\"FFI string conversion failed\");\n"
" return;\n"
" }\n"
" };\n"
"\n"
" crate::log(msg_str, level);\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:70
msgid "The example is is written to ensure that:"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:72
msgid ""
"1. The `unsafe` block is as small as possible.\n"
"2. The pointer with an \"untracked\" lifetime becomes a \"tracked\" shared\n"
" reference"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:76
msgid "Consider an alternative, where the string is actually copied:"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:78
msgid ""
"```rust,ignore\n"
"pub mod unsafe_module {\n"
"\n"
" // other module content\n"
"\n"
" pub extern \"C\" fn mylib_log(msg: *const libc::c_char, level: "
"libc::c_int) {\n"
" // DO NOT USE THIS CODE.\n"
" // IT IS UGLY, VERBOSE, AND CONTAINS A SUBTLE BUG.\n"
"\n"
" let level: crate::LogLevel = match level { /* ... */ };\n"
"\n"
" let msg_len = unsafe { /* SAFETY: strlen is what it is, I guess? */\n"
" libc::strlen(msg)\n"
" };\n"
"\n"
" let mut msg_data = Vec::with_capacity(msg_len + 1);\n"
"\n"
" let msg_cstr: std::ffi::CString = unsafe {\n"
" // SAFETY: copying from a foreign pointer expected to live\n"
" // for the entire stack frame into owned memory\n"
" std::ptr::copy_nonoverlapping(msg, msg_data.as_mut(), msg_len);\n"
"\n"
" msg_data.set_len(msg_len + 1);\n"
"\n"
" std::ffi::CString::from_vec_with_nul(msg_data).unwrap()\n"
" }\n"
"\n"
" let msg_str: String = unsafe {\n"
" match msg_cstr.into_string() {\n"
" Ok(s) => s,\n"
" Err(e) => {\n"
" crate::log_error(\"FFI string conversion failed\");\n"
" return;\n"
" }\n"
" }\n"
" };\n"
"\n"
" crate::log(&msg_str, level);\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:120
msgid "This code in inferior to the original in two respects:"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:122
msgid ""
"1. There is much more `unsafe` code, and more importantly, more invariants "
"it\n"
" must uphold.\n"
"2. Due to the extensive arithmetic required, there is a bug in this version\n"
" that cases Rust `undefined behaviour`."
msgstr ""
#: src\idioms/ffi/accepting-strings.md:127
msgid ""
"The bug here is a simple mistake in pointer arithmetic: the string was "
"copied,\n"
"all `msg_len` bytes of it. However, the `NUL` terminator at the end was not."
msgstr ""
#: src\idioms/ffi/accepting-strings.md:130
msgid ""
"The Vector then had its size _set_ to the length of the _zero padded string_ "
"--\n"
"rather than _resized_ to it, which could have added a zero at the end.\n"
"As a result, the last byte in the Vector is uninitialized memory.\n"
"When the `CString` is created at the bottom of the block, its read of the\n"
"Vector will cause `undefined behaviour`!"
msgstr ""
#: src\idioms/ffi/accepting-strings.md:136
msgid ""
"Like many such issues, this would be difficult issue to track down.\n"
"Sometimes it would panic because the string was not `UTF-8`, sometimes it "
"would\n"
"put a weird character at the end of the string, sometimes it would just\n"
"completely crash."
msgstr ""
#: src\idioms/ffi/accepting-strings.md:143
#: src\idioms/ffi/passing-strings.md:105
msgid "None?"
msgstr ""
#: src\idioms/ffi/passing-strings.md:1
msgid "# Passing Strings"
msgstr ""
#: src\idioms/ffi/passing-strings.md:5
msgid ""
"When passing strings to FFI functions, there are four principles that should "
"be\n"
"followed:"
msgstr ""
#: src\idioms/ffi/passing-strings.md:8
msgid ""
"1. Make the lifetime of owned strings as long as possible.\n"
"2. Minimize `unsafe` code during the conversion.\n"
"3. If the C code can modify the string data, use `Vec` instead of "
"`CString`.\n"
"4. Unless the Foreign Function API requires it, the ownership of the string\n"
" should not transfer to the callee."
msgstr ""
#: src\idioms/ffi/passing-strings.md:16
msgid ""
"Rust has built-in support for C-style strings with its `CString` and `CStr`\n"
"types. However, there are different approaches one can take with strings "
"that\n"
"are being sent to a foreign function call from a Rust function."
msgstr ""
#: src\idioms/ffi/passing-strings.md:20
msgid ""
"The best practice is simple: use `CString` in such a way as to minimize\n"
"`unsafe` code. However, a secondary caveat is that\n"
"_the object must live long enough_, meaning the lifetime should be "
"maximized.\n"
"In addition, the documentation explains that \"round-tripping\" a `CString` "
"after\n"
"modification is UB, so additional work is necessary in that case."
msgstr ""
#: src\idioms/ffi/passing-strings.md:28
msgid ""
"```rust,ignore\n"
"pub mod unsafe_module {\n"
"\n"
" // other module content\n"
"\n"
" extern \"C\" {\n"
" fn seterr(message: *const libc::c_char);\n"
" fn geterr(buffer: *mut libc::c_char, size: libc::c_int) -> "
"libc::c_int;\n"
" }\n"
"\n"
" fn report_error_to_ffi<S: Into<String>>(\n"
" err: S\n"
" ) -> Result<(), std::ffi::NulError>{\n"
" let c_err = std::ffi::CString::new(err.into())?;\n"
"\n"
" unsafe {\n"
" // SAFETY: calling an FFI whose documentation says the pointer "
"is\n"
" // const, so no modification should occur\n"
" seterr(c_err.as_ptr());\n"
" }\n"
"\n"
" Ok(())\n"
" // The lifetime of c_err continues until here\n"
" }\n"
"\n"
" fn get_error_from_ffi() -> Result<String, std::ffi::IntoStringError> {\n"
" let mut buffer = vec![0u8; 1024];\n"
" unsafe {\n"
" // SAFETY: calling an FFI whose documentation implies\n"
" // that the input need only live as long as the call\n"
" let written: usize = geterr(buffer.as_mut_ptr(), 1023).into();\n"
"\n"
" buffer.truncate(written + 1);\n"
" }\n"
"\n"
" std::ffi::CString::new(buffer).unwrap().into_string()\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/ffi/passing-strings.md:70
msgid "The example is written in a way to ensure that:"
msgstr ""
#: src\idioms/ffi/passing-strings.md:72
msgid ""
"1. The `unsafe` block is as small as possible.\n"
"2. The `CString` lives long enough.\n"
"3. Errors with typecasts are always propagated when possible."
msgstr ""
#: src\idioms/ffi/passing-strings.md:76
msgid ""
"A common mistake (so common it's in the documentation) is to not use the\n"
"variable in the first block:"
msgstr ""
#: src\idioms/ffi/passing-strings.md:79
msgid ""
"```rust,ignore\n"
"pub mod unsafe_module {\n"
"\n"
" // other module content\n"
"\n"
" fn report_error<S: Into<String>>(err: S) -> Result<(), "
"std::ffi::NulError> {\n"
" unsafe {\n"
" // SAFETY: whoops, this contains a dangling pointer!\n"
" seterr(std::ffi::CString::new(err.into())?.as_ptr());\n"
" }\n"
" Ok(())\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/ffi/passing-strings.md:94
msgid ""
"This code will result in a dangling pointer, because the lifetime of the\n"
"`CString` is not extended by the pointer creation, unlike if a reference "
"were\n"
"created."
msgstr ""
#: src\idioms/ffi/passing-strings.md:98
msgid ""
"Another issue frequently raised is that the initialization of a 1k vector "
"of\n"
"zeroes is \"slow\". However, recent versions of Rust actually optimize that\n"
"particular macro to a call to `zmalloc`, meaning it is as fast as the "
"operating\n"
"system's ability to return zeroed memory (which is quite fast)."
msgstr ""
#: src\idioms/option-iter.md:1
msgid "# Iterating over an `Option`"
msgstr ""
#: src\idioms/option-iter.md:5
msgid ""
"`Option` can be viewed as a container that contains either zero or one\n"
"element. In particular, it implements the `IntoIterator` trait, and as such\n"
"can be used with generic code that needs such a type."
msgstr ""
#: src\idioms/option-iter.md:9
#: src\patterns/structural/small-crates.md:34
#: src\patterns/structural/unsafe-mods.md:22
msgid "## Examples"
msgstr ""
#: src\idioms/option-iter.md:11
msgid ""
"Since `Option` implements `IntoIterator`, it can be used as an argument to\n"
"[`.extend()`](https://doc.rust-lang.org/std/iter/trait.Extend.html#tymethod.extend):"
msgstr ""
#: src\idioms/option-iter.md:14
msgid ""
"```rust\n"
"let turing = Some(\"Turing\");\n"
"let mut logicians = vec![\"Curry\", \"Kleene\", \"Markov\"];\n"
"\n"
"logicians.extend(turing);\n"
"\n"
"// equivalent to\n"
"if let Some(turing_inner) = turing {\n"
" logicians.push(turing_inner);\n"
"}\n"
"```"
msgstr ""
#: src\idioms/option-iter.md:26
msgid ""
"If you need to tack an `Option` to the end of an existing iterator, you can\n"
"pass it to "
"[`.chain()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.chain):"
msgstr ""
#: src\idioms/option-iter.md:29
msgid ""
"```rust\n"
"let turing = Some(\"Turing\");\n"
"let logicians = vec![\"Curry\", \"Kleene\", \"Markov\"];\n"
"\n"
"for logician in logicians.iter().chain(turing.iter()) {\n"
" println!(\"{} is a logician\", logician);\n"
"}\n"
"```"
msgstr ""
#: src\idioms/option-iter.md:38
msgid ""
"Note that if the `Option` is always `Some`, then it is more idiomatic to "
"use\n"
"[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) on the\n"
"element instead."
msgstr ""
#: src\idioms/option-iter.md:42
msgid ""
"Also, since `Option` implements `IntoIterator`, it's possible to iterate "
"over\n"
"it using a `for` loop. This is equivalent to matching it with `if let "
"Some(..)`,\n"
"and in most cases you should prefer the latter."
msgstr ""
#: src\idioms/option-iter.md:48
msgid ""
"- [`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) is "
"an\n"
" iterator which yields exactly one element. It's a more readable "
"alternative to\n"
" `Some(foo).into_iter()`.\n"
"\n"
"- "
"[`Iterator::filter_map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map)\n"
" is a version of "
"[`Iterator::map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map),\n"
" specialized to mapping functions which return `Option`.\n"
"\n"
"- The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides "
"functions\n"
" for converting an `Option` to a zero- or one-element slice.\n"
"\n"
"- [Documentation for "
"`Option<T>`](https://doc.rust-lang.org/std/option/enum.Option.html)"
msgstr ""
#: src\idioms/pass-var-to-closure.md:1
msgid "# Pass variables to closure"
msgstr ""
#: src\idioms/pass-var-to-closure.md:5
msgid ""
"By default, closures capture their environment by borrowing. Or you can use\n"
"`move`-closure to move whole environment. However, often you want to move "
"just\n"
"some variables to closure, give it copy of some data, pass it by reference, "
"or\n"
"perform some other transformation."
msgstr ""
#: src\idioms/pass-var-to-closure.md:10
msgid "Use variable rebinding in separate scope for that."
msgstr ""
#: src\idioms/pass-var-to-closure.md:14
msgid "Use"
msgstr ""
#: src\idioms/pass-var-to-closure.md:16
msgid ""
"```rust\n"
"use std::rc::Rc;\n"
"\n"
"let num1 = Rc::new(1);\n"
"let num2 = Rc::new(2);\n"
"let num3 = Rc::new(3);\n"
"let closure = {\n"
" // `num1` is moved\n"
" let num2 = num2.clone(); // `num2` is cloned\n"
" let num3 = num3.as_ref(); // `num3` is borrowed\n"
" move || {\n"
" *num1 + *num2 + *num3;\n"
" }\n"
"};\n"
"```"
msgstr ""
#: src\idioms/pass-var-to-closure.md:32
msgid "instead of"
msgstr ""
#: src\idioms/pass-var-to-closure.md:34
msgid ""
"```rust\n"
"use std::rc::Rc;\n"
"\n"
"let num1 = Rc::new(1);\n"
"let num2 = Rc::new(2);\n"
"let num3 = Rc::new(3);\n"
"\n"
"let num2_cloned = num2.clone();\n"
"let num3_borrowed = num3.as_ref();\n"
"let closure = move || {\n"
" *num1 + *num2_cloned + *num3_borrowed;\n"
"};\n"
"```"
msgstr ""
#: src\idioms/pass-var-to-closure.md:50
msgid ""
"Copied data are grouped together with closure definition, so their purpose "
"is\n"
"more clear, and they will be dropped immediately even if they are not "
"consumed\n"
"by closure."
msgstr ""
#: src\idioms/pass-var-to-closure.md:54
msgid ""
"Closure uses same variable names as surrounding code whether data are copied "
"or\n"
"moved."
msgstr ""
#: src\idioms/pass-var-to-closure.md:59
msgid "Additional indentation of closure body."
msgstr ""
#: src\idioms/priv-extend.md:1
msgid "# `#[non_exhaustive]` and private fields for extensibility"
msgstr ""
#: src\idioms/priv-extend.md:5
msgid ""
"A small set of scenarios exist where a library author may want to add "
"public\n"
"fields to a public struct or new variants to an enum without breaking "
"backwards\n"
"compatibility."
msgstr ""
#: src\idioms/priv-extend.md:9
msgid "Rust offers two solutions to this problem:"
msgstr ""
#: src\idioms/priv-extend.md:11
msgid ""
"- Use `#[non_exhaustive]` on `struct`s, `enum`s, and `enum` variants.\n"
" For extensive documentation on all the places where `#[non_exhaustive]` "
"can be\n"
" used, see [the "
"docs](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute).\n"
"\n"
"- You may add a private field to a struct to prevent it from being directly\n"
" instantiated or matched against (see Alternative)"
msgstr ""
#: src\idioms/priv-extend.md:20
msgid ""
"```rust\n"
"mod a {\n"
" // Public struct.\n"
" #[non_exhaustive]\n"
" pub struct S {\n"
" pub foo: i32,\n"
" }\n"
" \n"
" #[non_exhaustive]\n"
" pub enum AdmitMoreVariants {\n"
" VariantA,\n"
" VariantB,\n"
" #[non_exhaustive]\n"
" VariantC { a: String }\n"
" }\n"
"}\n"
"\n"
"fn print_matched_variants(s: a::S) {\n"
" // Because S is `#[non_exhaustive]`, it cannot be named here and\n"
" // we must use `..` in the pattern.\n"
" let a::S { foo: _, ..} = s;\n"
" \n"
" let some_enum = a::AdmitMoreVariants::VariantA;\n"
" match some_enum {\n"
" a::AdmitMoreVariants::VariantA => println!(\"it's an A\"),\n"
" a::AdmitMoreVariants::VariantB => println!(\"it's a b\"),\n"
"\n"
" // .. required because this variant is non-exhaustive as well\n"
" a::AdmitMoreVariants::VariantC { a, .. } => println!(\"it's a c\"),\n"
"\n"
" // The wildcard match is required because more variants may be\n"
" // added in the future\n"
" _ => println!(\"it's a new variant\")\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\idioms/priv-extend.md:57
msgid "## Alternative: `Private fields` for structs"
msgstr ""
#: src\idioms/priv-extend.md:59
msgid ""
"`#[non_exhaustive]` only works across crate boundaries.\n"
"Within a crate, the private field method may be used."
msgstr ""
#: src\idioms/priv-extend.md:62
msgid ""
"Adding a field to a struct is a mostly backwards compatible change.\n"
"However, if a client uses a pattern to deconstruct a struct instance, they\n"
"might name all the fields in the struct and adding a new one would break "
"that\n"
"pattern.\n"
"The client could name some fields and use `..` in the pattern, in which case "
"adding\n"
"another field is backwards compatible.\n"
"Making at least one of the struct's fields private forces clients to use the "
"latter\n"
"form of patterns, ensuring that the struct is future-proof."
msgstr ""
#: src\idioms/priv-extend.md:71
msgid ""
"The downside of this approach is that you might need to add an otherwise "
"unneeded\n"
"field to the struct.\n"
"You can use the `()` type so that there is no runtime overhead and prepend "
"`_` to\n"
"the field name to avoid the unused field warning."
msgstr ""
#: src\idioms/priv-extend.md:76
msgid ""
"```rust\n"
"pub struct S {\n"
" pub a: i32,\n"
" // Because `b` is private, you cannot match on `S` without using `..` "
"and `S`\n"
" // cannot be directly instantiated or matched against\n"
" _b: ()\n"
"}\n"
"```"
msgstr ""
#: src\idioms/priv-extend.md:87
msgid ""
"On `struct`s, `#[non_exhaustive]` allows adding additional fields in a "
"backwards\n"
"compatible way.\n"
"It will also prevent clients from using the struct constructor, even if all "
"the\n"
"fields are public.\n"
"This may be helpful, but it's worth considering if you _want_ an additional "
"field\n"
"to be found by clients as a compiler error rather than something that may be "
"silently\n"
"undiscovered."
msgstr ""
#: src\idioms/priv-extend.md:95
msgid ""
"`#[non_exhaustive]` can be applied to enum variants as well.\n"
"A `#[non_exhaustive]` variant behaves in the same way as a "
"`#[non_exhaustive]` struct."
msgstr ""
#: src\idioms/priv-extend.md:98
msgid ""
"Use this deliberately and with caution: incrementing the major version when "
"adding\n"
"fields or variants is often a better option.\n"
"`#[non_exhaustive]` may be appropriate in scenarios where you're modeling an "
"external\n"
"resource that may change out-of-sync with your library, but is not a general "
"purpose\n"
"tool."
msgstr ""
#: src\idioms/priv-extend.md:104
msgid "### Disadvantages"
msgstr ""
#: src\idioms/priv-extend.md:106
msgid ""
"`#[non_exhaustive]` can make your code much less ergonomic to use, "
"especially when\n"
"forced to handle unknown enum variants.\n"
"It should only be used when these sorts of evolutions are required "
"**without**\n"
"incrementing the major version."
msgstr ""
#: src\idioms/priv-extend.md:111
msgid ""
"When `#[non_exhaustive]` is applied to `enum`s, it forces clients to handle "
"a\n"
"wildcard variant.\n"
"If there is no sensible action to take in this case, this may lead to "
"awkward\n"
"code and code paths that are only executed in extremely rare circumstances.\n"
"If a client decides to `panic!()` in this scenario, it may have been better "
"to\n"
"expose this error at compile time.\n"
"In fact, `#[non_exhaustive]` forces clients to handle the \"Something else\" "
"case;\n"
"there is rarely a sensible action to take in this scenario."
msgstr ""
#: src\idioms/priv-extend.md:122
msgid ""
"- [RFC introducing #[non_exhaustive] attribute for enums and "
"structs](https://github.com/rust-lang/rfcs/blob/master/text/2008-non-exhaustive.md)"
msgstr ""
#: src\idioms/rustdoc-init.md:1
msgid "# Easy doc initialization\r"
msgstr ""
#: src\idioms/rustdoc-init.md:5
msgid ""
"If a struct takes significant effort to initialize when writing docs, it can "
"be\r\n"
"quicker to wrap your example with a helper function which takes the struct "
"as an\r\n"
"argument."
msgstr ""
#: src\idioms/rustdoc-init.md:9
msgid "## Motivation\r"
msgstr ""
#: src\idioms/rustdoc-init.md:11
msgid ""
"Sometimes there is a struct with multiple or complicated parameters and "
"several\r\n"
"methods. Each of these methods should have examples."
msgstr ""
#: src\idioms/rustdoc-init.md:14
msgid "For example:"
msgstr ""
#: src\idioms/rustdoc-init.md:16
msgid ""
"````rust,ignore\r\n"
"struct Connection {\r\n"
" name: String,\r\n"
" stream: TcpStream,\r\n"
"}\r\n"
"\r\n"
"impl Connection {\r\n"
" /// Sends a request over the connection.\r\n"
" ///\r\n"
" /// # Example\r\n"
" /// ```no_run\r\n"
" /// # // Boilerplate are required to get an example working.\r\n"
" /// # let stream = TcpStream::connect(\"127.0.0.1:34254\");\r\n"
" /// # let connection = Connection { name: \"foo\".to_owned(), stream "
"};\r\n"
" /// # let request = Request::new(\"RequestId\", RequestType::Get, "
"\"payload\");\r\n"
" /// let response = connection.send_request(request);\r\n"
" /// assert!(response.is_ok());\r\n"
" /// ```\r\n"
" fn send_request(&self, request: Request) -> Result<Status, SendErr> {\r\n"
" // ...\r\n"
" }\r\n"
"\r\n"
" /// Oh no, all that boilerplate needs to be repeated here!\r\n"
" fn check_status(&self) -> Status {\r\n"
" // ...\r\n"
" }\r\n"
"}\r\n"
"````"
msgstr ""
#: src\idioms/rustdoc-init.md:45
msgid "## Example\r"
msgstr ""
#: src\idioms/rustdoc-init.md:47
msgid ""
"Instead of typing all of this boilerplate to create a `Connection` and\r\n"
"`Request`, it is easier to just create a wrapping helper function which "
"takes\r\n"
"them as arguments:"
msgstr ""
#: src\idioms/rustdoc-init.md:51
msgid ""
"````rust,ignore\r\n"
"struct Connection {\r\n"
" name: String,\r\n"
" stream: TcpStream,\r\n"
"}\r\n"
"\r\n"
"impl Connection {\r\n"
" /// Sends a request over the connection.\r\n"
" ///\r\n"
" /// # Example\r\n"
" /// ```\r\n"
" /// # fn call_send(connection: Connection, request: Request) {\r\n"
" /// let response = connection.send_request(request);\r\n"
" /// assert!(response.is_ok());\r\n"
" /// # }\r\n"
" /// ```\r\n"
" fn send_request(&self, request: Request) {\r\n"
" // ...\r\n"
" }\r\n"
"}\r\n"
"````"
msgstr ""
#: src\idioms/rustdoc-init.md:73
msgid ""
"**Note** in the above example the line `assert!(response.is_ok());` will "
"not\r\n"
"actually run while testing because it is inside a function which is never\r\n"
"invoked."
msgstr ""
#: src\idioms/rustdoc-init.md:77
msgid "## Advantages\r"
msgstr ""
#: src\idioms/rustdoc-init.md:79
msgid "This is much more concise and avoids repetitive code in examples."
msgstr ""
#: src\idioms/rustdoc-init.md:81
msgid "## Disadvantages\r"
msgstr ""
#: src\idioms/rustdoc-init.md:83
msgid ""
"As example is in a function, the code will not be tested. Though it will "
"still be\r\n"
"checked to make sure it compiles when running a `cargo test`. So this "
"pattern is\r\n"
"most useful when you need `no_run`. With this, you do not need to add "
"`no_run`."
msgstr ""
#: src\idioms/rustdoc-init.md:87
msgid "## Discussion\r"
msgstr ""
#: src\idioms/rustdoc-init.md:89
msgid "If assertions are not required this pattern works well."
msgstr ""
#: src\idioms/rustdoc-init.md:91
msgid ""
"If they are, an alternative can be to create a public method to create a "
"helper\r\n"
"instance which is annotated with `#[doc(hidden)]` (so that users won't see "
"it).\r\n"
"Then this method can be called inside of rustdoc because it is part of "
"the\r\n"
"crate's public API."
msgstr ""
#: src\idioms/temporary-mutability.md:1
msgid "# Temporary mutability"
msgstr ""
#: src\idioms/temporary-mutability.md:5
msgid ""
"Often it is necessary to prepare and process some data, but after that data "
"are\n"
"only inspected and never modified. The intention can be made explicit by "
"redefining\n"
"the mutable variable as immutable."
msgstr ""
#: src\idioms/temporary-mutability.md:9
msgid ""
"It can be done either by processing data within a nested block or by "
"redefining\n"
"the variable."
msgstr ""
#: src\idioms/temporary-mutability.md:14
msgid "Say, vector must be sorted before usage."
msgstr ""
#: src\idioms/temporary-mutability.md:16
msgid "Using nested block:"
msgstr ""
#: src\idioms/temporary-mutability.md:18
msgid ""
"```rust,ignore\n"
"let data = {\n"
" let mut data = get_vec();\n"
" data.sort();\n"
" data\n"
"};\n"
"\n"
"// Here `data` is immutable.\n"
"```"
msgstr ""
#: src\idioms/temporary-mutability.md:28
msgid "Using variable rebinding:"
msgstr ""
#: src\idioms/temporary-mutability.md:30
msgid ""
"```rust,ignore\n"
"let mut data = get_vec();\n"
"data.sort();\n"
"let data = data;\n"
"\n"
"// Here `data` is immutable.\n"
"```"
msgstr ""
#: src\idioms/temporary-mutability.md:40
msgid ""
"Compiler ensures that you don't accidentally mutate data after some point."
msgstr ""
#: src\idioms/temporary-mutability.md:44
msgid ""
"Nested block requires additional indentation of block body.\n"
"One more line to return data from block or redefine variable."
msgstr ""
#: src\idioms/return-consumed-arg-on-error.md:1
msgid "# Return consumed argument on error"
msgstr ""
#: src\idioms/return-consumed-arg-on-error.md:5
msgid ""
"If a fallible function consumes (moves) an argument, return that argument "
"back inside\n"
"an error."
msgstr ""
#: src\idioms/return-consumed-arg-on-error.md:10
msgid ""
"```rust\n"
"pub fn send(value: String) -> Result<(), SendError> {\n"
" println!(\"using {value} in a meaningful way\");\n"
" // Simulate non-deterministic fallible action.\n"
" use std::time::SystemTime;\n"
" let period = "
"SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();\n"
" if period.subsec_nanos() % 2 == 1 {\n"
" Ok(())\n"
" } else {\n"
" Err(SendError(value))\n"
" }\n"
"}\n"
"\n"
"pub struct SendError(String);\n"
"\n"
"fn main() {\n"
" let mut value = \"imagine this is very long string\".to_string();\n"
"\n"
" let success = 's: {\n"
" // Try to send value two times.\n"
" for _ in 0..2 {\n"
" value = match send(value) {\n"
" Ok(()) => break 's true,\n"
" Err(SendError(value)) => value,\n"
" }\n"
" }\n"
" false\n"
" };\n"
"\n"
" println!(\"success: {}\", success);\n"
"}\n"
"```"
msgstr ""
#: src\idioms/return-consumed-arg-on-error.md:45
msgid ""
"In case of error you may want to try some alternative way or to\n"
"retry action in case of non-deterministic function. But if the argument\n"
"is always consumed, you are forced to clone it on every call, which\n"
"is not very efficient."
msgstr ""
#: src\idioms/return-consumed-arg-on-error.md:50
msgid ""
"The standard library uses this approach in e.g. `String::from_utf8` method.\n"
"When given a vector that doesn't contain valid UTF-8, a `FromUtf8Error`\n"
"is returned.\n"
"You can get original vector back using `FromUtf8Error::into_bytes` method."
msgstr ""
#: src\idioms/return-consumed-arg-on-error.md:57
msgid "Better performance because of moving arguments whenever possible."
msgstr ""
#: src\idioms/return-consumed-arg-on-error.md:61
msgid "Slightly more complex error types."
msgstr ""
#: src\patterns/index.md:1
msgid "# Design Patterns"
msgstr ""
#: src\patterns/index.md:3
msgid ""
"[Design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) "
"are\n"
"\"general reusable solutions to a commonly occurring problem within a given\n"
"context in software design\". Design patterns are a great way to describe "
"the\n"
"culture of a programming language. Design patterns are very "
"language-specific -\n"
"what is a pattern in one language may be unnecessary in another due to a\n"
"language feature, or impossible to express due to a missing feature."
msgstr ""
#: src\patterns/index.md:10
msgid ""
"If overused, design patterns can add unnecessary complexity to programs.\n"
"However, they are a great way to share intermediate and advanced level "
"knowledge\n"
"about a programming language."
msgstr ""
#: src\patterns/index.md:16
msgid ""
"Rust has many unique features. These features give us great benefit by "
"removing\n"
"whole classes of problems. Some of them are also patterns that are _unique_ "
"to Rust."
msgstr ""
#: src\patterns/index.md:19
msgid "## YAGNI"
msgstr ""
#: src\patterns/index.md:21
msgid ""
"YAGNI is an acronym that stands for `You Aren't Going to Need It`.\n"
"It's a vital software design principle to apply as you write code."
msgstr ""
#: src\patterns/index.md:24
msgid "> The best code I ever wrote was code I never wrote."
msgstr ""
#: src\patterns/index.md:26
msgid ""
"If we apply YAGNI to design patterns, we see that the features of Rust allow "
"us to\n"
"throw out many patterns. For instance, there is no need for the [strategy "
"pattern](https://en.wikipedia.org/wiki/Strategy_pattern)\n"
"in Rust because we can just use "
"[traits](https://doc.rust-lang.org/book/traits.html)."
msgstr ""
#: src\patterns/behavioural/intro.md:1
msgid "# Behavioural Patterns"
msgstr ""
#: src\patterns/behavioural/intro.md:3
msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Behavioral_pattern):"
msgstr ""
#: src\patterns/behavioural/intro.md:5
msgid ""
"> Design patterns that identify common communication patterns among "
"objects.\n"
"> By doing so, these patterns increase flexibility in carrying out "
"communication."
msgstr ""
#: src\patterns/behavioural/command.md:1
msgid "# Command"
msgstr ""
#: src\patterns/behavioural/command.md:5
msgid ""
"The basic idea of the Command pattern is to separate out actions into its "
"own\n"
"objects and pass them as parameters."
msgstr ""
#: src\patterns/behavioural/command.md:10
msgid ""
"Suppose we have a sequence of actions or transactions encapsulated as "
"objects.\n"
"We want these actions or commands to be executed or invoked in some order "
"later\n"
"at different time. These commands may also be triggered as a result of some "
"event.\n"
"For example, when a user pushes a button, or on arrival of a data packet.\n"
"In addition, these commands might be undoable. This may come in useful for\n"
"operations of an editor. We might want to store logs of executed commands so "
"that\n"
"we could reapply the changes later if the system crashes."
msgstr ""
#: src\patterns/behavioural/command.md:20
msgid ""
"Define two database operations `create table` and `add field`. Each of "
"these\n"
"operations is a command which knows how to undo the command, e.g., `drop "
"table`\n"
"and `remove field`. When a user invokes a database migration operation then "
"each\n"
"command is executed in the defined order, and when the user invokes the "
"rollback\n"
"operation then the whole set of commands is invoked in reverse order."
msgstr ""
#: src\patterns/behavioural/command.md:26
msgid "## Approach: Using trait objects"
msgstr ""
#: src\patterns/behavioural/command.md:28
msgid ""
"We define a common trait which encapsulates our command with two operations\n"
"`execute` and `rollback`. All command `structs` must implement this trait."
msgstr ""
#: src\patterns/behavioural/command.md:31
msgid ""
"```rust\n"
"pub trait Migration {\n"
" fn execute(&self) -> &str;\n"
" fn rollback(&self) -> &str;\n"
"}\n"
"\n"
"pub struct CreateTable;\n"
"impl Migration for CreateTable {\n"
" fn execute(&self) -> &str {\n"
" \"create table\"\n"
" }\n"
" fn rollback(&self) -> &str {\n"
" \"drop table\"\n"
" }\n"
"}\n"
"\n"
"pub struct AddField;\n"
"impl Migration for AddField {\n"
" fn execute(&self) -> &str {\n"
" \"add field\"\n"
" }\n"
" fn rollback(&self) -> &str {\n"
" \"remove field\"\n"
" }\n"
"}\n"
"\n"
"struct Schema {\n"
" commands: Vec<Box<dyn Migration>>,\n"
"}\n"
"\n"
"impl Schema {\n"
" fn new() -> Self {\n"
" Self { commands: vec![] }\n"
" }\n"
"\n"
" fn add_migration(&mut self, cmd: Box<dyn Migration>) {\n"
" self.commands.push(cmd);\n"
" }\n"
"\n"
" fn execute(&self) -> Vec<&str> {\n"
" self.commands.iter().map(|cmd| cmd.execute()).collect()\n"
" }\n"
" fn rollback(&self) -> Vec<&str> {\n"
" self.commands\n"
" .iter()\n"
" .rev() // reverse iterator's direction\n"
" .map(|cmd| cmd.rollback())\n"
" .collect()\n"
" }\n"
"}\n"
"\n"
"fn main() {\n"
" let mut schema = Schema::new();\n"
"\n"
" let cmd = Box::new(CreateTable);\n"
" schema.add_migration(cmd);\n"
" let cmd = Box::new(AddField);\n"
" schema.add_migration(cmd);\n"
"\n"
" assert_eq!(vec![\"create table\", \"add field\"], schema.execute());\n"
" assert_eq!(vec![\"remove field\", \"drop table\"], schema.rollback());\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/command.md:95
msgid "## Approach: Using function pointers"
msgstr ""
#: src\patterns/behavioural/command.md:97
msgid ""
"We could follow another approach by creating each individual command as\n"
"a different function and store function pointers to invoke these functions "
"later\n"
"at a different time. Since function pointers implement all three traits "
"`Fn`,\n"
"`FnMut`, and `FnOnce` we could as well pass and store closures instead of\n"
"function pointers."
msgstr ""
#: src\patterns/behavioural/command.md:103
msgid ""
"```rust\n"
"type FnPtr = fn() -> String;\n"
"struct Command {\n"
" execute: FnPtr,\n"
" rollback: FnPtr,\n"
"}\n"
"\n"
"struct Schema {\n"
" commands: Vec<Command>,\n"
"}\n"
"\n"
"impl Schema {\n"
" fn new() -> Self {\n"
" Self { commands: vec![] }\n"
" }\n"
" fn add_migration(&mut self, execute: FnPtr, rollback: FnPtr) {\n"
" self.commands.push(Command { execute, rollback });\n"
" }\n"
" fn execute(&self) -> Vec<String> {\n"
" self.commands.iter().map(|cmd| (cmd.execute)()).collect()\n"
" }\n"
" fn rollback(&self) -> Vec<String> {\n"
" self.commands\n"
" .iter()\n"
" .rev()\n"
" .map(|cmd| (cmd.rollback)())\n"
" .collect()\n"
" }\n"
"}\n"
"\n"
"fn add_field() -> String {\n"
" \"add field\".to_string()\n"
"}\n"
"\n"
"fn remove_field() -> String {\n"
" \"remove field\".to_string()\n"
"}\n"
"\n"
"fn main() {\n"
" let mut schema = Schema::new();\n"
" schema.add_migration(|| \"create table\".to_string(), || \"drop "
"table\".to_string());\n"
" schema.add_migration(add_field, remove_field);\n"
" assert_eq!(vec![\"create table\", \"add field\"], schema.execute());\n"
" assert_eq!(vec![\"remove field\", \"drop table\"], schema.rollback());\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/command.md:150
msgid "## Approach: Using `Fn` trait objects"
msgstr ""
#: src\patterns/behavioural/command.md:152
msgid ""
"Finally, instead of defining a common command trait we could store\n"
"each command implementing the `Fn` trait separately in vectors."
msgstr ""
#: src\patterns/behavioural/command.md:155
msgid ""
"```rust\n"
"type Migration<'a> = Box<dyn Fn() -> &'a str>;\n"
"\n"
"struct Schema<'a> {\n"
" executes: Vec<Migration<'a>>,\n"
" rollbacks: Vec<Migration<'a>>,\n"
"}\n"
"\n"
"impl<'a> Schema<'a> {\n"
" fn new() -> Self {\n"
" Self {\n"
" executes: vec![],\n"
" rollbacks: vec![],\n"
" }\n"
" }\n"
" fn add_migration<E, R>(&mut self, execute: E, rollback: R)\n"
" where\n"
" E: Fn() -> &'a str + 'static,\n"
" R: Fn() -> &'a str + 'static,\n"
" {\n"
" self.executes.push(Box::new(execute));\n"
" self.rollbacks.push(Box::new(rollback));\n"
" }\n"
" fn execute(&self) -> Vec<&str> {\n"
" self.executes.iter().map(|cmd| cmd()).collect()\n"
" }\n"
" fn rollback(&self) -> Vec<&str> {\n"
" self.rollbacks.iter().rev().map(|cmd| cmd()).collect()\n"
" }\n"
"}\n"
"\n"
"fn add_field() -> &'static str {\n"
" \"add field\"\n"
"}\n"
"\n"
"fn remove_field() -> &'static str {\n"
" \"remove field\"\n"
"}\n"
"\n"
"fn main() {\n"
" let mut schema = Schema::new();\n"
" schema.add_migration(|| \"create table\", || \"drop table\");\n"
" schema.add_migration(add_field, remove_field);\n"
" assert_eq!(vec![\"create table\", \"add field\"], schema.execute());\n"
" assert_eq!(vec![\"remove field\", \"drop table\"], schema.rollback());\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/command.md:205
msgid ""
"If our commands are small and may be defined as functions or passed as a "
"closure\n"
"then using function pointers might be preferable since it does not exploit\n"
"dynamic dispatch. But if our command is a whole struct with a bunch of "
"functions\n"
"and variables defined as seperated module then using trait objects would be\n"
"more suitable. A case of application can be found in "
"[`actix`](https://actix.rs/),\n"
"which uses trait objects when it registers a handler function for routes.\n"
"In case of using `Fn` trait objects we can create and use commands in the "
"same\n"
"way as we used in case of function pointers."
msgstr ""
#: src\patterns/behavioural/command.md:214
msgid ""
"As performance, there is always a trade-off between performance and code\n"
"simplicity and organisation. Static dispatch gives faster performance, "
"while\n"
"dynamic dispatch provides flexibility when we structure our application."
msgstr ""
#: src\patterns/behavioural/command.md:220
msgid ""
"- [Command pattern](https://en.wikipedia.org/wiki/Command_pattern)\n"
"\n"
"- [Another example for the `command` "
"pattern](https://web.archive.org/web/20210223131236/https://chercher.tech/rust/command-design-pattern-rust)"
msgstr ""
#: src\patterns/behavioural/interpreter.md:1
msgid "# Interpreter"
msgstr ""
#: src\patterns/behavioural/interpreter.md:5
msgid ""
"If a problem occurs very often and requires long and repetitive steps to "
"solve\n"
"it, then the problem instances might be expressed in a simple language and "
"an\n"
"interpreter object could solve it by interpreting the sentences written in "
"this\n"
"simple language."
msgstr ""
#: src\patterns/behavioural/interpreter.md:10
msgid "Basically, for any kind of problems we define:"
msgstr ""
#: src\patterns/behavioural/interpreter.md:12
msgid ""
"- A [domain specific "
"language](https://en.wikipedia.org/wiki/Domain-specific_language),\n"
"- A grammar for this language,\n"
"- An interpreter that solves the problem instances."
msgstr ""
#: src\patterns/behavioural/interpreter.md:18
msgid ""
"Our goal is to translate simple mathematical expressions into postfix "
"expressions\n"
"(or [Reverse Polish "
"notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation))\n"
"For simplicity, our expressions consist of ten digits `0`, ..., `9` and two\n"
"operations `+`, `-`. For example, the expression `2 + 4` is translated into\n"
"`2 4 +`."
msgstr ""
#: src\patterns/behavioural/interpreter.md:24
msgid "## Context Free Grammar for our problem"
msgstr ""
#: src\patterns/behavioural/interpreter.md:26
msgid ""
"Our task is translating infix expressions into postfix ones. Let's define a "
"context\n"
"free grammar for a set of infix expressions over `0`, ..., `9`, `+`, and "
"`-`,\n"
"where:"
msgstr ""
#: src\patterns/behavioural/interpreter.md:30
msgid ""
"- Terminal symbols: `0`, `...`, `9`, `+`, `-`\n"
"- Non-terminal symbols: `exp`, `term`\n"
"- Start symbol is `exp`\n"
"- And the following are production rules"
msgstr ""
#: src\patterns/behavioural/interpreter.md:35
msgid ""
"```ignore\n"
"exp -> exp + term\n"
"exp -> exp - term\n"
"exp -> term\n"
"term -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9\n"
"```"
msgstr ""
#: src\patterns/behavioural/interpreter.md:42
msgid ""
"**NOTE:** This grammar should be further transformed depending on what we "
"are going\n"
"to do with it. For example, we might need to remove left recursion. For "
"more\n"
"details please see [Compilers: Principles,Techniques, and "
"Tools](https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)\n"
"(aka Dragon Book)."
msgstr ""
#: src\patterns/behavioural/interpreter.md:47
msgid "## Solution"
msgstr ""
#: src\patterns/behavioural/interpreter.md:49
msgid ""
"We simply implement a recursive descent parser. For simplicity's sake, the "
"code\n"
"panics when an expression is syntactically wrong (for example `2-34` or "
"`2+5-`\n"
"are wrong according to the grammar definition)."
msgstr ""
#: src\patterns/behavioural/interpreter.md:53
msgid ""
"```rust\n"
"pub struct Interpreter<'a> {\n"
" it: std::str::Chars<'a>,\n"
"}\n"
"\n"
"impl<'a> Interpreter<'a> {\n"
"\n"
" pub fn new(infix: &'a str) -> Self {\n"
" Self { it: infix.chars() }\n"
" }\n"
"\n"
" fn next_char(&mut self) -> Option<char> {\n"
" self.it.next()\n"
" }\n"
"\n"
" pub fn interpret(&mut self, out: &mut String) {\n"
" self.term(out);\n"
"\n"
" while let Some(op) = self.next_char() {\n"
" if op == '+' || op == '-' {\n"
" self.term(out);\n"
" out.push(op);\n"
" } else {\n"
" panic!(\"Unexpected symbol '{}'\", op);\n"
" }\n"
" }\n"
" }\n"
"\n"
" fn term(&mut self, out: &mut String) {\n"
" match self.next_char() {\n"
" Some(ch) if ch.is_digit(10) => out.push(ch),\n"
" Some(ch) => panic!(\"Unexpected symbol '{}'\", ch),\n"
" None => panic!(\"Unexpected end of string\"),\n"
" }\n"
" }\n"
"}\n"
"\n"
"pub fn main() {\n"
" let mut intr = Interpreter::new(\"2+3\");\n"
" let mut postfix = String::new();\n"
" intr.interpret(&mut postfix);\n"
" assert_eq!(postfix, \"23+\");\n"
"\n"
" intr = Interpreter::new(\"1-2+3-4\");\n"
" postfix.clear();\n"
" intr.interpret(&mut postfix);\n"
" assert_eq!(postfix, \"12-3+4-\");\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/interpreter.md:105
msgid ""
"There may be a wrong perception that the Interpreter design pattern is about "
"design\n"
"grammars for formal languages and implementation of parsers for these "
"grammars.\n"
"In fact, this pattern is about expressing problem instances in a more "
"specific\n"
"way and implementing functions/classes/structs that solve these problem "
"instances.\n"
"Rust language has `macro_rules!` that allow us to define special syntax and "
"rules\n"
"on how to expand this syntax into source code."
msgstr ""
#: src\patterns/behavioural/interpreter.md:112
msgid ""
"In the following example we create a simple `macro_rules!` that computes\n"
"[Euclidean length](https://en.wikipedia.org/wiki/Euclidean_distance) of `n`\n"
"dimensional vectors. Writing `norm!(x,1,2)` might be easier to express and "
"more\n"
"efficient than packing `x,1,2` into a `Vec` and calling a function "
"computing\n"
"the length."
msgstr ""
#: src\patterns/behavioural/interpreter.md:118
msgid ""
"```rust\n"
"macro_rules! norm {\n"
" ($($element:expr),*) => {\n"
" {\n"
" let mut n = 0.0;\n"
" $(\n"
" n += ($element as f64)*($element as f64);\n"
" )*\n"
" n.sqrt()\n"
" }\n"
" };\n"
"}\n"
"\n"
"fn main() {\n"
" let x = -3f64;\n"
" let y = 4f64;\n"
"\n"
" assert_eq!(3f64, norm!(x));\n"
" assert_eq!(5f64, norm!(x, y));\n"
" assert_eq!(0f64, norm!(0, 0, 0)); \n"
" assert_eq!(1f64, norm!(0.5, -0.5, 0.5, -0.5));\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/interpreter.md:144
msgid ""
"- [Interpreter pattern](https://en.wikipedia.org/wiki/Interpreter_pattern)\n"
"- [Context free "
"grammar](https://en.wikipedia.org/wiki/Context-free_grammar)\n"
"- [macro_rules!](https://doc.rust-lang.org/rust-by-example/macros.html)"
msgstr ""
#: src\patterns/behavioural/newtype.md:1
msgid "# Newtype"
msgstr ""
#: src\patterns/behavioural/newtype.md:3
msgid ""
"What if in some cases we want a type to behave similar to another type or\n"
"enforce some behaviour at compile time when using only type aliases would\n"
"not be enough?"
msgstr ""
#: src\patterns/behavioural/newtype.md:7
msgid ""
"For example, if we want to create a custom `Display` implementation for "
"`String`\n"
"due to security considerations (e.g. passwords)."
msgstr ""
#: src\patterns/behavioural/newtype.md:10
msgid ""
"For such cases we could use the `Newtype` pattern to provide **type "
"safety**\n"
"and **encapsulation**."
msgstr ""
#: src\patterns/behavioural/newtype.md:15
msgid ""
"Use a tuple struct with a single field to make an opaque wrapper for a "
"type.\n"
"This creates a new type, rather than an alias to a type (`type` items)."
msgstr ""
#: src\patterns/behavioural/newtype.md:20
msgid ""
"```rust,ignore\n"
"// Some type, not necessarily in the same module or even crate.\n"
"struct Foo {\n"
" //..\n"
"}\n"
"\n"
"impl Foo {\n"
" // These functions are not present on Bar.\n"
" //..\n"
"}\n"
"\n"
"// The newtype.\n"
"pub struct Bar(Foo);\n"
"\n"
"impl Bar {\n"
" // Constructor.\n"
" pub fn new(\n"
" //..\n"
" ) -> Self {\n"
"\n"
" //..\n"
"\n"
" }\n"
"\n"
" //..\n"
"}\n"
"\n"
"fn main() {\n"
" let b = Bar::new(...);\n"
"\n"
" // Foo and Bar are type incompatible, the following do not type check.\n"
" // let f: Foo = b;\n"
" // let b: Bar = Foo { ... };\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/newtype.md:58
msgid ""
"The primary motivation for newtypes is abstraction. It allows you to share\n"
"implementation details between types while precisely controlling the "
"interface.\n"
"By using a newtype rather than exposing the implementation type as part of "
"an\n"
"API, it allows you to change implementation backwards compatibly."
msgstr ""
#: src\patterns/behavioural/newtype.md:63
msgid ""
"Newtypes can be used for distinguishing units, e.g., wrapping `f64` to give\n"
"distinguishable `Miles` and `Kilometres`."
msgstr ""
#: src\patterns/behavioural/newtype.md:68
msgid ""
"The wrapped and wrapper types are not type compatible (as opposed to using\n"
"`type`), so users of the newtype will never 'confuse' the wrapped and "
"wrapper\n"
"types."
msgstr ""
#: src\patterns/behavioural/newtype.md:72
msgid "Newtypes are a zero-cost abstraction - there is no runtime overhead."
msgstr ""
#: src\patterns/behavioural/newtype.md:74
msgid ""
"The privacy system ensures that users cannot access the wrapped type (if "
"the\n"
"field is private, which it is by default)."
msgstr ""
#: src\patterns/behavioural/newtype.md:79
msgid ""
"The downside of newtypes (especially compared with type aliases), is that "
"there\n"
"is no special language support. This means there can be _a lot_ of "
"boilerplate.\n"
"You need a 'pass through' method for every method you want to expose on the\n"
"wrapped type, and an impl for every trait you want to also be implemented "
"for\n"
"the wrapper type."
msgstr ""
#: src\patterns/behavioural/newtype.md:87
msgid ""
"Newtypes are very common in Rust code. Abstraction or representing units are "
"the\n"
"most common uses, but they can be used for other reasons:"
msgstr ""
#: src\patterns/behavioural/newtype.md:90
msgid ""
"- restricting functionality (reduce the functions exposed or traits "
"implemented),\n"
"- making a type with copy semantics have move semantics,\n"
"- abstraction by providing a more concrete type and thus hiding internal "
"types,\n"
" e.g.,"
msgstr ""
#: src\patterns/behavioural/newtype.md:95
msgid ""
"```rust,ignore\n"
"pub struct Foo(Bar<T1, T2>);\n"
"```"
msgstr ""
#: src\patterns/behavioural/newtype.md:99
msgid ""
"Here, `Bar` might be some public, generic type and `T1` and `T2` are some "
"internal\n"
"types. Users of our module shouldn't know that we implement `Foo` by using a "
"`Bar`,\n"
"but what we're really hiding here is the types `T1` and `T2`, and how they "
"are used\n"
"with `Bar`."
msgstr ""
#: src\patterns/behavioural/newtype.md:106
msgid ""
"- [Advanced Types in the "
"book](https://doc.rust-lang.org/book/ch19-04-advanced-types.html?highlight=newtype#using-the-newtype-pattern-for-type-safety-and-abstraction)\n"
"- [Newtypes in Haskell](https://wiki.haskell.org/Newtype)\n"
"- [Type "
"aliases](https://doc.rust-lang.org/stable/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases)\n"
"- [derive_more](https://crates.io/crates/derive_more), a crate for deriving "
"many\n"
" builtin traits on newtypes.\n"
"- [The Newtype Pattern In "
"Rust](https://www.worthe-it.co.za/blog/2020-10-31-newtype-pattern-in-rust.html)"
msgstr ""
#: src\patterns/behavioural/RAII.md:1
msgid "# RAII with guards"
msgstr ""
#: src\patterns/behavioural/RAII.md:5
msgid ""
"[RAII][wikipedia] stands for \"Resource Acquisition is Initialisation\" "
"which is a\n"
"terrible name. The essence of the pattern is that resource initialisation is "
"done\n"
"in the constructor of an object and finalisation in the destructor. This "
"pattern\n"
"is extended in Rust by using a RAII object as a guard of some resource and "
"relying\n"
"on the type system to ensure that access is always mediated by the guard "
"object."
msgstr ""
#: src\patterns/behavioural/RAII.md:13
msgid ""
"Mutex guards are the classic example of this pattern from the std library "
"(this\n"
"is a simplified version of the real implementation):"
msgstr ""
#: src\patterns/behavioural/RAII.md:16
msgid ""
"```rust,ignore\n"
"use std::ops::Deref;\n"
"\n"
"struct Foo {}\n"
"\n"
"struct Mutex<T> {\n"
" // We keep a reference to our data: T here.\n"
" //..\n"
"}\n"
"\n"
"struct MutexGuard<'a, T: 'a> {\n"
" data: &'a T,\n"
" //..\n"
"}\n"
"\n"
"// Locking the mutex is explicit.\n"
"impl<T> Mutex<T> {\n"
" fn lock(&self) -> MutexGuard<T> {\n"
" // Lock the underlying OS mutex.\n"
" //..\n"
"\n"
" // MutexGuard keeps a reference to self\n"
" MutexGuard {\n"
" data: self,\n"
" //..\n"
" }\n"
" }\n"
"}\n"
"\n"
"// Destructor for unlocking the mutex.\n"
"impl<'a, T> Drop for MutexGuard<'a, T> {\n"
" fn drop(&mut self) {\n"
" // Unlock the underlying OS mutex.\n"
" //..\n"
" }\n"
"}\n"
"\n"
"// Implementing Deref means we can treat MutexGuard like a pointer to T.\n"
"impl<'a, T> Deref for MutexGuard<'a, T> {\n"
" type Target = T;\n"
"\n"
" fn deref(&self) -> &T {\n"
" self.data\n"
" }\n"
"}\n"
"\n"
"fn baz(x: Mutex<Foo>) {\n"
" let xx = x.lock();\n"
" xx.foo(); // foo is a method on Foo.\n"
" // The borrow checker ensures we can't store a reference to the "
"underlying\n"
" // Foo which will outlive the guard xx.\n"
"\n"
" // x is unlocked when we exit this function and xx's destructor is "
"executed.\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/RAII.md:74
msgid ""
"Where a resource must be finalised after use, RAII can be used to do this\n"
"finalisation. If it is an error to access that resource after finalisation, "
"then\n"
"this pattern can be used to prevent such errors."
msgstr ""
#: src\patterns/behavioural/RAII.md:80
msgid ""
"Prevents errors where a resource is not finalised and where a resource is "
"used\n"
"after finalisation."
msgstr ""
#: src\patterns/behavioural/RAII.md:85
msgid ""
"RAII is a useful pattern for ensuring resources are properly deallocated or\n"
"finalised. We can make use of the borrow checker in Rust to statically "
"prevent\n"
"errors stemming from using resources after finalisation takes place."
msgstr ""
#: src\patterns/behavioural/RAII.md:89
msgid ""
"The core aim of the borrow checker is to ensure that references to data do "
"not\n"
"outlive that data. The RAII guard pattern works because the guard object\n"
"contains a reference to the underlying resource and only exposes such\n"
"references. Rust ensures that the guard cannot outlive the underlying "
"resource\n"
"and that references to the resource mediated by the guard cannot outlive "
"the\n"
"guard. To see how this works it is helpful to examine the signature of "
"`deref`\n"
"without lifetime elision:"
msgstr ""
#: src\patterns/behavioural/RAII.md:97
msgid ""
"```rust,ignore\n"
"fn deref<'a>(&'a self) -> &'a T {\n"
" //..\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/RAII.md:103
msgid ""
"The returned reference to the resource has the same lifetime as `self` "
"(`'a`).\n"
"The borrow checker therefore ensures that the lifetime of the reference to "
"`T`\n"
"is shorter than the lifetime of `self`."
msgstr ""
#: src\patterns/behavioural/RAII.md:107
msgid ""
"Note that implementing `Deref` is not a core part of this pattern, it only "
"makes\n"
"using the guard object more ergonomic. Implementing a `get` method on the "
"guard\n"
"works just as well."
msgstr ""
#: src\patterns/behavioural/RAII.md:113
msgid "[Finalisation in destructors idiom](../../idioms/dtor-finally.md)"
msgstr ""
#: src\patterns/behavioural/RAII.md:115
msgid ""
"RAII is a common pattern in C++: "
"[cppreference.com](http://en.cppreference.com/w/cpp/language/raii),\n"
"[wikipedia][wikipedia]."
msgstr ""
#: src\patterns/behavioural/RAII.md:120
msgid ""
"[Style guide "
"entry](https://doc.rust-lang.org/1.0.0/style/ownership/raii.html)\n"
"(currently just a placeholder)."
msgstr ""
#: src\patterns/behavioural/strategy.md:1
msgid "# Strategy (aka Policy)"
msgstr ""
#: src\patterns/behavioural/strategy.md:5
msgid ""
"The [Strategy design "
"pattern](https://en.wikipedia.org/wiki/Strategy_pattern)\n"
"is a technique that enables separation of concerns.\n"
"It also allows to decouple software modules through [Dependency "
"Inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle)."
msgstr ""
#: src\patterns/behavioural/strategy.md:9
msgid ""
"The basic idea behind the Strategy pattern is that, given an algorithm "
"solving\n"
"a particular problem, we define only the skeleton of the algorithm at an "
"abstract\n"
"level, and we separate the specific algorithms implementation into "
"different parts."
msgstr ""
#: src\patterns/behavioural/strategy.md:13
msgid ""
"In this way, a client using the algorithm may choose a specific "
"implementation,\n"
"while the general algorithm workflow remains the same. In other words, the "
"abstract\n"
"specification of the class does not depend on the specific implementation of "
"the\n"
"derived class, but specific implementation must adhere to the abstract "
"specification.\n"
"This is why we call it \"Dependency Inversion\"."
msgstr ""
#: src\patterns/behavioural/strategy.md:21
msgid ""
"Imagine we are working on a project that generates reports every month.\n"
"We need the reports to be generated in different formats (strategies), "
"e.g.,\n"
"in `JSON` or `Plain Text` formats.\n"
"But things vary over time, and we don't know what kind of requirement we may "
"get\n"
"in the future. For example, we may need to generate our report in a "
"completely new\n"
"format, or just modify one of the existing formats."
msgstr ""
#: src\patterns/behavioural/strategy.md:30
msgid ""
"In this example our invariants (or abstractions) are `Context`, "
"`Formatter`,\n"
"and `Report`, while `Text` and `Json` are our strategy structs. These "
"strategies\n"
"have to implement the `Formatter` trait."
msgstr ""
#: src\patterns/behavioural/strategy.md:34
msgid ""
"```rust\n"
"use std::collections::HashMap;\n"
"\n"
"type Data = HashMap<String, u32>;\n"
"\n"
"trait Formatter {\n"
" fn format(&self, data: &Data, buf: &mut String);\n"
"}\n"
"\n"
"struct Report;\n"
"\n"
"impl Report {\n"
" // Write should be used but we kept it as String to ignore error "
"handling\n"
" fn generate<T: Formatter>(g: T, s: &mut String) {\n"
" // backend operations...\n"
" let mut data = HashMap::new();\n"
" data.insert(\"one\".to_string(), 1);\n"
" data.insert(\"two\".to_string(), 2);\n"
" // generate report\n"
" g.format(&data, s);\n"
" }\n"
"}\n"
"\n"
"struct Text;\n"
"impl Formatter for Text {\n"
" fn format(&self, data: &Data, buf: &mut String) {\n"
" for (k, v) in data {\n"
" let entry = format!(\"{} {}\\n"
"\", k, v);\n"
" buf.push_str(&entry);\n"
" }\n"
" }\n"
"}\n"
"\n"
"struct Json;\n"
"impl Formatter for Json {\n"
" fn format(&self, data: &Data, buf: &mut String) {\n"
" buf.push('[');\n"
" for (k, v) in data.into_iter() {\n"
" let entry = format!(r#\"{{\"{}\":\"{}\"}}\"#, k, v);\n"
" buf.push_str(&entry);\n"
" buf.push(',');\n"
" }\n"
" if !data.is_empty() {\n"
" buf.pop(); // remove extra , at the end\n"
" }\n"
" buf.push(']');\n"
" }\n"
"}\n"
"\n"
"fn main() {\n"
" let mut s = String::from(\"\");\n"
" Report::generate(Text, &mut s);\n"
" assert!(s.contains(\"one 1\"));\n"
" assert!(s.contains(\"two 2\"));\n"
"\n"
" s.clear(); // reuse the same buffer\n"
" Report::generate(Json, &mut s);\n"
" assert!(s.contains(r#\"{\"one\":\"1\"}\"#));\n"
" assert!(s.contains(r#\"{\"two\":\"2\"}\"#));\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/strategy.md:98
msgid ""
"The main advantage is separation of concerns. For example, in this case "
"`Report`\n"
"does not know anything about specific implementations of `Json` and `Text`,\n"
"whereas the output implementations does not care about how data is "
"preprocessed,\n"
"stored, and fetched. The only thing they have to know is context and a "
"specific\n"
"trait and method to implement, i.e,`Formatter` and `run`."
msgstr ""
#: src\patterns/behavioural/strategy.md:106
msgid ""
"For each strategy there must be implemented at least one module, so number "
"of modules\n"
"increases with number of strategies. If there are many strategies to choose "
"from\n"
"then users have to know how strategies differ from one another."
msgstr ""
#: src\patterns/behavioural/strategy.md:112
msgid ""
"In the previous example all strategies are implemented in a single file.\n"
"Ways of providing different strategies includes:"
msgstr ""
#: src\patterns/behavioural/strategy.md:115
msgid ""
"- All in one file (as shown in this example, similar to being separated as "
"modules)\n"
"- Separated as modules, E.g. `formatter::json` module, `formatter::text` "
"module\n"
"- Use compiler feature flags, E.g. `json` feature, `text` feature\n"
"- Separated as crates, E.g. `json` crate, `text` crate"
msgstr ""
#: src\patterns/behavioural/strategy.md:120
msgid ""
"Serde crate is a good example of the `Strategy` pattern in action. Serde "
"allows\n"
"[full customization](https://serde.rs/custom-serialization.html) of the "
"serialization\n"
"behavior by manually implementing `Serialize` and `Deserialize` traits for "
"our\n"
"type. For example, we could easily swap `serde_json` with `serde_cbor` since "
"they\n"
"expose similar methods. Having this makes the helper crate `serde_transcode` "
"much\n"
"more useful and ergonomic."
msgstr ""
#: src\patterns/behavioural/strategy.md:127
msgid ""
"However, we don't need to use traits in order to design this pattern in Rust."
msgstr ""
#: src\patterns/behavioural/strategy.md:129
msgid ""
"The following toy example demonstrates the idea of the Strategy pattern "
"using Rust\n"
"`closures`:"
msgstr ""
#: src\patterns/behavioural/strategy.md:132
msgid ""
"```rust\n"
"struct Adder;\n"
"impl Adder {\n"
" pub fn add<F>(x: u8, y: u8, f: F) -> u8\n"
" where\n"
" F: Fn(u8, u8) -> u8,\n"
" {\n"
" f(x, y)\n"
" }\n"
"}\n"
"\n"
"fn main() {\n"
" let arith_adder = |x, y| x + y;\n"
" let bool_adder = |x, y| {\n"
" if x == 1 || y == 1 {\n"
" 1\n"
" } else {\n"
" 0\n"
" }\n"
" };\n"
" let custom_adder = |x, y| 2 * x + y;\n"
"\n"
" assert_eq!(9, Adder::add(4, 5, arith_adder));\n"
" assert_eq!(0, Adder::add(0, 0, bool_adder));\n"
" assert_eq!(5, Adder::add(1, 3, custom_adder));\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/strategy.md:160
msgid "In fact, Rust already uses this idea for `Options`'s `map` method:"
msgstr ""
#: src\patterns/behavioural/strategy.md:162
msgid ""
"```rust\n"
"fn main() {\n"
" let val = Some(\"Rust\");\n"
"\n"
" let len_strategy = |s: &str| s.len();\n"
" assert_eq!(4, val.map(len_strategy).unwrap());\n"
"\n"
" let first_byte_strategy = |s: &str| s.bytes().next().unwrap();\n"
" assert_eq!(82, val.map(first_byte_strategy).unwrap());\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/strategy.md:176
msgid ""
"- [Strategy Pattern](https://en.wikipedia.org/wiki/Strategy_pattern)\n"
"- [Dependency "
"Injection](https://en.wikipedia.org/wiki/Dependency_injection)\n"
"- [Policy Based "
"Design](https://en.wikipedia.org/wiki/Modern_C++_Design#Policy-based_design)"
msgstr ""
#: src\patterns/behavioural/visitor.md:1
msgid "# Visitor"
msgstr ""
#: src\patterns/behavioural/visitor.md:5
msgid ""
"A visitor encapsulates an algorithm that operates over a heterogeneous\n"
"collection of objects. It allows multiple different algorithms to be "
"written\n"
"over the same data without having to modify the data (or their primary\n"
"behaviour)."
msgstr ""
#: src\patterns/behavioural/visitor.md:10
msgid ""
"Furthermore, the visitor pattern allows separating the traversal of\n"
"a collection of objects from the operations performed on each object."
msgstr ""
#: src\patterns/behavioural/visitor.md:15
msgid ""
"```rust,ignore\n"
"// The data we will visit\n"
"mod ast {\n"
" pub enum Stmt {\n"
" Expr(Expr),\n"
" Let(Name, Expr),\n"
" }\n"
"\n"
" pub struct Name {\n"
" value: String,\n"
" }\n"
"\n"
" pub enum Expr {\n"
" IntLit(i64),\n"
" Add(Box<Expr>, Box<Expr>),\n"
" Sub(Box<Expr>, Box<Expr>),\n"
" }\n"
"}\n"
"\n"
"// The abstract visitor\n"
"mod visit {\n"
" use ast::*;\n"
"\n"
" pub trait Visitor<T> {\n"
" fn visit_name(&mut self, n: &Name) -> T;\n"
" fn visit_stmt(&mut self, s: &Stmt) -> T;\n"
" fn visit_expr(&mut self, e: &Expr) -> T;\n"
" }\n"
"}\n"
"\n"
"use visit::*;\n"
"use ast::*;\n"
"\n"
"// An example concrete implementation - walks the AST interpreting it as "
"code.\n"
"struct Interpreter;\n"
"impl Visitor<i64> for Interpreter {\n"
" fn visit_name(&mut self, n: &Name) -> i64 { panic!() }\n"
" fn visit_stmt(&mut self, s: &Stmt) -> i64 {\n"
" match *s {\n"
" Stmt::Expr(ref e) => self.visit_expr(e),\n"
" Stmt::Let(..) => unimplemented!(),\n"
" }\n"
" }\n"
"\n"
" fn visit_expr(&mut self, e: &Expr) -> i64 {\n"
" match *e {\n"
" Expr::IntLit(n) => n,\n"
" Expr::Add(ref lhs, ref rhs) => self.visit_expr(lhs) + "
"self.visit_expr(rhs),\n"
" Expr::Sub(ref lhs, ref rhs) => self.visit_expr(lhs) - "
"self.visit_expr(rhs),\n"
" }\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/visitor.md:69
msgid ""
"One could implement further visitors, for example a type checker, without "
"having\n"
"to modify the AST data."
msgstr ""
#: src\patterns/behavioural/visitor.md:74
msgid ""
"The visitor pattern is useful anywhere that you want to apply an algorithm "
"to\n"
"heterogeneous data. If data is homogeneous, you can use an iterator-like "
"pattern.\n"
"Using a visitor object (rather than a functional approach) allows the "
"visitor to\n"
"be stateful and thus communicate information between nodes."
msgstr ""
#: src\patterns/behavioural/visitor.md:81
msgid ""
"It is common for the `visit_*` methods to return void (as opposed to in the\n"
"example). In that case it is possible to factor out the traversal code and "
"share\n"
"it between algorithms (and also to provide noop default methods). In Rust, "
"the\n"
"common way to do this is to provide `walk_*` functions for each datum. For\n"
"example,"
msgstr ""
#: src\patterns/behavioural/visitor.md:87
msgid ""
"```rust,ignore\n"
"pub fn walk_expr(visitor: &mut Visitor, e: &Expr) {\n"
" match *e {\n"
" Expr::IntLit(_) => {},\n"
" Expr::Add(ref lhs, ref rhs) => {\n"
" visitor.visit_expr(lhs);\n"
" visitor.visit_expr(rhs);\n"
" }\n"
" Expr::Sub(ref lhs, ref rhs) => {\n"
" visitor.visit_expr(lhs);\n"
" visitor.visit_expr(rhs);\n"
" }\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\patterns/behavioural/visitor.md:103
msgid ""
"In other languages (e.g., Java) it is common for data to have an `accept` "
"method\n"
"which performs the same duty."
msgstr ""
#: src\patterns/behavioural/visitor.md:108
msgid "The visitor pattern is a common pattern in most OO languages."
msgstr ""
#: src\patterns/behavioural/visitor.md:110
msgid "[Wikipedia article](https://en.wikipedia.org/wiki/Visitor_pattern)"
msgstr ""
#: src\patterns/behavioural/visitor.md:112
msgid ""
"The [fold](../creational/fold.md) pattern is similar to visitor but "
"produces\n"
"a new version of the visited data structure."
msgstr ""
#: src\patterns/creational/intro.md:1
msgid "# Creational Patterns"
msgstr ""
#: src\patterns/creational/intro.md:3
msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Creational_pattern):"
msgstr ""
#: src\patterns/creational/intro.md:5
msgid ""
"> Design patterns that deal with object creation mechanisms, trying to "
"create objects\n"
"> in a manner suitable to the situation. The basic form of object creation "
"could\n"
"> result in design problems or in added complexity to the design. Creational "
"design\n"
"> patterns solve this problem by somehow controlling this object creation."
msgstr ""
#: src\patterns/creational/builder.md:1
msgid "# Builder"
msgstr ""
#: src\patterns/creational/builder.md:5
msgid "Construct an object with calls to a builder helper."
msgstr ""
#: src\patterns/creational/builder.md:9
msgid ""
"```rust\n"
"#[derive(Debug, PartialEq)]\n"
"pub struct Foo {\n"
" // Lots of complicated fields.\n"
" bar: String,\n"
"}\n"
"\n"
"impl Foo {\n"
" // This method will help users to discover the builder\n"
" pub fn builder() -> FooBuilder {\n"
" FooBuilder::default()\n"
" }\n"
"}\n"
"\n"
"#[derive(Default)]\n"
"pub struct FooBuilder {\n"
" // Probably lots of optional fields.\n"
" bar: String,\n"
"}\n"
"\n"
"impl FooBuilder {\n"
" pub fn new(/* ... */) -> FooBuilder {\n"
" // Set the minimally required fields of Foo.\n"
" FooBuilder {\n"
" bar: String::from(\"X\"),\n"
" }\n"
" }\n"
"\n"
" pub fn name(mut self, bar: String) -> FooBuilder {\n"
" // Set the name on the builder itself, and return the builder by "
"value.\n"
" self.bar = bar;\n"
" self\n"
" }\n"
"\n"
" // If we can get away with not consuming the Builder here, that is an\n"
" // advantage. It means we can use the FooBuilder as a template for "
"constructing\n"
" // many Foos.\n"
" pub fn build(self) -> Foo {\n"
" // Create a Foo from the FooBuilder, applying all settings in "
"FooBuilder\n"
" // to Foo.\n"
" Foo { bar: self.bar }\n"
" }\n"
"}\n"
"\n"
"#[test]\n"
"fn builder_test() {\n"
" let foo = Foo {\n"
" bar: String::from(\"Y\"),\n"
" };\n"
" let foo_from_builder: Foo = "
"FooBuilder::new().name(String::from(\"Y\")).build();\n"
" assert_eq!(foo, foo_from_builder);\n"
"}\n"
"```"
msgstr ""
#: src\patterns/creational/builder.md:65
msgid ""
"Useful when you would otherwise require many constructors or where\n"
"construction has side effects."
msgstr ""
#: src\patterns/creational/builder.md:70
msgid "Separates methods for building from other methods."
msgstr ""
#: src\patterns/creational/builder.md:72
msgid "Prevents proliferation of constructors."
msgstr ""
#: src\patterns/creational/builder.md:74
msgid ""
"Can be used for one-liner initialisation as well as more complex "
"construction."
msgstr ""
#: src\patterns/creational/builder.md:78
msgid ""
"More complex than creating a struct object directly, or a simple "
"constructor\n"
"function."
msgstr ""
#: src\patterns/creational/builder.md:83
msgid ""
"This pattern is seen more frequently in Rust (and for simpler objects) than "
"in\n"
"many other languages because Rust lacks overloading. Since you can only have "
"a\n"
"single method with a given name, having multiple constructors is less nice "
"in\n"
"Rust than in C++, Java, or others."
msgstr ""
#: src\patterns/creational/builder.md:88
msgid ""
"This pattern is often used where the builder object is useful in its own "
"right,\n"
"rather than being just a builder. For example, see\n"
"[`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html)\n"
"is a builder for "
"[`Child`](https://doc.rust-lang.org/std/process/struct.Child.html)\n"
"(a process). In these cases, the `T` and `TBuilder` naming pattern is not "
"used."
msgstr ""
#: src\patterns/creational/builder.md:94
msgid ""
"The example takes and returns the builder by value. It is often more "
"ergonomic\n"
"(and more efficient) to take and return the builder as a mutable reference. "
"The\n"
"borrow checker makes this work naturally. This approach has the advantage "
"that\n"
"one can write code like"
msgstr ""
#: src\patterns/creational/builder.md:99
msgid ""
"```rust,ignore\n"
"let mut fb = FooBuilder::new();\n"
"fb.a();\n"
"fb.b();\n"
"let f = fb.build();\n"
"```"
msgstr ""
#: src\patterns/creational/builder.md:106
msgid "as well as the `FooBuilder::new().a().b().build()` style."
msgstr ""
#: src\patterns/creational/builder.md:110
msgid ""
"- [Description in the style "
"guide](https://web.archive.org/web/20210104103100/https://doc.rust-lang.org/1.12.0/style/ownership/builders.html)\n"
"- [derive_builder](https://crates.io/crates/derive_builder), a crate for "
"automatically\n"
" implementing this pattern while avoiding the boilerplate.\n"
"- [Constructor pattern](../../idioms/ctor.md) for when construction is "
"simpler.\n"
"- [Builder pattern "
"(wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern)\n"
"- [Construction of complex "
"values](https://web.archive.org/web/20210104103000/https://rust-lang.github.io/api-guidelines/type-safety.html#c-builder)"
msgstr ""
#: src\patterns/creational/fold.md:1
msgid "# Fold"
msgstr ""
#: src\patterns/creational/fold.md:5
msgid ""
"Run an algorithm over each item in a collection of data to create a new "
"item,\n"
"thus creating a whole new collection."
msgstr ""
#: src\patterns/creational/fold.md:8
msgid ""
"The etymology here is unclear to me. The terms 'fold' and 'folder' are used\n"
"in the Rust compiler, although it appears to me to be more like a map than "
"a\n"
"fold in the usual sense. See the discussion below for more details."
msgstr ""
#: src\patterns/creational/fold.md:14
msgid ""
"```rust,ignore\n"
"// The data we will fold, a simple AST.\n"
"mod ast {\n"
" pub enum Stmt {\n"
" Expr(Box<Expr>),\n"
" Let(Box<Name>, Box<Expr>),\n"
" }\n"
"\n"
" pub struct Name {\n"
" value: String,\n"
" }\n"
"\n"
" pub enum Expr {\n"
" IntLit(i64),\n"
" Add(Box<Expr>, Box<Expr>),\n"
" Sub(Box<Expr>, Box<Expr>),\n"
" }\n"
"}\n"
"\n"
"// The abstract folder\n"
"mod fold {\n"
" use ast::*;\n"
"\n"
" pub trait Folder {\n"
" // A leaf node just returns the node itself. In some cases, we can "
"do this\n"
" // to inner nodes too.\n"
" fn fold_name(&mut self, n: Box<Name>) -> Box<Name> { n }\n"
" // Create a new inner node by folding its children.\n"
" fn fold_stmt(&mut self, s: Box<Stmt>) -> Box<Stmt> {\n"
" match *s {\n"
" Stmt::Expr(e) => Box::new(Stmt::Expr(self.fold_expr(e))),\n"
" Stmt::Let(n, e) => Box::new(Stmt::Let(self.fold_name(n), "
"self.fold_expr(e))),\n"
" }\n"
" }\n"
" fn fold_expr(&mut self, e: Box<Expr>) -> Box<Expr> { ... }\n"
" }\n"
"}\n"
"\n"
"use fold::*;\n"
"use ast::*;\n"
"\n"
"// An example concrete implementation - renames every name to 'foo'.\n"
"struct Renamer;\n"
"impl Folder for Renamer {\n"
" fn fold_name(&mut self, n: Box<Name>) -> Box<Name> {\n"
" Box::new(Name { value: \"foo\".to_owned() })\n"
" }\n"
" // Use the default methods for the other nodes.\n"
"}\n"
"```"
msgstr ""
#: src\patterns/creational/fold.md:65
msgid ""
"The result of running the `Renamer` on an AST is a new AST identical to the "
"old\n"
"one, but with every name changed to `foo`. A real life folder might have "
"some\n"
"state preserved between nodes in the struct itself."
msgstr ""
#: src\patterns/creational/fold.md:69
msgid ""
"A folder can also be defined to map one data structure to a different (but\n"
"usually similar) data structure. For example, we could fold an AST into a "
"HIR\n"
"tree (HIR stands for high-level intermediate representation)."
msgstr ""
#: src\patterns/creational/fold.md:75
msgid ""
"It is common to want to map a data structure by performing some operation "
"on\n"
"each node in the structure. For simple operations on simple data "
"structures,\n"
"this can be done using `Iterator::map`. For more complex operations, "
"perhaps\n"
"where earlier nodes can affect the operation on later nodes, or where "
"iteration\n"
"over the data structure is non-trivial, using the fold pattern is more\n"
"appropriate."
msgstr ""
#: src\patterns/creational/fold.md:82
msgid ""
"Like the visitor pattern, the fold pattern allows us to separate traversal "
"of a\n"
"data structure from the operations performed to each node."
msgstr ""
#: src\patterns/creational/fold.md:87
msgid ""
"Mapping data structures in this fashion is common in functional languages. "
"In OO\n"
"languages, it would be more common to mutate the data structure in place. "
"The\n"
"'functional' approach is common in Rust, mostly due to the preference for\n"
"immutability. Using fresh data structures, rather than mutating old ones, "
"makes\n"
"reasoning about the code easier in most circumstances."
msgstr ""
#: src\patterns/creational/fold.md:93
msgid ""
"The trade-off between efficiency and reusability can be tweaked by changing "
"how\n"
"nodes are accepted by the `fold_*` methods."
msgstr ""
#: src\patterns/creational/fold.md:96
msgid ""
"In the above example we operate on `Box` pointers. Since these own their "
"data\n"
"exclusively, the original copy of the data structure cannot be re-used. On "
"the\n"
"other hand if a node is not changed, reusing it is very efficient."
msgstr ""
#: src\patterns/creational/fold.md:100
msgid ""
"If we were to operate on borrowed references, the original data structure "
"can be\n"
"reused; however, a node must be cloned even if unchanged, which can be\n"
"expensive."
msgstr ""
#: src\patterns/creational/fold.md:104
msgid ""
"Using a reference counted pointer gives the best of both worlds - we can "
"reuse\n"
"the original data structure, and we don't need to clone unchanged nodes. "
"However,\n"
"they are less ergonomic to use and mean that the data structures cannot be\n"
"mutable."
msgstr ""
#: src\patterns/creational/fold.md:111
msgid ""
"Iterators have a `fold` method, however this folds a data structure into a\n"
"value, rather than into a new data structure. An iterator's `map` is more "
"like\n"
"this fold pattern."
msgstr ""
#: src\patterns/creational/fold.md:115
msgid ""
"In other languages, fold is usually used in the sense of Rust's iterators,\n"
"rather than this pattern. Some functional languages have powerful constructs "
"for\n"
"performing flexible maps over data structures."
msgstr ""
#: src\patterns/creational/fold.md:119
msgid ""
"The [visitor](../behavioural/visitor.md) pattern is closely related to "
"fold.\n"
"They share the concept of walking a data structure performing an operation "
"on\n"
"each node. However, the visitor does not create a new data structure nor "
"consume\n"
"the old one."
msgstr ""
#: src\patterns/structural/intro.md:1
msgid "# Structural Patterns"
msgstr ""
#: src\patterns/structural/intro.md:3
msgid "From [Wikipedia](https://en.wikipedia.org/wiki/Structural_pattern):"
msgstr ""
#: src\patterns/structural/intro.md:5
msgid ""
"> Design patterns that ease the design by identifying a simple way to "
"realize relationships\n"
"> among entities."
msgstr ""
#: src\patterns/structural/compose-structs.md:1
msgid "# Compose structs together for better borrowing"
msgstr ""
#: src\patterns/structural/compose-structs.md:3
msgid "TODO - this is not a very snappy name"
msgstr ""
#: src\patterns/structural/compose-structs.md:7
msgid ""
"Sometimes a large struct will cause issues with the borrow checker - "
"although\n"
"fields can be borrowed independently, sometimes the whole struct ends up "
"being\n"
"used at once, preventing other uses. A solution might be to decompose the "
"struct\n"
"into several smaller structs. Then compose these together into the original\n"
"struct. Then each struct can be borrowed separately and have more flexible\n"
"behaviour."
msgstr ""
#: src\patterns/structural/compose-structs.md:14
msgid ""
"This will often lead to a better design in other ways: applying this design\n"
"pattern often reveals smaller units of functionality."
msgstr ""
#: src\patterns/structural/compose-structs.md:19
msgid ""
"Here is a contrived example of where the borrow checker foils us in our plan "
"to\n"
"use a struct:"
msgstr ""
#: src\patterns/structural/compose-structs.md:22
msgid ""
"```rust\n"
"struct A {\n"
" f1: u32,\n"
" f2: u32,\n"
" f3: u32,\n"
"}\n"
"\n"
"fn foo(a: &mut A) -> &u32 { &a.f2 }\n"
"fn bar(a: &mut A) -> u32 { a.f1 + a.f3 }\n"
"\n"
"fn baz(a: &mut A) {\n"
" // The later usage of x causes a to be borrowed for the rest of the "
"function.\n"
" let x = foo(a);\n"
" // Borrow checker error:\n"
" // let y = bar(a); // ~ ERROR: cannot borrow `*a` as mutable more than "
"once\n"
" // at a time\n"
" println!(\"{}\", x);\n"
"}\n"
"```"
msgstr ""
#: src\patterns/structural/compose-structs.md:42
msgid ""
"We can apply this design pattern and refactor `A` into two smaller structs, "
"thus\n"
"solving the borrow checking issue:"
msgstr ""
#: src\patterns/structural/compose-structs.md:45
msgid ""
"```rust\n"
"// A is now composed of two structs - B and C.\n"
"struct A {\n"
" b: B,\n"
" c: C,\n"
"}\n"
"struct B {\n"
" f2: u32,\n"
"}\n"
"struct C {\n"
" f1: u32,\n"
" f3: u32,\n"
"}\n"
"\n"
"// These functions take a B or C, rather than A.\n"
"fn foo(b: &mut B) -> &u32 { &b.f2 }\n"
"fn bar(c: &mut C) -> u32 { c.f1 + c.f3 }\n"
"\n"
"fn baz(a: &mut A) {\n"
" let x = foo(&mut a.b);\n"
" // Now it's OK!\n"
" let y = bar(&mut a.c);\n"
" println!(\"{}\", x);\n"
"}\n"
"```"
msgstr ""
#: src\patterns/structural/compose-structs.md:73
msgid "TODO Why and where you should use the pattern"
msgstr ""
#: src\patterns/structural/compose-structs.md:77
msgid "Lets you work around limitations in the borrow checker."
msgstr ""
#: src\patterns/structural/compose-structs.md:79
msgid "Often produces a better design."
msgstr ""
#: src\patterns/structural/compose-structs.md:83
msgid "Leads to more verbose code."
msgstr ""
#: src\patterns/structural/compose-structs.md:85
msgid ""
"Sometimes, the smaller structs are not good abstractions, and so we end up "
"with\n"
"a worse design. That is probably a 'code smell', indicating that the "
"program\n"
"should be refactored in some way."
msgstr ""
#: src\patterns/structural/compose-structs.md:91
msgid ""
"This pattern is not required in languages that don't have a borrow checker, "
"so\n"
"in that sense is unique to Rust. However, making smaller units of "
"functionality\n"
"often leads to cleaner code: a widely acknowledged principle of software\n"
"engineering, independent of the language."
msgstr ""
#: src\patterns/structural/compose-structs.md:96
msgid ""
"This pattern relies on Rust's borrow checker to be able to borrow fields\n"
"independently of each other. In the example, the borrow checker knows that "
"`a.b`\n"
"and `a.c` are distinct and can be borrowed independently, it does not try "
"to\n"
"borrow all of `a`, which would make this pattern useless."
msgstr ""
#: src\patterns/structural/small-crates.md:1
msgid "# Prefer small crates"
msgstr ""
#: src\patterns/structural/small-crates.md:5
msgid "Prefer small crates that do one thing well."
msgstr ""
#: src\patterns/structural/small-crates.md:7
msgid ""
"Cargo and crates.io make it easy to add third-party libraries, much more so "
"than\n"
"in say C or C++. Moreover, since packages on crates.io cannot be edited or "
"removed\n"
"after publication, any build that works now should continue to work in the "
"future.\n"
"We should take advantage of this tooling, and use smaller, more fine-grained "
"dependencies."
msgstr ""
#: src\patterns/structural/small-crates.md:14
msgid ""
"- Small crates are easier to understand, and encourage more modular code.\n"
"- Crates allow for re-using code between projects.\n"
" For example, the `url` crate was developed as part of the Servo browser "
"engine,\n"
" but has since found wide use outside the project.\n"
"- Since the compilation unit\n"
" of Rust is the crate, splitting a project into multiple crates can allow "
"more of\n"
" the code to be built in parallel."
msgstr ""
#: src\patterns/structural/small-crates.md:24
msgid ""
"- This can lead to \"dependency hell\", when a project depends on multiple "
"conflicting\n"
" versions of a crate at the same time. For example, the `url` crate has "
"both versions\n"
" 1.0 and 0.5. Since the `Url` from `url:1.0` and the `Url` from `url:0.5` "
"are\n"
" different types, an HTTP client that uses `url:0.5` would not accept `Url` "
"values\n"
" from a web scraper that uses `url:1.0`.\n"
"- Packages on crates.io are not curated. A crate may be poorly written, "
"have\n"
" unhelpful documentation, or be outright malicious.\n"
"- Two small crates may be less optimized than one large one, since the "
"compiler\n"
" does not perform link-time optimization (LTO) by default."
msgstr ""
#: src\patterns/structural/small-crates.md:36
msgid ""
"The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides "
"functions\n"
"for converting `&T` to `&[T]`."
msgstr ""
#: src\patterns/structural/small-crates.md:39
msgid ""
"The [`url`](https://crates.io/crates/url) crate provides tools for working "
"with\n"
"URLs."
msgstr ""
#: src\patterns/structural/small-crates.md:42
msgid ""
"The [`num_cpus`](https://crates.io/crates/num_cpus) crate provides a "
"function to\n"
"query the number of CPUs on a machine."
msgstr ""
#: src\patterns/structural/small-crates.md:47
msgid "- [crates.io: The Rust community crate host](https://crates.io/)"
msgstr ""
#: src\patterns/structural/unsafe-mods.md:1
msgid "# Contain unsafety in small modules"
msgstr ""
#: src\patterns/structural/unsafe-mods.md:5
msgid ""
"If you have `unsafe` code, create the smallest possible module that can "
"uphold\n"
"the needed invariants to build a minimal safe interface upon the unsafety. "
"Embed\n"
"this into a larger module that contains only safe code and presents an "
"ergonomic\n"
"interface. Note that the outer module can contain unsafe functions and "
"methods\n"
"that call directly into the unsafe code. Users may use this to gain speed "
"benefits."
msgstr ""
#: src\patterns/structural/unsafe-mods.md:13
msgid ""
"- This restricts the unsafe code that must be audited\n"
"- Writing the outer module is much easier, since you can count on the "
"guarantees\n"
" of the inner module"
msgstr ""
#: src\patterns/structural/unsafe-mods.md:19
msgid ""
"- Sometimes, it may be hard to find a suitable interface.\n"
"- The abstraction may introduce inefficiencies."
msgstr ""
#: src\patterns/structural/unsafe-mods.md:24
msgid ""
"- The [`toolshed`](https://docs.rs/toolshed) crate contains its unsafe "
"operations\n"
" in submodules, presenting a safe interface to users.\n"
"- `std`'s `String` class is a wrapper over `Vec<u8>` with the added "
"invariant\n"
" that the contents must be valid UTF-8. The operations on `String` ensure "
"this\n"
" behavior.\n"
" However, users have the option of using an `unsafe` method to create a "
"`String`,\n"
" in which case the onus is on them to guarantee the validity of the "
"contents."
msgstr ""
#: src\patterns/structural/unsafe-mods.md:34
msgid ""
"- [Ralf Jung's Blog about invariants in unsafe "
"code](https://www.ralfj.de/blog/2018/08/22/two-kinds-of-invariants.html)"
msgstr ""
#: src\patterns/ffi/intro.md:1
msgid "# FFI Patterns"
msgstr ""
#: src\patterns/ffi/intro.md:3
msgid ""
"Writing FFI code is an entire course in itself.\n"
"However, there are several idioms here that can act as pointers, and avoid "
"traps\n"
"for inexperienced users of unsafe Rust."
msgstr ""
#: src\patterns/ffi/intro.md:7
msgid "This section contains design patterns that may be useful when doing FFI."
msgstr ""
#: src\patterns/ffi/intro.md:9
msgid ""
"1. [Object-Based API](./export.md) design that has good memory safety "
"characteristics,\n"
" and a clean boundary of what is safe and what is unsafe\n"
"\n"
"2. [Type Consolidation into Wrappers](./wrappers.md) - group multiple Rust "
"types\n"
" together into an opaque \"object\""
msgstr ""
#: src\patterns/ffi/export.md:1
msgid "# Object-Based APIs"
msgstr ""
#: src\patterns/ffi/export.md:5
msgid ""
"When designing APIs in Rust which are exposed to other languages, there are "
"some\n"
"important design principles which are contrary to normal Rust API design:"
msgstr ""
#: src\patterns/ffi/export.md:8
msgid ""
"1. All Encapsulated types should be _owned_ by Rust, _managed_ by the user,\n"
" and _opaque_.\n"
"2. All Transactional data types should be _owned_ by the user, and "
"_transparent_.\n"
"3. All library behavior should be functions acting upon Encapsulated types.\n"
"4. All library behavior should be encapsulated into types not based on "
"structure,\n"
" but _provenance/lifetime_."
msgstr ""
#: src\patterns/ffi/export.md:17
msgid ""
"Rust has built-in FFI support to other languages.\n"
"It does this by providing a way for crate authors to provide C-compatible "
"APIs\n"
"through different ABIs (though that is unimportant to this practice)."
msgstr ""
#: src\patterns/ffi/export.md:21
msgid ""
"Well-designed Rust FFI follows C API design principles, while compromising "
"the\n"
"design in Rust as little as possible. There are three goals with any foreign "
"API:"
msgstr ""
#: src\patterns/ffi/export.md:24
msgid ""
"1. Make it easy to use in the target language.\n"
"2. Avoid the API dictating internal unsafety on the Rust side as much as "
"possible.\n"
"3. Keep the potential for memory unsafety and Rust `undefined behaviour` as "
"small\n"
" as possible."
msgstr ""
#: src\patterns/ffi/export.md:29
msgid ""
"Rust code must trust the memory safety of the foreign language beyond a "
"certain\n"
"point. However, every bit of `unsafe` code on the Rust side is an "
"opportunity for\n"
"bugs, or to exacerbate `undefined behaviour`."
msgstr ""
#: src\patterns/ffi/export.md:33
msgid ""
"For example, if a pointer provenance is wrong, that may be a segfault due "
"to\n"
"invalid memory access. But if it is manipulated by unsafe code, it could "
"become\n"
"full-blown heap corruption."
msgstr ""
#: src\patterns/ffi/export.md:37
msgid ""
"The Object-Based API design allows for writing shims that have good memory "
"safety\n"
"characteristics, and a clean boundary of what is safe and what is `unsafe`."
msgstr ""
#: src\patterns/ffi/export.md:42
msgid ""
"The POSIX standard defines the API to access an on-file database, known as "
"[DBM](https://web.archive.org/web/20210105035602/https://www.mankier.com/0p/ndbm.h).\n"
"It is an excellent example of an \"object-based\" API."
msgstr ""
#: src\patterns/ffi/export.md:45
msgid ""
"Here is the definition in C, which hopefully should be easy to read for "
"those\n"
"involved in FFI. The commentary below should help explain it for those who\n"
"miss the subtleties."
msgstr ""
#: src\patterns/ffi/export.md:49
msgid ""
"```C\n"
"struct DBM;\n"
"typedef struct { void *dptr, size_t dsize } datum;\n"
"\n"
"int dbm_clearerr(DBM *);\n"
"void dbm_close(DBM *);\n"
"int dbm_delete(DBM *, datum);\n"
"int dbm_error(DBM *);\n"
"datum dbm_fetch(DBM *, datum);\n"
"datum dbm_firstkey(DBM *);\n"
"datum dbm_nextkey(DBM *);\n"
"DBM *dbm_open(const char *, int, mode_t);\n"
"int dbm_store(DBM *, datum, datum, int);\n"
"```"
msgstr ""
#: src\patterns/ffi/export.md:64
msgid "This API defines two types: `DBM` and `datum`."
msgstr ""
#: src\patterns/ffi/export.md:66
msgid ""
"The `DBM` type was called an \"encapsulated\" type above.\n"
"It is designed to contain internal state, and acts as an entry point for "
"the\n"
"library's behavior."
msgstr ""
#: src\patterns/ffi/export.md:70
msgid ""
"It is completely opaque to the user, who cannot create a `DBM` themselves "
"since\n"
"they don't know its size or layout. Instead, they must call `dbm_open`, and "
"that\n"
"only gives them _a pointer to one_."
msgstr ""
#: src\patterns/ffi/export.md:74
msgid ""
"This means all `DBM`s are \"owned\" by the library in a Rust sense.\n"
"The internal state of unknown size is kept in memory controlled by the "
"library,\n"
"not the user. The user can only manage its life cycle with `open` and "
"`close`,\n"
"and perform operations on it with the other functions."
msgstr ""
#: src\patterns/ffi/export.md:79
msgid ""
"The `datum` type was called a \"transactional\" type above.\n"
"It is designed to facilitate the exchange of information between the library "
"and\n"
"its user."
msgstr ""
#: src\patterns/ffi/export.md:83
msgid ""
"The database is designed to store \"unstructured data\", with no pre-defined "
"length\n"
"or meaning. As a result, the `datum` is the C equivalent of a Rust slice: a "
"bunch\n"
"of bytes, and a count of how many there are. The main difference is that "
"there is\n"
"no type information, which is what `void` indicates."
msgstr ""
#: src\patterns/ffi/export.md:88
msgid ""
"Keep in mind that this header is written from the library's point of view.\n"
"The user likely has some type they are using, which has a known size.\n"
"But the library does not care, and by the rules of C casting, any type "
"behind a\n"
"pointer can be cast to `void`."
msgstr ""
#: src\patterns/ffi/export.md:93
msgid ""
"As noted earlier, this type is _transparent_ to the user. But also, this "
"type is\n"
"_owned_ by the user.\n"
"This has subtle ramifications, due to that pointer inside it.\n"
"The question is, who owns the memory that pointer points to?"
msgstr ""
#: src\patterns/ffi/export.md:98
msgid ""
"The answer for best memory safety is, \"the user\".\n"
"But in cases such as retrieving a value, the user does not know how to "
"allocate\n"
"it correctly (since they don't know how long the value is). In this case, "
"the library\n"
"code is expected to use the heap that the user has access to -- such as the "
"C library\n"
"`malloc` and `free` -- and then _transfer ownership_ in the Rust sense."
msgstr ""
#: src\patterns/ffi/export.md:104
msgid ""
"This may all seem speculative, but this is what a pointer means in C.\n"
"It means the same thing as Rust: \"user defined lifetime.\"\n"
"The user of the library needs to read the documentation in order to use it "
"correctly.\n"
"That said, there are some decisions that have fewer or greater consequences "
"if users\n"
"do it wrong. Minimizing those are what this best practice is about, and the "
"key\n"
"is to _transfer ownership of everything that is transparent_."
msgstr ""
#: src\patterns/ffi/export.md:113
msgid ""
"This minimizes the number of memory safety guarantees the user must uphold "
"to a\n"
"relatively small number:"
msgstr ""
#: src\patterns/ffi/export.md:116
msgid ""
"1. Do not call any function with a pointer not returned by `dbm_open` "
"(invalid\n"
" access or corruption).\n"
"2. Do not call any function on a pointer after close (use after free).\n"
"3. The `dptr` on any `datum` must be `NULL`, or point to a valid slice of "
"memory\n"
" at the advertised length."
msgstr ""
#: src\patterns/ffi/export.md:122
msgid ""
"In addition, it avoids a lot of pointer provenance issues.\n"
"To understand why, let us consider an alternative in some depth: key "
"iteration."
msgstr ""
#: src\patterns/ffi/export.md:125
msgid ""
"Rust is well known for its iterators.\n"
"When implementing one, the programmer makes a separate type with a bounded "
"lifetime\n"
"to its owner, and implements the `Iterator` trait."
msgstr ""
#: src\patterns/ffi/export.md:129
msgid "Here is how iteration would be done in Rust for `DBM`:"
msgstr ""
#: src\patterns/ffi/export.md:131
msgid ""
"```rust,ignore\n"
"struct Dbm { ... }\n"
"\n"
"impl Dbm {\n"
" /* ... */\n"
" pub fn keys<'it>(&'it self) -> DbmKeysIter<'it> { ... }\n"
" /* ... */\n"
"}\n"
"\n"
"struct DbmKeysIter<'it> {\n"
" owner: &'it Dbm,\n"
"}\n"
"\n"
"impl<'it> Iterator for DbmKeysIter<'it> { ... }\n"
"```"
msgstr ""
#: src\patterns/ffi/export.md:147
msgid ""
"This is clean, idiomatic, and safe. thanks to Rust's guarantees.\n"
"However, consider what a straightforward API translation would look like:"
msgstr ""
#: src\patterns/ffi/export.md:150
msgid ""
"```rust,ignore\n"
"#[no_mangle]\n"
"pub extern \"C\" fn dbm_iter_new(owner: *const Dbm) -> *mut DbmKeysIter {\n"
" // THIS API IS A BAD IDEA! For real applications, use object-based "
"design instead.\n"
"}\n"
"#[no_mangle]\n"
"pub extern \"C\" fn dbm_iter_next(\n"
" iter: *mut DbmKeysIter,\n"
" key_out: *const datum\n"
") -> libc::c_int {\n"
" // THIS API IS A BAD IDEA! For real applications, use object-based "
"design instead.\n"
"}\n"
"#[no_mangle]\n"
"pub extern \"C\" fn dbm_iter_del(*mut DbmKeysIter) {\n"
" // THIS API IS A BAD IDEA! For real applications, use object-based "
"design instead.\n"
"}\n"
"```"
msgstr ""
#: src\patterns/ffi/export.md:168
msgid ""
"This API loses a key piece of information: the lifetime of the iterator must "
"not\n"
"exceed the lifetime of the `Dbm` object that owns it. A user of the library "
"could\n"
"use it in a way which causes the iterator to outlive the data it is "
"iterating on,\n"
"resulting in reading uninitialized memory."
msgstr ""
#: src\patterns/ffi/export.md:173
msgid ""
"This example written in C contains a bug that will be explained afterwards:"
msgstr ""
#: src\patterns/ffi/export.md:175
msgid ""
"```C\n"
"int count_key_sizes(DBM *db) {\n"
" // DO NOT USE THIS FUNCTION. IT HAS A SUBTLE BUT SERIOUS BUG!\n"
" datum key;\n"
" int len = 0;\n"
"\n"
" if (!dbm_iter_new(db)) {\n"
" dbm_close(db);\n"
" return -1;\n"
" }\n"
"\n"
" int l;\n"
" while ((l = dbm_iter_next(owner, &key)) >= 0) { // an error is indicated "
"by -1\n"
" free(key.dptr);\n"
" len += key.dsize;\n"
" if (l == 0) { // end of the iterator\n"
" dbm_close(owner);\n"
" }\n"
" }\n"
" if l >= 0 {\n"
" return -1;\n"
" } else {\n"
" return len;\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\patterns/ffi/export.md:202
msgid ""
"This bug is a classic. Here's what happens when the iterator returns the\n"
"end-of-iteration marker:"
msgstr ""
#: src\patterns/ffi/export.md:205
msgid ""
"1. The loop condition sets `l` to zero, and enters the loop because `0 >= "
"0`.\n"
"2. The length is incremented, in this case by zero.\n"
"3. The if statement is true, so the database is closed. There should be a "
"break\n"
" statement here.\n"
"4. The loop condition executes again, causing a `next` call on the closed "
"object."
msgstr ""
#: src\patterns/ffi/export.md:211
msgid ""
"The worst part about this bug?\n"
"If the Rust implementation was careful, this code will work most of the "
"time!\n"
"If the memory for the `Dbm` object is not immediately reused, an internal "
"check\n"
"will almost certainly fail, resulting in the iterator returning a `-1` "
"indicating\n"
"an error. But occasionally, it will cause a segmentation fault, or even "
"worse,\n"
"nonsensical memory corruption!"
msgstr ""
#: src\patterns/ffi/export.md:218
msgid ""
"None of this can be avoided by Rust.\n"
"From its perspective, it put those objects on its heap, returned pointers to "
"them,\n"
"and gave up control of their lifetimes. The C code simply must \"play nice\"."
msgstr ""
#: src\patterns/ffi/export.md:222
msgid ""
"The programmer must read and understand the API documentation.\n"
"While some consider that par for the course in C, a good API design can "
"mitigate\n"
"this risk. The POSIX API for `DBM` did this by _consolidating the ownership_ "
"of\n"
"the iterator with its parent:"
msgstr ""
#: src\patterns/ffi/export.md:227
msgid ""
"```C\n"
"datum dbm_firstkey(DBM *);\n"
"datum dbm_nextkey(DBM *);\n"
"```"
msgstr ""
#: src\patterns/ffi/export.md:232
msgid ""
"Thus, all the lifetimes were bound together, and such unsafety was prevented."
msgstr ""
#: src\patterns/ffi/export.md:236
msgid ""
"However, this design choice also has a number of drawbacks, which should be\n"
"considered as well."
msgstr ""
#: src\patterns/ffi/export.md:239
msgid ""
"First, the API itself becomes less expressive.\n"
"With POSIX DBM, there is only one iterator per object, and every call "
"changes\n"
"its state. This is much more restrictive than iterators in almost any "
"language,\n"
"even though it is safe. Perhaps with other related objects, whose lifetimes "
"are\n"
"less hierarchical, this limitation is more of a cost than the safety."
msgstr ""
#: src\patterns/ffi/export.md:245
msgid ""
"Second, depending on the relationships of the API's parts, significant "
"design effort\n"
"may be involved. Many of the easier design points have other patterns "
"associated\n"
"with them:"
msgstr ""
#: src\patterns/ffi/export.md:249
msgid ""
"- [Wrapper Type Consolidation](./wrappers.md) groups multiple Rust types "
"together\n"
" into an opaque \"object\"\n"
"\n"
"- [FFI Error Passing](../../idioms/ffi/errors.md) explains error handling "
"with integer\n"
" codes and sentinel return values (such as `NULL` pointers)\n"
"\n"
"- [Accepting Foreign Strings](../../idioms/ffi/accepting-strings.md) allows "
"accepting\n"
" strings with minimal unsafe code, and is easier to get right than\n"
" [Passing Strings to FFI](../../idioms/ffi/passing-strings.md)"
msgstr ""
#: src\patterns/ffi/export.md:259
msgid ""
"However, not every API can be done this way.\n"
"It is up to the best judgement of the programmer as to who their audience is."
msgstr ""
#: src\patterns/ffi/wrappers.md:1
msgid "# Type Consolidation into Wrappers"
msgstr ""
#: src\patterns/ffi/wrappers.md:5
msgid ""
"This pattern is designed to allow gracefully handling multiple related "
"types,\n"
"while minimizing the surface area for memory unsafety."
msgstr ""
#: src\patterns/ffi/wrappers.md:8
msgid ""
"One of the cornerstones of Rust's aliasing rules is lifetimes.\n"
"This ensures that many patterns of access between types can be memory safe,\n"
"data race safety included."
msgstr ""
#: src\patterns/ffi/wrappers.md:12
msgid ""
"However, when Rust types are exported to other languages, they are usually "
"transformed\n"
"into pointers. In Rust, a pointer means \"the user manages the lifetime of "
"the pointee.\"\n"
"It is their responsibility to avoid memory unsafety."
msgstr ""
#: src\patterns/ffi/wrappers.md:16
msgid ""
"Some level of trust in the user code is thus required, notably around "
"use-after-free\n"
"which Rust can do nothing about. However, some API designs place higher "
"burdens\n"
"than others on the code written in the other language."
msgstr ""
#: src\patterns/ffi/wrappers.md:20
msgid ""
"The lowest risk API is the \"consolidated wrapper\", where all possible "
"interactions\n"
"with an object are folded into a \"wrapper type\", while keeping the Rust "
"API clean."
msgstr ""
#: src\patterns/ffi/wrappers.md:25
msgid ""
"To understand this, let us look at a classic example of an API to export: "
"iteration\n"
"through a collection."
msgstr ""
#: src\patterns/ffi/wrappers.md:28
msgid "That API looks like this:"
msgstr ""
#: src\patterns/ffi/wrappers.md:30
msgid ""
"1. The iterator is initialized with `first_key`.\n"
"2. Each call to `next_key` will advance the iterator.\n"
"3. Calls to `next_key` if the iterator is at the end will do nothing.\n"
"4. As noted above, the iterator is \"wrapped into\" the collection (unlike "
"the native\n"
" Rust API)."
msgstr ""
#: src\patterns/ffi/wrappers.md:36
msgid ""
"If the iterator implements `nth()` efficiently, then it is possible to make "
"it\n"
"ephemeral to each function call:"
msgstr ""
#: src\patterns/ffi/wrappers.md:39
msgid ""
"```rust,ignore\n"
"struct MySetWrapper {\n"
" myset: MySet,\n"
" iter_next: usize,\n"
"}\n"
"\n"
"impl MySetWrapper {\n"
" pub fn first_key(&mut self) -> Option<&Key> {\n"
" self.iter_next = 0;\n"
" self.next_key()\n"
" }\n"
" pub fn next_key(&mut self) -> Option<&Key> {\n"
" if let Some(next) = self.myset.keys().nth(self.iter_next) {\n"
" self.iter_next += 1;\n"
" Some(next)\n"
" } else {\n"
" None\n"
" }\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\patterns/ffi/wrappers.md:61
msgid "As a result, the wrapper is simple and contains no `unsafe` code."
msgstr ""
#: src\patterns/ffi/wrappers.md:65
msgid ""
"This makes APIs safer to use, avoiding issues with lifetimes between types.\n"
"See [Object-Based APIs](./export.md) for more on the advantages and "
"pitfalls\n"
"this avoids."
msgstr ""
#: src\patterns/ffi/wrappers.md:71
msgid ""
"Often, wrapping types is quite difficult, and sometimes a Rust API "
"compromise\n"
"would make things easier."
msgstr ""
#: src\patterns/ffi/wrappers.md:74
msgid ""
"As an example, consider an iterator which does not efficiently implement "
"`nth()`.\n"
"It would definitely be worth putting in special logic to make the object "
"handle\n"
"iteration internally, or to support a different access pattern efficiently "
"that\n"
"only the Foreign Function API will use."
msgstr ""
#: src\patterns/ffi/wrappers.md:79
msgid "### Trying to Wrap Iterators (and Failing)"
msgstr ""
#: src\patterns/ffi/wrappers.md:81
msgid ""
"To wrap any type of iterator into the API correctly, the wrapper would need "
"to\n"
"do what a C version of the code would do: erase the lifetime of the "
"iterator,\n"
"and manage it manually."
msgstr ""
#: src\patterns/ffi/wrappers.md:85
msgid "Suffice it to say, this is _incredibly_ difficult."
msgstr ""
#: src\patterns/ffi/wrappers.md:87
msgid "Here is an illustration of just _one_ pitfall."
msgstr ""
#: src\patterns/ffi/wrappers.md:89
msgid "A first version of `MySetWrapper` would look like this:"
msgstr ""
#: src\patterns/ffi/wrappers.md:91
msgid ""
"```rust,ignore\n"
"struct MySetWrapper {\n"
" myset: MySet,\n"
" iter_next: usize,\n"
" // created from a transmuted Box<KeysIter + 'self>\n"
" iterator: Option<NonNull<KeysIter<'static>>>,\n"
"}\n"
"```"
msgstr ""
#: src\patterns/ffi/wrappers.md:100
msgid ""
"With `transmute` being used to extend a lifetime, and a pointer to hide it,\n"
"it's ugly already. But it gets even worse: _any other operation can cause\n"
"Rust `undefined behaviour`_."
msgstr ""
#: src\patterns/ffi/wrappers.md:104
msgid ""
"Consider that the `MySet` in the wrapper could be manipulated by other\n"
"functions during iteration, such as storing a new value to the key it was\n"
"iterating over. The API doesn't discourage this, and in fact some similar C\n"
"libraries expect it."
msgstr ""
#: src\patterns/ffi/wrappers.md:109
msgid "A simple implementation of `myset_store` would be:"
msgstr ""
#: src\patterns/ffi/wrappers.md:111
msgid ""
"```rust,ignore\n"
"pub mod unsafe_module {\n"
"\n"
" // other module content\n"
"\n"
" pub fn myset_store(\n"
" myset: *mut MySetWrapper,\n"
" key: datum,\n"
" value: datum) -> libc::c_int {\n"
"\n"
" // DO NOT USE THIS CODE. IT IS UNSAFE TO DEMONSTRATE A PROLBEM.\n"
"\n"
" let myset: &mut MySet = unsafe { // SAFETY: whoops, UB occurs in "
"here!\n"
" &mut (*myset).myset\n"
" };\n"
"\n"
" /* ...check and cast key and value data... */\n"
"\n"
" match myset.store(casted_key, casted_value) {\n"
" Ok(_) => 0,\n"
" Err(e) => e.into()\n"
" }\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\patterns/ffi/wrappers.md:137
msgid ""
"If the iterator exists when this function is called, we have violated one of "
"Rust's\n"
"aliasing rules. According to Rust, the mutable reference in this block must "
"have\n"
"_exclusive_ access to the object. If the iterator simply exists, it's not "
"exclusive,\n"
"so we have `undefined behaviour`! "
msgstr ""
#: src\patterns/ffi/wrappers.md:142
msgid ""
"To avoid this, we must have a way of ensuring that mutable reference really "
"is exclusive.\n"
"That basically means clearing out the iterator's shared reference while it "
"exists,\n"
"and then reconstructing it. In most cases, that will still be less efficient "
"than\n"
"the C version."
msgstr ""
#: src\patterns/ffi/wrappers.md:147
msgid ""
"Some may ask: how can C do this more efficiently?\n"
"The answer is, it cheats. Rust's aliasing rules are the problem, and C "
"simply ignores\n"
"them for its pointers. In exchange, it is common to see code that is "
"declared\n"
"in the manual as \"not thread safe\" under some or all circumstances. In "
"fact,\n"
"the [GNU C "
"library](https://manpages.debian.org/buster/manpages/attributes.7.en.html)\n"
"has an entire lexicon dedicated to concurrent behavior!"
msgstr ""
#: src\patterns/ffi/wrappers.md:154
msgid ""
"Rust would rather make everything memory safe all the time, for both safety "
"and\n"
"optimizations that C code cannot attain. Being denied access to certain "
"shortcuts\n"
"is the price Rust programmers need to pay."
msgstr ""
#: src\patterns/ffi/wrappers.md:158
msgid ""
"For the C programmers out there scratching their heads, the iterator need\n"
"not be read _during_ this code cause the UB. The exclusivity rule also "
"enables\n"
"compiler optimizations which may cause inconsistent observations by the "
"iterator's\n"
"shared reference (e.g. stack spills or reordering instructions for "
"efficiency).\n"
"These observations may happen _any time after_ the mutable reference is "
"created."
msgstr ""
#: src\anti_patterns/index.md:1
msgid "# Anti-patterns"
msgstr ""
#: src\anti_patterns/index.md:3
msgid ""
"An [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern) is a solution "
"to\n"
"a \"recurring problem that is usually ineffective and risks being highly\n"
"counterproductive\". Just as valuable as knowing how to solve a problem, is\n"
"knowing how _not_ to solve it. Anti-patterns give us great counter-examples "
"to\n"
"consider relative to design patterns. Anti-patterns are not confined to "
"code.\n"
"For example, a process can be an anti-pattern, too."
msgstr ""
#: src\anti_patterns/borrow_clone.md:1
msgid "# Clone to satisfy the borrow checker"
msgstr ""
#: src\anti_patterns/borrow_clone.md:5
msgid ""
"The borrow checker prevents Rust users from developing otherwise unsafe code "
"by\n"
"ensuring that either: only one mutable reference exists, or potentially many "
"but\n"
"all immutable references exist. If the code written does not hold true to "
"these\n"
"conditions, this anti-pattern arises when the developer resolves the "
"compiler\n"
"error by cloning the variable."
msgstr ""
#: src\anti_patterns/borrow_clone.md:13
msgid ""
"```rust\n"
"// define any variable\n"
"let mut x = 5;\n"
"\n"
"// Borrow `x` -- but clone it first\n"
"let y = &mut (x.clone());\n"
"\n"
"// without the x.clone() two lines prior, this line would fail on compile "
"as\n"
"// x has been borrowed\n"
"// thanks to x.clone(), x was never borrowed, and this line will run.\n"
"println!(\"{}\", x);\n"
"\n"
"// perform some action on the borrow to prevent rust from optimizing this\n"
"//out of existence\n"
"*y += 1;\n"
"```"
msgstr ""
#: src\anti_patterns/borrow_clone.md:32
msgid ""
"It is tempting, particularly for beginners, to use this pattern to resolve\n"
"confusing issues with the borrow checker. However, there are serious\n"
"consequences. Using `.clone()` causes a copy of the data to be made. Any "
"changes\n"
"between the two are not synchronized -- as if two completely separate "
"variables\n"
"exist."
msgstr ""
#: src\anti_patterns/borrow_clone.md:38
msgid ""
"There are special cases -- `Rc<T>` is designed to handle clones "
"intelligently.\n"
"It internally manages exactly one copy of the data, and cloning it will "
"only\n"
"clone the reference."
msgstr ""
#: src\anti_patterns/borrow_clone.md:42
msgid ""
"There is also `Arc<T>` which provides shared ownership of a value of type T\n"
"that is allocated in the heap. Invoking `.clone()` on `Arc` produces a new "
"`Arc`\n"
"instance, which points to the same allocation on the heap as the source "
"`Arc`,\n"
"while increasing a reference count."
msgstr ""
#: src\anti_patterns/borrow_clone.md:47
msgid ""
"In general, clones should be deliberate, with full understanding of the\n"
"consequences. If a clone is used to make a borrow checker error disappear,\n"
"that's a good indication this anti-pattern may be in use."
msgstr ""
#: src\anti_patterns/borrow_clone.md:51
msgid ""
"Even though `.clone()` is an indication of a bad pattern, sometimes\n"
"**it is fine to write inefficient code**, in cases such as when:"
msgstr ""
#: src\anti_patterns/borrow_clone.md:54
msgid ""
"- the developer is still new to ownership\n"
"- the code doesn't have great speed or memory constraints\n"
" (like hackathon projects or prototypes)\n"
"- satisfying the borrow checker is really complicated, and you prefer to\n"
" optimize readability over performance"
msgstr ""
#: src\anti_patterns/borrow_clone.md:60
msgid ""
"If an unnecessary clone is suspected, The [Rust Book's chapter on "
"Ownership](https://doc.rust-lang.org/book/ownership.html)\n"
"should be understood fully before assessing whether the clone is required or "
"not."
msgstr ""
#: src\anti_patterns/borrow_clone.md:63
msgid ""
"Also be sure to always run `cargo clippy` in your project, which will detect "
"some\n"
"cases in which `.clone()` is not necessary, like "
"[1](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone),\n"
"[2](https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy),\n"
"[3](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) or "
"[4](https://rust-lang.github.io/rust-clippy/master/index.html#clone_double_ref)."
msgstr ""
#: src\anti_patterns/borrow_clone.md:70
msgid ""
"- [`mem::{take(_), replace(_)}` to keep owned values in changed "
"enums](../idioms/mem-replace.md)\n"
"- [`Rc<T>` documentation, which handles .clone() "
"intelligently](http://doc.rust-lang.org/std/rc/)\n"
"- [`Arc<T>` documentation, a thread-safe reference-counting "
"pointer](https://doc.rust-lang.org/std/sync/struct.Arc.html)\n"
"- [Tricks with ownership in "
"Rust](https://web.archive.org/web/20210120233744/https://xion.io/post/code/rust-borrowchk-tricks.html)"
msgstr ""
#: src\anti_patterns/deny-warnings.md:1
msgid "# `#![deny(warnings)]`"
msgstr ""
#: src\anti_patterns/deny-warnings.md:5
msgid ""
"A well-intentioned crate author wants to ensure their code builds without\n"
"warnings. So they annotate their crate root with the following:"
msgstr ""
#: src\anti_patterns/deny-warnings.md:10
msgid ""
"```rust\n"
"#![deny(warnings)]\n"
"\n"
"// All is well.\n"
"```"
msgstr ""
#: src\anti_patterns/deny-warnings.md:18
msgid "It is short and will stop the build if anything is amiss."
msgstr ""
#: src\anti_patterns/deny-warnings.md:20
msgid "## Drawbacks"
msgstr ""
#: src\anti_patterns/deny-warnings.md:22
msgid ""
"By disallowing the compiler to build with warnings, a crate author opts out "
"of\n"
"Rust's famed stability. Sometimes new features or old misfeatures need a "
"change\n"
"in how things are done, thus lints are written that `warn` for a certain "
"grace\n"
"period before being turned to `deny`."
msgstr ""
#: src\anti_patterns/deny-warnings.md:27
msgid ""
"For example, it was discovered that a type could have two `impl`s with the "
"same\n"
"method. This was deemed a bad idea, but in order to make the transition "
"smooth,\n"
"the `overlapping-inherent-impls` lint was introduced to give a warning to "
"those\n"
"stumbling on this fact, before it becomes a hard error in a future release."
msgstr ""
#: src\anti_patterns/deny-warnings.md:32
msgid ""
"Also sometimes APIs get deprecated, so their use will emit a warning where\n"
"before there was none."
msgstr ""
#: src\anti_patterns/deny-warnings.md:35
msgid ""
"All this conspires to potentially break the build whenever something changes."
msgstr ""
#: src\anti_patterns/deny-warnings.md:37
msgid ""
"Furthermore, crates that supply additional lints (e.g. [rust-clippy]) can "
"no\n"
"longer be used unless the annotation is removed. This is mitigated with\n"
"[--cap-lints]. The `--cap-lints=warn` command line argument, turns all "
"`deny`\n"
"lint errors into warnings."
msgstr ""
#: src\anti_patterns/deny-warnings.md:42
#: src\functional/generics-type-classes.md:227
msgid "## Alternatives"
msgstr ""
#: src\anti_patterns/deny-warnings.md:44
msgid ""
"There are two ways of tackling this problem: First, we can decouple the "
"build\n"
"setting from the code, and second, we can name the lints we want to deny\n"
"explicitly."
msgstr ""
#: src\anti_patterns/deny-warnings.md:48
msgid "The following command line will build with all warnings set to `deny`:"
msgstr ""
#: src\anti_patterns/deny-warnings.md:50
msgid "`RUSTFLAGS=\"-D warnings\" cargo build`"
msgstr ""
#: src\anti_patterns/deny-warnings.md:52
msgid ""
"This can be done by any individual developer (or be set in a CI tool like\n"
"Travis, but remember that this may break the build when something changes)\n"
"without requiring a change to the code."
msgstr ""
#: src\anti_patterns/deny-warnings.md:56
msgid ""
"Alternatively, we can specify the lints that we want to `deny` in the code.\n"
"Here is a list of warning lints that is (hopefully) safe to deny (as of "
"Rustc 1.48.0):"
msgstr ""
#: src\anti_patterns/deny-warnings.md:59
msgid ""
"```rust,ignore\n"
"#![deny(bad_style,\n"
" const_err,\n"
" dead_code,\n"
" improper_ctypes,\n"
" non_shorthand_field_patterns,\n"
" no_mangle_generic_items,\n"
" overflowing_literals,\n"
" path_statements,\n"
" patterns_in_fns_without_body,\n"
" private_in_public,\n"
" unconditional_recursion,\n"
" unused,\n"
" unused_allocation,\n"
" unused_comparisons,\n"
" unused_parens,\n"
" while_true)]\n"
"```"
msgstr ""
#: src\anti_patterns/deny-warnings.md:78
msgid "In addition, the following `allow`ed lints may be a good idea to `deny`:"
msgstr ""
#: src\anti_patterns/deny-warnings.md:80
msgid ""
"```rust,ignore\n"
"#![deny(missing_debug_implementations,\n"
" missing_docs,\n"
" trivial_casts,\n"
" trivial_numeric_casts,\n"
" unused_extern_crates,\n"
" unused_import_braces,\n"
" unused_qualifications,\n"
" unused_results)]\n"
"```"
msgstr ""
#: src\anti_patterns/deny-warnings.md:91
msgid "Some may also want to add `missing-copy-implementations` to their list."
msgstr ""
#: src\anti_patterns/deny-warnings.md:93
msgid ""
"Note that we explicitly did not add the `deprecated` lint, as it is fairly\n"
"certain that there will be more deprecated APIs in the future."
msgstr ""
#: src\anti_patterns/deny-warnings.md:98
msgid ""
"- [A collection of all clippy "
"lints](https://rust-lang.github.io/rust-clippy/master)\n"
"- [deprecate attribute] documentation\n"
"- Type `rustc -W help` for a list of lints on your system. Also type\n"
" `rustc --help` for a general list of options\n"
"- [rust-clippy] is a collection of lints for better Rust code"
msgstr ""
#: src\anti_patterns/deref.md:1
msgid "# `Deref` polymorphism"
msgstr ""
#: src\anti_patterns/deref.md:5
msgid ""
"Misuse the `Deref` trait to emulate inheritance between structs, and thus "
"reuse\n"
"methods."
msgstr ""
#: src\anti_patterns/deref.md:10
msgid ""
"Sometimes we want to emulate the following common pattern from OO languages "
"such\n"
"as Java:"
msgstr ""
#: src\anti_patterns/deref.md:13
msgid ""
"```java\n"
"class Foo {\n"
" void m() { ... }\n"
"}\n"
"\n"
"class Bar extends Foo {}\n"
"\n"
"public static void main(String[] args) {\n"
" Bar b = new Bar();\n"
" b.m();\n"
"}\n"
"```"
msgstr ""
#: src\anti_patterns/deref.md:26
msgid "We can use the deref polymorphism anti-pattern to do so:"
msgstr ""
#: src\anti_patterns/deref.md:28
msgid ""
"```rust\n"
"use std::ops::Deref;\n"
"\n"
"struct Foo {}\n"
"\n"
"impl Foo {\n"
" fn m(&self) {\n"
" //..\n"
" }\n"
"}\n"
"\n"
"struct Bar {\n"
" f: Foo,\n"
"}\n"
"\n"
"impl Deref for Bar {\n"
" type Target = Foo;\n"
" fn deref(&self) -> &Foo {\n"
" &self.f\n"
" }\n"
"}\n"
"\n"
"fn main() {\n"
" let b = Bar { f: Foo {} };\n"
" b.m();\n"
"}\n"
"```"
msgstr ""
#: src\anti_patterns/deref.md:56
msgid ""
"There is no struct inheritance in Rust. Instead we use composition and "
"include\n"
"an instance of `Foo` in `Bar` (since the field is a value, it is stored "
"inline,\n"
"so if there were fields, they would have the same layout in memory as the "
"Java\n"
"version (probably, you should use `#[repr(C)]` if you want to be sure))."
msgstr ""
#: src\anti_patterns/deref.md:61
msgid ""
"In order to make the method call work we implement `Deref` for `Bar` with "
"`Foo`\n"
"as the target (returning the embedded `Foo` field). That means that when we\n"
"dereference a `Bar` (for example, using `*`) then we will get a `Foo`. That "
"is\n"
"pretty weird. Dereferencing usually gives a `T` from a reference to `T`, "
"here we\n"
"have two unrelated types. However, since the dot operator does implicit\n"
"dereferencing, it means that the method call will search for methods on "
"`Foo` as\n"
"well as `Bar`."
msgstr ""
#: src\anti_patterns/deref.md:71
msgid "You save a little boilerplate, e.g.,"
msgstr ""
#: src\anti_patterns/deref.md:73
msgid ""
"```rust,ignore\n"
"impl Bar {\n"
" fn m(&self) {\n"
" self.f.m()\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\anti_patterns/deref.md:83
msgid ""
"Most importantly this is a surprising idiom - future programmers reading "
"this in\n"
"code will not expect this to happen. That's because we are misusing the "
"`Deref`\n"
"trait rather than using it as intended (and documented, etc.). It's also "
"because\n"
"the mechanism here is completely implicit."
msgstr ""
#: src\anti_patterns/deref.md:88
msgid ""
"This pattern does not introduce subtyping between `Foo` and `Bar` like\n"
"inheritance in Java or C++ does. Furthermore, traits implemented by `Foo` "
"are\n"
"not automatically implemented for `Bar`, so this pattern interacts badly "
"with\n"
"bounds checking and thus generic programming."
msgstr ""
#: src\anti_patterns/deref.md:93
msgid ""
"Using this pattern gives subtly different semantics from most OO languages "
"with\n"
"regards to `self`. Usually it remains a reference to the sub-class, with "
"this\n"
"pattern it will be the 'class' where the method is defined."
msgstr ""
#: src\anti_patterns/deref.md:97
msgid ""
"Finally, this pattern only supports single inheritance, and has no notion "
"of\n"
"interfaces, class-based privacy, or other inheritance-related features. So, "
"it\n"
"gives an experience that will be subtly surprising to programmers used to "
"Java\n"
"inheritance, etc."
msgstr ""
#: src\anti_patterns/deref.md:104
msgid ""
"There is no one good alternative. Depending on the exact circumstances it "
"might\n"
"be better to re-implement using traits or to write out the facade methods "
"to\n"
"dispatch to `Foo` manually. We do intend to add a mechanism for inheritance\n"
"similar to this to Rust, but it is likely to be some time before it reaches\n"
"stable Rust. See these "
"[blog](http://aturon.github.io/blog/2015/09/18/reuse/)\n"
"[posts](http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/)\n"
"and this [RFC issue](https://github.com/rust-lang/rfcs/issues/349) for more "
"details."
msgstr ""
#: src\anti_patterns/deref.md:112
msgid ""
"The `Deref` trait is designed for the implementation of custom pointer "
"types.\n"
"The intention is that it will take a pointer-to-`T` to a `T`, not convert\n"
"between different types. It is a shame that this isn't (probably cannot be)\n"
"enforced by the trait definition."
msgstr ""
#: src\anti_patterns/deref.md:117
msgid ""
"Rust tries to strike a careful balance between explicit and implicit "
"mechanisms,\n"
"favouring explicit conversions between types. Automatic dereferencing in the "
"dot\n"
"operator is a case where the ergonomics strongly favour an implicit "
"mechanism,\n"
"but the intention is that this is limited to degrees of indirection, not\n"
"conversion between arbitrary types."
msgstr ""
#: src\anti_patterns/deref.md:125
msgid ""
"- [Collections are smart pointers idiom](../idioms/deref.md).\n"
"- Delegation crates for less boilerplate like "
"[delegate](https://crates.io/crates/delegate)\n"
" or [ambassador](https://crates.io/crates/ambassador)\n"
"- [Documentation for `Deref` "
"trait](https://doc.rust-lang.org/std/ops/trait.Deref.html)."
msgstr ""
#: src\functional/index.md:1
msgid "# Functional Usage of Rust"
msgstr ""
#: src\functional/index.md:3
msgid ""
"Rust is an imperative language, but it follows many\n"
"[functional "
"programming](https://en.wikipedia.org/wiki/Functional_programming) paradigms."
msgstr ""
#: src\functional/index.md:6
msgid ""
"> In computer science, _functional programming_ is a programming paradigm "
"where\n"
"> programs are constructed by applying and composing functions.\n"
"> It is a declarative programming paradigm in which function definitions "
"are\n"
"> trees of expressions that each return a value, rather than a sequence of\n"
"> imperative statements which change the state of the program."
msgstr ""
#: src\functional/paradigms.md:1
msgid "# Programming paradigms"
msgstr ""
#: src\functional/paradigms.md:3
msgid ""
"One of the biggest hurdles to understanding functional programs when coming\n"
"from an imperative background is the shift in thinking. Imperative programs\n"
"describe **how** to do something, whereas declarative programs describe\n"
"**what** to do. Let's sum the numbers from 1 to 10 to show this."
msgstr ""
#: src\functional/paradigms.md:8
msgid "## Imperative"
msgstr ""
#: src\functional/paradigms.md:10
msgid ""
"```rust\n"
"let mut sum = 0;\n"
"for i in 1..11 {\n"
" sum += i;\n"
"}\n"
"println!(\"{}\", sum);\n"
"```"
msgstr ""
#: src\functional/paradigms.md:18
msgid ""
"With imperative programs, we have to play compiler to see what is "
"happening.\n"
"Here, we start with a `sum` of `0`.\n"
"Next, we iterate through the range from 1 to 10.\n"
"Each time through the loop, we add the corresponding value in the range.\n"
"Then we print it out."
msgstr ""
#: src\functional/paradigms.md:24
msgid ""
"| `i` | `sum` |\n"
"| :-: | :---: |\n"
"| 1 | 1 |\n"
"| 2 | 3 |\n"
"| 3 | 6 |\n"
"| 4 | 10 |\n"
"| 5 | 15 |\n"
"| 6 | 21 |\n"
"| 7 | 28 |\n"
"| 8 | 36 |\n"
"| 9 | 45 |\n"
"| 10 | 55 |"
msgstr ""
#: src\functional/paradigms.md:37
msgid ""
"This is how most of us start out programming. We learn that a program is a "
"set\n"
"of steps."
msgstr ""
#: src\functional/paradigms.md:40
msgid "## Declarative"
msgstr ""
#: src\functional/paradigms.md:42
msgid ""
"```rust\n"
"println!(\"{}\", (1..11).fold(0, |a, b| a + b));\n"
"```"
msgstr ""
#: src\functional/paradigms.md:46
msgid ""
"Whoa! This is really different! What's going on here?\n"
"Remember that with declarative programs we are describing **what** to do,\n"
"rather than **how** to do it. `fold` is a function that "
"[composes](https://en.wikipedia.org/wiki/Function_composition)\n"
"functions. The name is a convention from Haskell."
msgstr ""
#: src\functional/paradigms.md:51
msgid ""
"Here, we are composing functions of addition (this closure: `|a, b| a + b`)\n"
"with a range from 1 to 10. The `0` is the starting point, so `a` is `0` at\n"
"first. `b` is the first element of the range, `1`. `0 + 1 = 1` is the "
"result.\n"
"So now we `fold` again, with `a = 1`, `b = 2` and so `1 + 2 = 3` is the "
"next\n"
"result. This process continues until we get to the last element in the "
"range,\n"
"`10`."
msgstr ""
#: src\functional/paradigms.md:58
msgid ""
"| `a` | `b` | result |\n"
"| :-: | :-: | :----: |\n"
"| 0 | 1 | 1 |\n"
"| 1 | 2 | 3 |\n"
"| 3 | 3 | 6 |\n"
"| 6 | 4 | 10 |\n"
"| 10 | 5 | 15 |\n"
"| 15 | 6 | 21 |\n"
"| 21 | 7 | 28 |\n"
"| 28 | 8 | 36 |\n"
"| 36 | 9 | 45 |\n"
"| 45 | 10 | 55 |"
msgstr ""
#: src\functional/generics-type-classes.md:1
msgid "# Generics as Type Classes"
msgstr ""
#: src\functional/generics-type-classes.md:5
msgid ""
"Rust's type system is designed more like functional languages (like "
"Haskell)\n"
"rather than imperative languages (like Java and C++). As a result, Rust can "
"turn\n"
"many kinds of programming problems into \"static typing\" problems. This is "
"one\n"
"of the biggest wins of choosing a functional language, and is critical to "
"many\n"
"of Rust's compile time guarantees."
msgstr ""
#: src\functional/generics-type-classes.md:11
msgid ""
"A key part of this idea is the way generic types work. In C++ and Java, for\n"
"example, generic types are a meta-programming construct for the compiler.\n"
"`vector<int>` and `vector<char>` in C++ are just two different copies of "
"the\n"
"same boilerplate code for a `vector` type (known as a `template`) with two\n"
"different types filled in."
msgstr ""
#: src\functional/generics-type-classes.md:17
msgid ""
"In Rust, a generic type parameter creates what is known in functional "
"languages\n"
"as a \"type class constraint\", and each different parameter filled in by an "
"end\n"
"user _actually changes the type_. In other words, `Vec<isize>` and "
"`Vec<char>`\n"
"_are two different types_, which are recognized as distinct by all parts of "
"the\n"
"type system."
msgstr ""
#: src\functional/generics-type-classes.md:23
msgid ""
"This is called **monomorphization**, where different types are created from\n"
"**polymorphic** code. This special behavior requires `impl` blocks to "
"specify\n"
"generic parameters. Different values for the generic type cause different "
"types,\n"
"and different types can have different `impl` blocks."
msgstr ""
#: src\functional/generics-type-classes.md:28
msgid ""
"In object-oriented languages, classes can inherit behavior from their "
"parents.\n"
"However, this allows the attachment of not only additional behavior to\n"
"particular members of a type class, but extra behavior as well."
msgstr ""
#: src\functional/generics-type-classes.md:32
msgid ""
"The nearest equivalent is the runtime polymorphism in Javascript and "
"Python,\n"
"where new members can be added to objects willy-nilly by any constructor.\n"
"However, unlike those languages, all of Rust's additional methods can be "
"type\n"
"checked when they are used, because their generics are statically defined. "
"That\n"
"makes them more usable while remaining safe."
msgstr ""
#: src\functional/generics-type-classes.md:40
msgid ""
"Suppose you are designing a storage server for a series of lab machines.\n"
"Because of the software involved, there are two different protocols you "
"need\n"
"to support: BOOTP (for PXE network boot), and NFS (for remote mount storage)."
msgstr ""
#: src\functional/generics-type-classes.md:44
msgid ""
"Your goal is to have one program, written in Rust, which can handle both of\n"
"them. It will have protocol handlers and listen for both kinds of requests. "
"The\n"
"main application logic will then allow a lab administrator to configure "
"storage\n"
"and security controls for the actual files."
msgstr ""
#: src\functional/generics-type-classes.md:49
msgid ""
"The requests from machines in the lab for files contain the same basic\n"
"information, no matter what protocol they came from: an authentication "
"method,\n"
"and a file name to retrieve. A straightforward implementation would look\n"
"something like this:"
msgstr ""
#: src\functional/generics-type-classes.md:54
msgid ""
"```rust,ignore\n"
"enum AuthInfo {\n"
" Nfs(crate::nfs::AuthInfo),\n"
" Bootp(crate::bootp::AuthInfo),\n"
"}\n"
"\n"
"struct FileDownloadRequest {\n"
" file_name: PathBuf,\n"
" authentication: AuthInfo,\n"
"}\n"
"```"
msgstr ""
#: src\functional/generics-type-classes.md:66
msgid ""
"This design might work well enough. But now suppose you needed to support\n"
"adding metadata that was _protocol specific_. For example, with NFS, you\n"
"wanted to determine what their mount point was in order to enforce "
"additional\n"
"security rules."
msgstr ""
#: src\functional/generics-type-classes.md:71
msgid ""
"The way the current struct is designed leaves the protocol decision until\n"
"runtime. That means any method that applies to one protocol and not the "
"other\n"
"requires the programmer to do a runtime check."
msgstr ""
#: src\functional/generics-type-classes.md:75
msgid "Here is how getting an NFS mount point would look:"
msgstr ""
#: src\functional/generics-type-classes.md:77
msgid ""
"```rust,ignore\n"
"struct FileDownloadRequest {\n"
" file_name: PathBuf,\n"
" authentication: AuthInfo,\n"
" mount_point: Option<PathBuf>,\n"
"}\n"
"\n"
"impl FileDownloadRequest {\n"
" // ... other methods ...\n"
"\n"
" /// Gets an NFS mount point if this is an NFS request. Otherwise,\n"
" /// return None.\n"
" pub fn mount_point(&self) -> Option<&Path> {\n"
" self.mount_point.as_ref()\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\functional/generics-type-classes.md:95
msgid ""
"Every caller of `mount_point()` must check for `None` and write code to "
"handle\n"
"it. This is true even if they know only NFS requests are ever used in a "
"given\n"
"code path!"
msgstr ""
#: src\functional/generics-type-classes.md:99
msgid ""
"It would be far more optimal to cause a compile-time error if the different\n"
"request types were confused. After all, the entire path of the user's code,\n"
"including what functions from the library they use, will know whether a "
"request\n"
"is an NFS request or a BOOTP request."
msgstr ""
#: src\functional/generics-type-classes.md:104
msgid ""
"In Rust, this is actually possible! The solution is to _add a generic type_ "
"in\n"
"order to split the API."
msgstr ""
#: src\functional/generics-type-classes.md:107
msgid "Here is what that looks like:"
msgstr ""
#: src\functional/generics-type-classes.md:109
msgid ""
"```rust\n"
"use std::path::{Path, PathBuf};\n"
"\n"
"mod nfs {\n"
" #[derive(Clone)]\n"
" pub(crate) struct AuthInfo(String); // NFS session management omitted\n"
"}\n"
"\n"
"mod bootp {\n"
" pub(crate) struct AuthInfo(); // no authentication in bootp\n"
"}\n"
"\n"
"// private module, lest outside users invent their own protocol kinds!\n"
"mod proto_trait {\n"
" use std::path::{Path, PathBuf};\n"
" use super::{bootp, nfs};\n"
"\n"
" pub(crate) trait ProtoKind {\n"
" type AuthInfo;\n"
" fn auth_info(&self) -> Self::AuthInfo;\n"
" }\n"
"\n"
" pub struct Nfs {\n"
" auth: nfs::AuthInfo,\n"
" mount_point: PathBuf,\n"
" }\n"
"\n"
" impl Nfs {\n"
" pub(crate) fn mount_point(&self) -> &Path {\n"
" &self.mount_point\n"
" }\n"
" }\n"
"\n"
" impl ProtoKind for Nfs {\n"
" type AuthInfo = nfs::AuthInfo;\n"
" fn auth_info(&self) -> Self::AuthInfo {\n"
" self.auth.clone()\n"
" }\n"
" }\n"
"\n"
" pub struct Bootp(); // no additional metadata\n"
"\n"
" impl ProtoKind for Bootp {\n"
" type AuthInfo = bootp::AuthInfo;\n"
" fn auth_info(&self) -> Self::AuthInfo {\n"
" bootp::AuthInfo()\n"
" }\n"
" }\n"
"}\n"
"\n"
"use proto_trait::ProtoKind; // keep internal to prevent impls\n"
"pub use proto_trait::{Nfs, Bootp}; // re-export so callers can see them\n"
"\n"
"struct FileDownloadRequest<P: ProtoKind> {\n"
" file_name: PathBuf,\n"
" protocol: P,\n"
"}\n"
"\n"
"// all common API parts go into a generic impl block\n"
"impl<P: ProtoKind> FileDownloadRequest<P> {\n"
" fn file_path(&self) -> &Path {\n"
" &self.file_name\n"
" }\n"
"\n"
" fn auth_info(&self) -> P::AuthInfo {\n"
" self.protocol.auth_info()\n"
" }\n"
"}\n"
"\n"
"// all protocol-specific impls go into their own block\n"
"impl FileDownloadRequest<Nfs> {\n"
" fn mount_point(&self) -> &Path {\n"
" self.protocol.mount_point()\n"
" }\n"
"}\n"
"\n"
"fn main() {\n"
" // your code here\n"
"}\n"
"```"
msgstr ""
#: src\functional/generics-type-classes.md:190
msgid ""
"With this approach, if the user were to make a mistake and use the wrong\n"
"type;"
msgstr ""
#: src\functional/generics-type-classes.md:193
msgid ""
"```rust,ignore\n"
"fn main() {\n"
" let mut socket = crate::bootp::listen()?;\n"
" while let Some(request) = socket.next_request()? {\n"
" match request.mount_point().as_ref()\n"
" \"/secure\" => socket.send(\"Access denied\"),\n"
" _ => {} // continue on...\n"
" }\n"
" // Rest of the code here\n"
" }\n"
"}\n"
"```"
msgstr ""
#: src\functional/generics-type-classes.md:206
msgid ""
"They would get a syntax error. The type `FileDownloadRequest<Bootp>` does "
"not\n"
"implement `mount_point()`, only the type `FileDownloadRequest<Nfs>` does. "
"And\n"
"that is created by the NFS module, not the BOOTP module of course!"
msgstr ""
#: src\functional/generics-type-classes.md:212
msgid ""
"First, it allows fields that are common to multiple states to be "
"de-duplicated.\n"
"By making the non-shared fields generic, they are implemented once."
msgstr ""
#: src\functional/generics-type-classes.md:215
msgid ""
"Second, it makes the `impl` blocks easier to read, because they are broken "
"down\n"
"by state. Methods common to all states are typed once in one block, and "
"methods\n"
"unique to one state are in a separate block."
msgstr ""
#: src\functional/generics-type-classes.md:219
msgid ""
"Both of these mean there are fewer lines of code, and they are better "
"organized."
msgstr ""
#: src\functional/generics-type-classes.md:223
msgid ""
"This currently increases the size of the binary, due to the way "
"monomorphization\n"
"is implemented in the compiler. Hopefully the implementation will be able "
"to\n"
"improve in the future."
msgstr ""
#: src\functional/generics-type-classes.md:229
msgid ""
"- If a type seems to need a \"split API\" due to construction or partial\n"
" initialization, consider the\n"
" [Builder Pattern](../patterns/creational/builder.md) instead.\n"
"\n"
"- If the API between types does not change -- only the behavior does -- "
"then\n"
" the [Strategy Pattern](../patterns/behavioural/strategy.md) is better "
"used\n"
" instead."
msgstr ""
#: src\functional/generics-type-classes.md:239
msgid "This pattern is used throughout the standard library:"
msgstr ""
#: src\functional/generics-type-classes.md:241
msgid ""
"- `Vec<u8>` can be cast from a String, unlike every other type of "
"`Vec<T>`.[^1]\n"
"- They can also be cast into a binary heap, but only if they contain a type\n"
" that implements the `Ord` trait.[^2]\n"
"- The `to_string` method was specialized for `Cow` only of type `str`.[^3]"
msgstr ""
#: src\functional/generics-type-classes.md:246
msgid "It is also used by several popular crates to allow API flexibility:"
msgstr ""
#: src\functional/generics-type-classes.md:248
msgid ""
"- The `embedded-hal` ecosystem used for embedded devices makes extensive use "
"of\n"
" this pattern. For example, it allows statically verifying the "
"configuration of\n"
" device registers used to control embedded pins. When a pin is put into a "
"mode,\n"
" it returns a `Pin<MODE>` struct, whose generic determines the functions\n"
" usable in that mode, which are not on the `Pin` itself. [^4]\n"
"\n"
"- The `hyper` HTTP client library uses this to expose rich APIs for "
"different\n"
" pluggable requests. Clients with different connectors have different "
"methods\n"
" on them as well as different trait implementations, while a core set of\n"
" methods apply to any connector. [^5]\n"
"\n"
"- The \"type state\" pattern -- where an object gains and loses API based on "
"an\n"
" internal state or invariant -- is implemented in Rust using the same "
"basic\n"
" concept, and a slightly different technique. [^6]"
msgstr ""
#: src\functional/generics-type-classes.md:263
msgid ""
"See: [impl From\\<CString\\> for "
"Vec\\<u8\\>](https://doc.rust-lang.org/1.59.0/src/std/ffi/c_str.rs.html#803-811)"
msgstr ""
#: src\functional/generics-type-classes.md:265
msgid ""
"See: [impl\\<T\\> From\\<Vec\\<T, Global\\>\\> for "
"BinaryHeap\\<T\\>](https://doc.rust-lang.org/stable/src/alloc/collections/binary_heap.rs.html#1345-1354)"
msgstr ""
#: src\functional/generics-type-classes.md:267
msgid ""
"See: [impl\\<'\\_\\> ToString for Cow\\<'\\_, "
"str>](https://doc.rust-lang.org/stable/src/alloc/string.rs.html#2235-2240)"
msgstr ""
#: src\functional/generics-type-classes.md:269
msgid ""
"Example:\n"
"[https://docs.rs/stm32f30x-hal/0.1.0/stm32f30x_hal/gpio/gpioa/struct.PA0.html](https://docs.rs/stm32f30x-hal/0.1.0/stm32f30x_hal/gpio/gpioa/struct.PA0.html)"
msgstr ""
#: src\functional/generics-type-classes.md:272
msgid ""
"See:\n"
"[https://docs.rs/hyper/0.14.5/hyper/client/struct.Client.html](https://docs.rs/hyper/0.14.5/hyper/client/struct.Client.html)"
msgstr ""
#: src\functional/generics-type-classes.md:275
msgid ""
"See:\n"
"[The Case for the Type State "
"Pattern](https://web.archive.org/web/20210325065112/https://www.novatec-gmbh.de/en/blog/the-case-for-the-typestate-pattern-the-typestate-pattern-itself/)\n"
"and\n"
"[Rusty Typestate Series (an extensive "
"thesis)](https://web.archive.org/web/20210328164854/https://rustype.github.io/notes/notes/rust-typestate-series/rust-typestate-index)"
msgstr ""
#: src\functional/lenses.md:1
msgid "# Lenses and Prisms"
msgstr ""
#: src\functional/lenses.md:3
msgid ""
"This is a pure functional concept that is not frequently used in Rust.\n"
"Nevertheless, exploring the concept may be helpful to understand other\n"
"patterns in Rust APIs, such as "
"[visitors](../patterns/behavioural/visitor.md).\n"
"They also have niche use cases."
msgstr ""
#: src\functional/lenses.md:8
msgid "## Lenses: Uniform Access Across Types"
msgstr ""
#: src\functional/lenses.md:10
msgid ""
"A lens is a concept from functional programming languages that allows\n"
"accessing parts of a data type in an abstract, unified way.[^1]\n"
"In basic concept, it is similar to the way Rust traits work with type "
"erasure,\n"
"but it has a bit more power and flexibility."
msgstr ""
#: src\functional/lenses.md:15
msgid ""
"For example, suppose a bank contains several JSON formats for customer\n"
"data.\n"
"This is because they come from different databases or legacy systems.\n"
"One database contains the data needed to perform credit checks:"
msgstr ""
#: src\functional/lenses.md:20
msgid ""
"```json\n"
"{ \"name\": \"Jane Doe\",\n"
" \"dob\": \"2002-02-24\",\n"
" [...]\n"
" \"customer_id\": 1048576332,\n"
"}\n"
"```"
msgstr ""
#: src\functional/lenses.md:28
msgid "Another one contains the account information:"
msgstr ""
#: src\functional/lenses.md:30
msgid ""
"```json\n"
"{ \"customer_id\": 1048576332,\n"
" \"accounts\": [\n"
" { \"account_id\": 2121,\n"
" \"account_type: \"savings\",\n"
" \"joint_customer_ids\": [],\n"
" [...]\n"
" },\n"
" { \"account_id\": 2122,\n"
" \"account_type: \"checking\",\n"
" \"joint_customer_ids\": [1048576333],\n"
" [...]\n"
" },\n"
" ]\n"
"}\n"
"```"
msgstr ""
#: src\functional/lenses.md:47
msgid ""
"Notice that both types have a customer ID number which corresponds to a "
"person.\n"
"How would a single function handle both records of different types?"
msgstr ""
#: src\functional/lenses.md:50
msgid ""
"In Rust, a `struct` could represent each of these types, and a trait would "
"have\n"
"a `get_customer_id` function they would implement:"
msgstr ""
#: src\functional/lenses.md:53
msgid ""
"```rust\n"
"use std::collections::HashSet;\n"
"\n"
"pub struct Account {\n"
" account_id: u32,\n"
" account_type: String,\n"
" // other fields omitted\n"
"}\n"
"\n"
"pub trait CustomerId {\n"
" fn get_customer_id(&self) -> u64;\n"
"}\n"
"\n"
"pub struct CreditRecord {\n"
" customer_id: u64,\n"
" name: String,\n"
" dob: String,\n"
" // other fields omitted\n"
"}\n"
"\n"
"impl CustomerId for CreditRecord {\n"
" fn get_customer_id(&self) -> u64 {\n"
" self.customer_id\n"
" }\n"
"}\n"
"\n"
"pub struct AccountRecord {\n"
" customer_id: u64,\n"
" accounts: Vec<Account>,\n"
"}\n"
"\n"
"impl CustomerId for AccountRecord {\n"
" fn get_customer_id(&self) -> u64 {\n"
" self.customer_id\n"
" }\n"
"}\n"
"\n"
"// static polymorphism: only one type, but each function call can choose it\n"
"fn unique_ids_set<R: CustomerId>(records: &[R]) -> HashSet<u64> {\n"
" records.iter().map(|r| r.get_customer_id()).collect()\n"
"}\n"
"\n"
"// dynamic dispatch: iterates over any type with a customer ID, collecting "
"all\n"
"// values together\n"
"fn unique_ids_iter<I>(iterator: I) -> HashSet<u64>\n"
" where I: Iterator<Item=Box<dyn CustomerId>>\n"
"{\n"
" iterator.map(|r| r.as_ref().get_customer_id()).collect()\n"
"}\n"
"```"
msgstr ""
#: src\functional/lenses.md:104
msgid ""
"Lenses, however, allow the code supporting customer ID to be moved from the\n"
"_type_ to the _accessor function_.\n"
"Rather than implementing a trait on each type, all matching structures can\n"
"simply be accessed the same way."
msgstr ""
#: src\functional/lenses.md:109
msgid ""
"While the Rust language itself does not support this (type erasure is the\n"
"preferred solution to this problem), the [lens-rs "
"crate](https://github.com/TOETOE55/lens-rs/blob/master/guide.md) allows "
"code\n"
"that feels like this to be written with macros:"
msgstr ""
#: src\functional/lenses.md:113
msgid ""
"```rust,ignore\n"
"use std::collections::HashSet;\n"
"\n"
"use lens_rs::{optics, Lens, LensRef, Optics};\n"
"\n"
"#[derive(Clone, Debug, Lens /* derive to allow lenses to work */)]\n"
"pub struct CreditRecord {\n"
" #[optic(ref)] // macro attribute to allow viewing this field\n"
" customer_id: u64,\n"
" name: String,\n"
" dob: String,\n"
" // other fields omitted\n"
"}\n"
"\n"
"#[derive(Clone, Debug)]\n"
"pub struct Account {\n"
" account_id: u32,\n"
" account_type: String,\n"
" // other fields omitted\n"
"}\n"
"\n"
"#[derive(Clone, Debug, Lens)]\n"
"pub struct AccountRecord {\n"
" #[optic(ref)]\n"
" customer_id: u64,\n"
" accounts: Vec<Account>,\n"
"}\n"
"\n"
"fn unique_ids_lens<T>(iter: impl Iterator<Item = T>) -> HashSet<u64>\n"
"where\n"
" T: LensRef<Optics![customer_id], u64>, // any type with this field\n"
"{\n"
" iter.map(|r| *r.view_ref(optics!(customer_id))).collect()\n"
"}\n"
"```"
msgstr ""
#: src\functional/lenses.md:149
msgid ""
"The version of `unique_ids_lens` shown here allows any type to be in the "
"iterator,\n"
"so long as it has an attribute called `customer_id` which can be accessed "
"by\n"
"the function.\n"
"This is how most functional programming languages operate on lenses."
msgstr ""
#: src\functional/lenses.md:154
msgid ""
"Rather than macros, they achieve this with a technique known as "
"\"currying\".\n"
"That is, they \"partially construct\" the function, leaving the type of the\n"
"final parameter (the value being operated on) unfilled until the function "
"is\n"
"called.\n"
"Thus it can be called with different types dynamically even from one place "
"in\n"
"the code.\n"
"That is what the `optics!` and `view_ref` in the example above simulates."
msgstr ""
#: src\functional/lenses.md:162
msgid ""
"The functional approach need not be restricted to accessing members.\n"
"More powerful lenses can be created which both _set_ and _get_ data in a\n"
"structure.\n"
"But the concept really becomes interesting when used as a building block "
"for\n"
"composition.\n"
"That is where the concept appears more clearly in Rust."
msgstr ""
#: src\functional/lenses.md:169
msgid "## Prisms: A Higher-Order form of \"Optics\""
msgstr ""
#: src\functional/lenses.md:171
msgid ""
"A simple function such as `unique_ids_lens` above operates on a single "
"lens.\n"
"A _prism_ is a function that operates on a _family_ of lenses.\n"
"It is one conceptual level higher, using lenses as a building block, and\n"
"continuing the metaphor, is part of a family of \"optics\".\n"
"It is the main one that is useful in understanding Rust APIs, so will be "
"the\n"
"focus here."
msgstr ""
#: src\functional/lenses.md:178
msgid ""
"The same way that traits allow \"lens-like\" design with static polymorphism "
"and\n"
"dynamic dispatch, prism-like designs appear in Rust APIs which split "
"problems\n"
"into multiple associated types to be composed.\n"
"A good example of this is the traits in the parsing crate _Serde_."
msgstr ""
#: src\functional/lenses.md:183
msgid ""
"Trying to understand the way _Serde_ works by only reading the API is a\n"
"challenge, especially the first time.\n"
"Consider the `Deserializer` trait, implemented by some type in any library\n"
"which parses a new format:"
msgstr ""
#: src\functional/lenses.md:188
msgid ""
"```rust,ignore\n"
"pub trait Deserializer<'de>: Sized {\n"
" type Error: Error;\n"
"\n"
" fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, "
"Self::Error>\n"
" where\n"
" V: Visitor<'de>;\n"
"\n"
" fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, "
"Self::Error>\n"
" where\n"
" V: Visitor<'de>;\n"
"\n"
" // remainder ommitted\n"
"}\n"
"```"
msgstr ""
#: src\functional/lenses.md:204
msgid ""
"For a trait that is just supposed to parse data from a format and return a\n"
"value, this looks odd."
msgstr ""
#: src\functional/lenses.md:207
msgid "Why are all the return types type erased?"
msgstr ""
#: src\functional/lenses.md:209
msgid ""
"To understand that, we need to keep the lens concept in mind and look at\n"
"the definition of the `Visitor` type that is passed in generically:"
msgstr ""
#: src\functional/lenses.md:212
msgid ""
"```rust,ignore\n"
"pub trait Visitor<'de>: Sized {\n"
" type Value;\n"
"\n"
" fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>\n"
" where\n"
" E: Error;\n"
"\n"
" fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>\n"
" where\n"
" E: Error;\n"
"\n"
" fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>\n"
" where\n"
" E: Error;\n"
"\n"
" // remainder omitted\n"
"}\n"
"```"
msgstr ""
#: src\functional/lenses.md:232
msgid ""
"The job of the `Visitor` type is to construct values in the _Serde_ data "
"model,\n"
"which are represented by its associated `Value` type."
msgstr ""
#: src\functional/lenses.md:235
msgid ""
"These values represent parts of the Rust value being deserialized.\n"
"If this fails, it returns an `Error` type - an error type determined by the\n"
"`Deserializer` when its methods were called."
msgstr ""
#: src\functional/lenses.md:239
msgid ""
"This highlights that `Deserializer` is similar to `CustomerId` from "
"earlier,\n"
"allowing any format parser which implements it to create `Value`s based on "
"what\n"
"it parsed.\n"
"The `Value` trait is acting like a lens in functional programming languages."
msgstr ""
#: src\functional/lenses.md:244
msgid ""
"But unlike the `CustomerId` trait, the return types of `Visitor` methods "
"are\n"
"_generic_, and the concrete `Value` type is _determined by the Visitor "
"itself_."
msgstr ""
#: src\functional/lenses.md:247
msgid ""
"Instead of acting as one lens, it effectively acts as a family of\n"
"lenses, one for each concrete type of `Visitor`."
msgstr ""
#: src\functional/lenses.md:250
msgid ""
"The `Deserializer` API is based on having a generic set of \"lenses\" work "
"across\n"
"a set of other generic types for \"observation\".\n"
"It is a _prism_."
msgstr ""
#: src\functional/lenses.md:254
msgid "For example, consider the identity record from earlier but simplified:"
msgstr ""
#: src\functional/lenses.md:256
msgid ""
"```json\n"
"{ \"name\": \"Jane Doe\",\n"
" \"customer_id\": 1048576332,\n"
"}\n"
"```"
msgstr ""
#: src\functional/lenses.md:262
msgid ""
"How would the _Serde_ library deserialize this JSON into `struct "
"CreditRecord`?"
msgstr ""
#: src\functional/lenses.md:264
msgid ""
"1. The user would call a library function to deserialize the data. This "
"would\n"
" create a `Deserializer` based on the JSON format.\n"
"1. Based on the fields in the struct, a `Visitor` would be created (more on\n"
" that in a moment) which knows how to create each type in a generic data\n"
" model that was needed to represent it: `u64` and `String`.\n"
"1. The deserializer would make calls to the `Visitor` as it parsed items.\n"
"1. The `Visitor` would indicate if the items found were expected, and if "
"not,\n"
" raise an error to indicate deserialization has failed."
msgstr ""
#: src\functional/lenses.md:273
msgid "For our very simple structure above, the expected pattern would be:"
msgstr ""
#: src\functional/lenses.md:275
msgid ""
"1. Visit a map (_Serde_'s equvialent to `HashMap` or JSON's dictionary).\n"
"1. Visit a string key called \"name\".\n"
"1. Visit a string value, which will go into the `name` field.\n"
"1. Visit a string key called \"customer_id\".\n"
"1. Visit a string value, which will go into the `customer_id` field.\n"
"1. Visit the end of the map."
msgstr ""
#: src\functional/lenses.md:282
msgid "But what determines which \"observation\" pattern is expected?"
msgstr ""
#: src\functional/lenses.md:284
msgid ""
"A functional programming language would be able to use currying to create\n"
"reflection of each type based on the type itself.\n"
"Rust does not support that, so every single type would need to have its own\n"
"code written based on its fields and their properties."
msgstr ""
#: src\functional/lenses.md:289
msgid "_Serde_ solves this usability challenge with a derive macro:"
msgstr ""
#: src\functional/lenses.md:291
msgid ""
"```rust,ignore\n"
"use serde::Deserialize;\n"
"\n"
"#[derive(Deserialize)]\n"
"struct IdRecord {\n"
" name: String,\n"
" customer_id: String,\n"
"}\n"
"```"
msgstr ""
#: src\functional/lenses.md:301
msgid ""
"That macro simply generates an impl block causing the struct to implement a\n"
"trait called `Deserialize`."
msgstr ""
#: src\functional/lenses.md:304
msgid "It is defined this way:"
msgstr ""
#: src\functional/lenses.md:306
msgid ""
"```rust,ignore\n"
"pub trait Deserialize<'de>: Sized {\n"
" fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n"
" where\n"
" D: Deserializer<'de>;\n"
"}\n"
"```"
msgstr ""
#: src\functional/lenses.md:314
msgid ""
"This is the function that determines how to create the struct itself.\n"
"Code is generated based on the struct's fields.\n"
"When the parsing library is called - in our example, a JSON parsing library "
"-\n"
"it creates a `Deserializer` and calls `Type::deserialize` with it as a\n"
"parameter."
msgstr ""
#: src\functional/lenses.md:320
msgid ""
"The `deserialize` code will then create a `Visitor` which will have its "
"calls\n"
"\"refracted\" by the `Deserializer`.\n"
"If everything goes well, eventually that `Visitor` will construct a value\n"
"corresponding to the type being parsed and return it."
msgstr ""
#: src\functional/lenses.md:325
msgid ""
"For a complete example, see the [_Serde_ "
"documentation](https://serde.rs/deserialize-struct.html)."
msgstr ""
#: src\functional/lenses.md:327
msgid "To wrap up, this is the power of _Serde_:"
msgstr ""
#: src\functional/lenses.md:329
msgid ""
"1. The structure being parsed is represented by an `impl` block for "
"`Deserialize`\n"
"1. The input data format (e.g. JSON) is represented by a `Deserializer` "
"called\n"
" by `Deserialize`\n"
"1. The `Deserializer` acts like a prism which \"refracts\" lens-like "
"`Visitor`\n"
" calls which actually build the data value"
msgstr ""
#: src\functional/lenses.md:335
msgid ""
"The result is that types to be deserialized only implement the \"top layer\" "
"of\n"
"the API, and file formats only need to implement the \"bottom layer\".\n"
"Each piece can then \"just work\" with the rest of the ecosystem, since "
"generic\n"
"types will bridge them."
msgstr ""
#: src\functional/lenses.md:340
msgid ""
"To emphasize, the only reason this model works on any format and any type "
"is\n"
"because the `Deserializer` trait's output type **is specified by the\n"
"implementor of `Visitor` it is passed**, rather than being tied to one "
"specific\n"
"type.\n"
"This was not true in the account example earlier."
msgstr ""
#: src\functional/lenses.md:346
msgid ""
"Rust's generic-inspired type system can bring it close to these concepts "
"and\n"
"use their power, as shown in this API design.\n"
"But it may also need procedural macros to create bridges for its generics."
msgstr ""
#: src\functional/lenses.md:350
msgid "## See Also"
msgstr ""
#: src\functional/lenses.md:352
msgid ""
"- [lens-rs crate](https://crates.io/crates/lens-rs) for a pre-built lenses\n"
" implementation, with a cleaner interface than these examples\n"
"- [serde](https://serde.rs) itself, which makes these concepts intuitive "
"for\n"
" end users (i.e. defining the structs) without needing to undestand the\n"
" details\n"
"- [luminance](https://github.com/phaazon/luminance-rs) is a crate for "
"drawing\n"
" computer graphics that uses lens API design, including proceducal macros "
"to\n"
" create full prisms for buffers of different pixel types that remain "
"generic\n"
"- [An Article about Lenses in "
"Scala](https://web.archive.org/web/20221128185849/https://medium.com/zyseme-technology/functional-references-lens-and-other-optics-in-scala-e5f7e2fdafe)\n"
" that is very readable even without Scala expertise.\n"
"- [Paper: Profunctor Optics: Modular Data\n"
" "
"Accessors](https://web.archive.org/web/20220701102832/https://arxiv.org/ftp/arxiv/papers/1703/1703.10857.pdf)"
msgstr ""
#: src\functional/lenses.md:365
msgid ""
"[School of Haskell: A Little Lens Starter "
"Tutorial](https://web.archive.org/web/20221128190041/https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of-the-week/a-little-lens-starter-tutorial)"
msgstr ""
#: src\additional_resources/index.md:1
msgid "# Additional resources"
msgstr ""
#: src\additional_resources/index.md:3
msgid "A collection of complementary helpful content"
msgstr ""
#: src\additional_resources/index.md:5
msgid "## Talks"
msgstr ""
#: src\additional_resources/index.md:7
msgid ""
"- [Design Patterns in Rust](https://www.youtube.com/watch?v=Pm_oO0N5B9k) by\n"
" Nicholas Cameron at the PDRust (2016)\n"
"- [Writing Idiomatic Libraries in "
"Rust](https://www.youtube.com/watch?v=0zOg8_B71gE)\n"
" by Pascal Hertleif at RustFest (2017)\n"
"- [Rust Programming Techniques](https://www.youtube.com/watch?v=vqavdUGKeb4) "
"by\n"
" Nicholas Cameron at LinuxConfAu (2018)"
msgstr ""
#: src\additional_resources/index.md:14
msgid "## Books (Online)"
msgstr ""
#: src\additional_resources/index.md:16
msgid "- [The Rust API Guidelines](https://rust-lang.github.io/api-guidelines)"
msgstr ""
#: src\additional_resources/design-principles.md:1
msgid "# Design principles"
msgstr ""
#: src\additional_resources/design-principles.md:3
msgid "## A brief overview over common design principles"
msgstr ""
#: src\additional_resources/design-principles.md:7
msgid "## [SOLID](https://en.wikipedia.org/wiki/SOLID)"
msgstr ""
#: src\additional_resources/design-principles.md:9
msgid ""
"- [Single Responsibility Principle "
"(SRP)](https://en.wikipedia.org/wiki/Single-responsibility_principle):\n"
" A class should only have a single responsibility, that is, only changes "
"to\n"
" one part of the software's specification should be able to affect the\n"
" specification of the class.\n"
"- [Open/Closed Principle "
"(OCP)](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle):\n"
" \"Software entities ... should be open for extension, but closed for\n"
" modification.\"\n"
"- [Liskov Substitution Principle "
"(LSP)](https://en.wikipedia.org/wiki/Liskov_substitution_principle):\n"
" \"Objects in a program should be replaceable with instances of their "
"subtypes\n"
" without altering the correctness of that program.\"\n"
"- [Interface Segregation Principle "
"(ISP)](https://en.wikipedia.org/wiki/Interface_segregation_principle):\n"
" \"Many client-specific interfaces are better than one general-purpose\n"
" interface.\"\n"
"- [Dependency Inversion Principle "
"(DIP)](https://en.wikipedia.org/wiki/Dependency_inversion_principle):\n"
" One should \"depend upon abstractions, [not] concretions.\""
msgstr ""
#: src\additional_resources/design-principles.md:25
msgid ""
"## [DRY (Dont Repeat "
"Yourself)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)"
msgstr ""
#: src\additional_resources/design-principles.md:27
msgid ""
"\"Every piece of knowledge must have a single, unambiguous, authoritative\n"
"representation within a system\""
msgstr ""
#: src\additional_resources/design-principles.md:30
msgid "## [KISS principle](https://en.wikipedia.org/wiki/KISS_principle)"
msgstr ""
#: src\additional_resources/design-principles.md:32
msgid ""
"most systems work best if they are kept simple rather than made "
"complicated;\n"
"therefore, simplicity should be a key goal in design, and unnecessary\n"
"complexity should be avoided"
msgstr ""
#: src\additional_resources/design-principles.md:36
msgid "## [Law of Demeter (LoD)](https://en.wikipedia.org/wiki/Law_of_Demeter)"
msgstr ""
#: src\additional_resources/design-principles.md:38
msgid ""
"a given object should assume as little as possible about the structure or\n"
"properties of anything else (including its subcomponents), in accordance "
"with\n"
"the principle of \"information hiding\""
msgstr ""
#: src\additional_resources/design-principles.md:42
msgid ""
"## [Design by contract "
"(DbC)](https://en.wikipedia.org/wiki/Design_by_contract)"
msgstr ""
#: src\additional_resources/design-principles.md:44
msgid ""
"software designers should define formal, precise and verifiable interface\n"
"specifications for software components, which extend the ordinary definition "
"of\n"
"abstract data types with preconditions, postconditions and invariants"
msgstr ""
#: src\additional_resources/design-principles.md:48
msgid ""
"## "
"[Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))"
msgstr ""
#: src\additional_resources/design-principles.md:50
msgid ""
"bundling of data with the methods that operate on that data, or the "
"restricting\n"
"of direct access to some of an object's components. Encapsulation is used "
"to\n"
"hide the values or state of a structured data object inside a class, "
"preventing\n"
"unauthorized parties' direct access to them."
msgstr ""
#: src\additional_resources/design-principles.md:55
msgid ""
"## "
"[Command-Query-Separation(CQS)](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation)"
msgstr ""
#: src\additional_resources/design-principles.md:57
msgid ""
"“Functions should not produce abstract side effects...only commands\n"
"(procedures) will be permitted to produce side effects.” - Bertrand Meyer:\n"
"Object-Oriented Software Construction"
msgstr ""
#: src\additional_resources/design-principles.md:61
msgid ""
"## [Principle of least astonishment "
"(POLA)](https://en.wikipedia.org/wiki/Principle_of_least_astonishment)"
msgstr ""
#: src\additional_resources/design-principles.md:63
msgid ""
"a component of a system should behave in a way that most users will expect "
"it\n"
"to behave. The behavior should not astonish or surprise users"
msgstr ""
#: src\additional_resources/design-principles.md:66
msgid "## Linguistic-Modular-Units"
msgstr ""
#: src\additional_resources/design-principles.md:68
msgid ""
"“Modules must correspond to syntactic units in the language used.” - "
"Bertrand\n"
"Meyer: Object-Oriented Software Construction"
msgstr ""
#: src\additional_resources/design-principles.md:71
msgid "## Self-Documentation"
msgstr ""
#: src\additional_resources/design-principles.md:73
msgid ""
"“The designer of a module should strive to make all information about the\n"
"module part of the module itself.” - Bertrand Meyer: Object-Oriented "
"Software\n"
"Construction"
msgstr ""
#: src\additional_resources/design-principles.md:77
msgid "## Uniform-Access"
msgstr ""
#: src\additional_resources/design-principles.md:79
msgid ""
"“All services offered by a module should be available through a uniform\n"
"notation, which does not betray whether they are implemented through storage "
"or\n"
"through computation.” - Bertrand Meyer: Object-Oriented Software Construction"
msgstr ""
#: src\additional_resources/design-principles.md:83
msgid "## Single-Choice"
msgstr ""
#: src\additional_resources/design-principles.md:85
msgid ""
"“Whenever a software system must support a set of alternatives, one and "
"only\n"
"one module in the system should know their exhaustive list.” - Bertrand "
"Meyer:\n"
"Object-Oriented Software Construction"
msgstr ""
#: src\additional_resources/design-principles.md:89
msgid "## Persistence-Closure"
msgstr ""
#: src\additional_resources/design-principles.md:91
msgid ""
"“Whenever a storage mechanism stores an object, it must store with it the\n"
"dependents of that object. Whenever a retrieval mechanism retrieves a\n"
"previously stored object, it must also retrieve any dependent of that "
"object\n"
"that has not yet been retrieved.” - Bertrand Meyer: Object-Oriented "
"Software\n"
"Construction"
msgstr ""