From af57ff0453e39f5477677742470cec888f4ed373 Mon Sep 17 00:00:00 2001 From: Nuga Date: Thu, 6 Aug 2026 10:53:01 +0200 Subject: [PATCH 1/3] Initialization and menu translation --- po/fr.po | 5938 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 5938 insertions(+) create mode 100644 po/fr.po diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 00000000..3babf5fc --- /dev/null +++ b/po/fr.po @@ -0,0 +1,5938 @@ +msgid "" +msgstr "" +"Project-Id-Version: Rust Design Patterns\n" +"POT-Creation-Date: 2025-05-17T14:07:35+09:00\n" +"PO-Revision-Date: 2026-08-06 10:44+0200\n" +"Last-Translator: Rémi \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.9\n" + +#: src/SUMMARY.md:1 +msgid "Summary" +msgstr "Résumé" + +#: src/SUMMARY.md:3 src/intro.md:1 +msgid "Introduction" +msgstr "Introduction" + +#: src/SUMMARY.md:4 src/translations.md:1 +msgid "Translations" +msgstr "Traductions" + +#: src/SUMMARY.md:5 src/idioms/index.md:1 +msgid "Idioms" +msgstr "Bonnes pratiques" + +#: src/SUMMARY.md:6 src/idioms/coercion-arguments.md:1 +msgid "Use borrowed types for arguments" +msgstr "Utiliser des types empruntés comme arguments" + +#: src/SUMMARY.md:7 +msgid "Concatenating Strings with format!" +msgstr "Concaténer les chaînes de caractères avec format!" + +#: src/SUMMARY.md:8 +msgid "Constructor" +msgstr "Constructeurs" + +#: src/SUMMARY.md:9 +msgid "The Default Trait" +msgstr "Le trait Default" + +#: src/SUMMARY.md:10 +msgid "Collections Are Smart Pointers" +msgstr "Les collections sont des pointeurs intelligents" + +#: src/SUMMARY.md:11 +msgid "Finalisation in Destructors" +msgstr "Finalisation dans les destructeurs" + +#: src/SUMMARY.md:12 +msgid "`mem::{take(_), replace(_)}`" +msgstr "`mem::{take(_), replace(_)}`" + +#: src/SUMMARY.md:13 src/idioms/on-stack-dyn-dispatch.md:1 +msgid "On-Stack Dynamic Dispatch" +msgstr "Affectation dynamique sur la pile" + +#: src/SUMMARY.md:14 src/SUMMARY.md:40 +msgid "Foreign function interface (FFI)" +msgstr "Foreign function interface (FFI)" + +#: src/SUMMARY.md:15 +msgid "Idiomatic Errors" +msgstr "Gestion idéale des erreurs" + +#: src/SUMMARY.md:16 src/idioms/ffi/accepting-strings.md:1 +msgid "Accepting Strings" +msgstr "Recevoir des chaînes de caractères" + +#: src/SUMMARY.md:17 src/idioms/ffi/passing-strings.md:1 +msgid "Passing Strings" +msgstr "Envoyer des chaînes de caractères" + +#: src/SUMMARY.md:18 +msgid "Iterating over an Option" +msgstr "Itérer sur les Options" + +#: src/SUMMARY.md:19 +msgid "Pass Variables to Closure" +msgstr "Envoyer des variables à une fermeture" + +#: src/SUMMARY.md:20 +msgid "Privacy For Extensibility" +msgstr "Visibilité des éléments pour l'extensibilité" + +#: src/SUMMARY.md:21 src/idioms/rustdoc-init.md:1 +msgid "Easy doc initialization" +msgstr "Simplifier l'initialisation de la documentation" + +#: src/SUMMARY.md:22 src/idioms/temporary-mutability.md:1 +msgid "Temporary mutability" +msgstr "Mutabilité temporaire" + +#: src/SUMMARY.md:23 +msgid "Return consumed arg on error" +msgstr "Renvoyer les arguments consommés en cas d'erreur" + +#: src/SUMMARY.md:25 src/patterns/index.md:1 +msgid "Design Patterns" +msgstr "Patrons de conception" + +#: src/SUMMARY.md:26 +msgid "Behavioural" +msgstr "Patrons comportementaux" + +#: src/SUMMARY.md:27 src/patterns/behavioural/command.md:1 +msgid "Command" +msgstr "Commande" + +#: src/SUMMARY.md:28 src/patterns/behavioural/interpreter.md:1 +msgid "Interpreter" +msgstr "Interpréteur" + +#: src/SUMMARY.md:29 src/patterns/behavioural/newtype.md:1 +msgid "Newtype" +msgstr "Nouveau type" + +#: src/SUMMARY.md:30 +msgid "RAII Guards" +msgstr "Garde RAII" + +#: src/SUMMARY.md:31 +msgid "Strategy" +msgstr "Stratégie" + +#: src/SUMMARY.md:32 src/patterns/behavioural/visitor.md:1 +msgid "Visitor" +msgstr "Visiteur" + +#: src/SUMMARY.md:33 +msgid "Creational" +msgstr "Patrons de création" + +#: src/SUMMARY.md:34 src/patterns/creational/builder.md:1 +msgid "Builder" +msgstr "Monteur" + +# Le terme original "fold" est discuté par l'auteur. La traduction enlève en plus une partie du sens. Peut-être qu'il faudrait s'éloigner du nom original pour trouver un nom français approprié à ce patron. +#: src/SUMMARY.md:35 src/patterns/creational/fold.md:1 +msgid "Fold" +msgstr "Repli" + +#: src/SUMMARY.md:36 +msgid "Structural" +msgstr "Patrons Structurels" + +#: src/SUMMARY.md:37 +msgid "Compose Structs" +msgstr "Structures composites" + +#: src/SUMMARY.md:38 +msgid "Prefer Small Crates" +msgstr "Réduire la taille des crates" + +#: src/SUMMARY.md:39 src/patterns/structural/unsafe-mods.md:1 +msgid "Contain unsafety in small modules" +msgstr "Restreindre le code non sécurisé dans des petits modules" + +#: src/SUMMARY.md:41 src/patterns/ffi/export.md:1 +msgid "Object-Based APIs" +msgstr "APIs basées sur les objets" + +#: src/SUMMARY.md:42 src/patterns/ffi/wrappers.md:1 +msgid "Type Consolidation into Wrappers" +msgstr "Consolidation des types par des Wrappers" + +#: src/SUMMARY.md:44 src/anti_patterns/index.md:1 +msgid "Anti-patterns" +msgstr "Anti-patrons" + +#: src/SUMMARY.md:45 src/anti_patterns/borrow_clone.md:1 +msgid "Clone to satisfy the borrow checker" +msgstr "Cloner pour satisfaire le vérificateur d'emprunt" + +#: src/SUMMARY.md:46 +msgid "`#[deny(warnings)]`" +msgstr "`#[deny(warnings)]`" + +#: src/SUMMARY.md:47 +msgid "Deref Polymorphism" +msgstr "Utiliser deref pour simuler le polymorphisme" + +#: src/SUMMARY.md:49 +msgid "Functional Programming" +msgstr "Programmation fonctionnelle" + +#: src/SUMMARY.md:50 src/functional/paradigms.md:1 +msgid "Programming paradigms" +msgstr "Paradigmes de programmation" + +#: src/SUMMARY.md:51 src/functional/generics-type-classes.md:1 +msgid "Generics as Type Classes" +msgstr "Les génériques sont des classes de types" + +#: src/SUMMARY.md:52 +msgid "Functional Optics" +msgstr "Optics" + +#: src/SUMMARY.md:54 +msgid "Additional Resources" +msgstr "Ressources additionnelles" + +#: src/SUMMARY.md:55 src/additional_resources/design-principles.md:1 +msgid "Design principles" +msgstr "Principes de conception" + +#: src/intro.md:3 +msgid "Participation" +msgstr "" + +#: src/intro.md:5 +msgid "" +"If you are interested in contributing to this book, check out the " +"[contribution guidelines](https://github.com/rust-unofficial/patterns/blob/" +"master/CONTRIBUTING.md)." +msgstr "" + +#: src/intro.md:8 +msgid "News" +msgstr "" + +#: src/intro.md:10 +msgid "" +"**2024-03-17**: You can now download the book in PDF format from [this link]" +"(https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf)." +msgstr "" + +#: src/intro.md:13 +msgid "Design patterns" +msgstr "" + +#: src/intro.md:15 +msgid "" +"In software development, we often come across problems that share " +"similarities regardless of the environment they appear in. Although the " +"implementation details are crucial to solve the task at hand, we may " +"abstract from these particularities to find the common practices that are " +"generically applicable." +msgstr "" + +#: src/intro.md:20 +msgid "" +"Design patterns are a collection of reusable and tested solutions to " +"recurring problems in engineering. They make our software more modular, " +"maintainable, and extensible. Moreover, these patterns provide a common " +"language for developers, making them an excellent tool for effective " +"communication when problem-solving in teams." +msgstr "" + +#: src/intro.md:26 +msgid "" +"Keep in mind: Each pattern comes with its own set of trade-offs. It's " +"crucial to focus on why you choose a particular pattern rather than just on " +"how to implement it.[^1]" +msgstr "" + +#: src/intro.md:30 src/patterns/index.md:14 +msgid "Design patterns in Rust" +msgstr "" + +#: src/intro.md:32 +msgid "" +"Rust is not object-oriented, and the combination of all its characteristics, " +"such as functional elements, a strong type system, and the borrow checker, " +"makes it unique. Because of this, Rust design patterns vary with respect to " +"other traditional object-oriented programming languages. That's why we " +"decided to write this book. We hope you enjoy reading it! The book is " +"divided in three main chapters:" +msgstr "" + +#: src/intro.md:39 +msgid "" +"[Idioms](./idioms/index.md): guidelines to follow when coding. They are the " +"social norms of the community. You should break them only if you have a good " +"reason for it." +msgstr "" + +#: src/intro.md:42 +msgid "" +"[Design patterns](./patterns/index.md): methods to solve common problems " +"when coding." +msgstr "" + +#: src/intro.md:44 +msgid "" +"[Anti-patterns](./anti_patterns/index.md): methods to solve common problems " +"when coding. However, while design patterns give us benefits, anti-patterns " +"create more problems." +msgstr "" + +#: src/intro.md:48 +msgid "" +"https://web.archive.org/web/20240124025806/https://www.infoq.com/podcasts/" +"software-architecture-hard-parts/" +msgstr "" + +#: src/translations.md:3 +msgid "" +"We are utilizing [mdbook-i18n-helper](https://github.com/google/mdbook-i18n-" +"helpers). 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:8 +msgid "External translations" +msgstr "" + +#: src/translations.md:10 +msgid "[简体中文](https://fomalhauthmj.github.io/patterns/)" +msgstr "" + +#: src/translations.md:12 +msgid "" +"If you want to add a translation, please open an issue in the [main " +"repository](https://github.com/rust-unofficial/patterns)." +msgstr "" + +#: src/idioms/index.md:3 +msgid "" +"[Idioms](https://en.wikipedia.org/wiki/Programming_idiom) are commonly used " +"styles, guidelines and patterns largely agreed upon by a community. Writing " +"idiomatic code allows other developers to understand better what is " +"happening." +msgstr "" + +#: src/idioms/index.md:7 +msgid "" +"After all, the computer only cares about the machine code that is generated " +"by the compiler. Instead, the source code is mainly beneficial to the " +"developer. So, since we have this abstraction layer, why not make it more " +"readable?" +msgstr "" + +#: src/idioms/index.md:11 +msgid "" +"Remember the [KISS principle](https://en.wikipedia.org/wiki/KISS_principle): " +"\"Keep It Simple, Stupid\". It claims that \"most systems work best if they " +"are kept simple rather than made complicated; therefore, simplicity should " +"be a key goal in design, and unnecessary complexity should be avoided\"." +msgstr "" + +#: src/idioms/index.md:16 +msgid "Code is there for humans, not computers, to understand." +msgstr "" + +#: src/idioms/coercion-arguments.md:3 src/idioms/concat-format.md:3 +#: src/idioms/ctor.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/rustdoc-init.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:3 +#: 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 " +"when you are deciding which argument type to use for a function argument. 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. In fact, you should " +"always prefer using the **borrowed type** over **borrowing the owned type**. " +"Such as `&str` over `&String`, `&[T]` over `&Vec`, or `&T` over `&Box`." +msgstr "" + +#: src/idioms/coercion-arguments.md:13 +msgid "" +"Using borrowed types you can avoid layers of indirection for those instances " +"where the owned type already provides a layer of indirection. For instance, " +"a `String` has a layer of indirection, so a `&String` will have two layers " +"of indirection. We can avoid this by using `&str` instead, and letting " +"`&String` coerce to a `&str` whenever the function is invoked." +msgstr "" + +#: src/idioms/coercion-arguments.md:19 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:19 +#: src/idioms/rustdoc-init.md:45 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:12 +#: src/patterns/behavioural/strategy.md:30 +#: src/patterns/behavioural/visitor.md:13 src/patterns/creational/builder.md:7 +#: src/patterns/creational/fold.md:12 +#: src/patterns/structural/compose-structs.md:15 +#: 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:21 +msgid "" +"For this example, we will illustrate some differences for using `&String` as " +"a function argument versus using a `&str`, but the ideas apply as well to " +"using `&Vec` versus using a `&[T]` or using a `&Box` versus a `&T`." +msgstr "" + +#: src/idioms/coercion-arguments.md:25 +msgid "" +"Consider an example where we wish to determine if a word contains three " +"consecutive vowels. We don't need to own the string to determine this, so we " +"will take a reference." +msgstr "" + +#: src/idioms/coercion-arguments.md:29 +msgid "The code might look something like this:" +msgstr "" + +#: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 +msgid "'a'" +msgstr "" + +#: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 +msgid "'e'" +msgstr "" + +#: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 +msgid "'i'" +msgstr "" + +#: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 +msgid "'o'" +msgstr "" + +#: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 +msgid "'u'" +msgstr "" + +#: src/idioms/coercion-arguments.md:49 +msgid "\"Ferris\"" +msgstr "" + +#: src/idioms/coercion-arguments.md:50 +msgid "\"Curious\"" +msgstr "" + +#: src/idioms/coercion-arguments.md:51 src/idioms/coercion-arguments.md:52 +msgid "\"{}: {}\"" +msgstr "" + +#: src/idioms/coercion-arguments.md:54 +msgid "" +"// This works fine, but the following two lines would fail:\n" +" // println!(\"Ferris: {}\", three_vowels(\"Ferris\"));\n" +" // println!(\"Curious: {}\", three_vowels(\"Curious\"));\n" +msgstr "" + +#: src/idioms/coercion-arguments.md:60 +msgid "" +"This works fine because we are passing a `&String` type as a parameter. If " +"we remove the comments on the last two lines, the example will fail. This is " +"because a `&str` type will not coerce to a `&String` type. We can fix this " +"by simply modifying the type for our argument." +msgstr "" + +#: src/idioms/coercion-arguments.md:65 +msgid "For instance, if we change our function declaration to:" +msgstr "" + +#: src/idioms/coercion-arguments.md:71 +msgid "then both versions will compile and print the same output." +msgstr "" + +#: src/idioms/coercion-arguments.md:78 +msgid "" +"But wait, that's not all! There is more to this story. It's likely that you " +"may say to yourself: that doesn't matter, I will never be using a `&'static " +"str` as an input anyways (as we did when we used `\"Ferris\"`). Even " +"ignoring this special example, you may still find that using `&str` will " +"give you more flexibility than using a `&String`." +msgstr "" + +#: src/idioms/coercion-arguments.md:84 +msgid "" +"Let's now take an example where someone gives us a sentence, and we want to " +"determine if any of the words in the sentence contain three consecutive " +"vowels. We probably should make use of the function we have already defined " +"and simply feed in each word from the sentence." +msgstr "" + +#: src/idioms/coercion-arguments.md:89 +msgid "An example of this could look like this:" +msgstr "" + +#: src/idioms/coercion-arguments.md:110 +msgid "\"Once upon a time, there was a friendly curious crab named Ferris\"" +msgstr "" + +#: src/idioms/coercion-arguments.md:111 +msgid "' '" +msgstr "" + +#: src/idioms/coercion-arguments.md:113 +msgid "\"{word} has three consecutive vowels!\"" +msgstr "" + +#: src/idioms/coercion-arguments.md:119 +msgid "" +"Running this example using our function declared with an argument type " +"`&str` will yield" +msgstr "" + +#: src/idioms/coercion-arguments.md:126 +msgid "" +"However, this example will not run when our function is declared with an " +"argument type `&String`. This is because string slices are a `&str` and not " +"a `&String` which would require an allocation to be converted to `&String` " +"which is not implicit, whereas converting from `String` to `&str` is cheap " +"and implicit." +msgstr "" + +#: src/idioms/coercion-arguments.md:132 src/idioms/ctor.md:101 +#: src/idioms/default.md:58 src/idioms/deref.md:76 +#: src/idioms/dtor-finally.md:93 src/idioms/mem-replace.md:116 +#: src/idioms/on-stack-dyn-dispatch.md:80 src/idioms/option-iter.md:47 +#: src/idioms/priv-extend.md:118 src/patterns/behavioural/command.md:218 +#: src/patterns/behavioural/interpreter.md:144 +#: src/patterns/behavioural/newtype.md:94 src/patterns/behavioural/RAII.md:112 +#: src/patterns/behavioural/strategy.md:178 +#: src/patterns/behavioural/visitor.md:108 +#: src/patterns/creational/builder.md:109 src/patterns/creational/fold.md:109 +#: src/patterns/structural/small-crates.md:45 +#: src/patterns/structural/unsafe-mods.md:33 +#: src/anti_patterns/borrow_clone.md:65 src/anti_patterns/deny-warnings.md:101 +#: src/anti_patterns/deref.md:124 src/functional/generics-type-classes.md:236 +msgid "See also" +msgstr "" + +#: src/idioms/coercion-arguments.md:134 +msgid "" +"[Rust Language Reference on Type Coercions](https://doc.rust-lang.org/" +"reference/type-coercions.html)" +msgstr "" + +#: src/idioms/coercion-arguments.md:135 +msgid "" +"For more discussion on how to handle `String` and `&str` see [this blog " +"series (2015)](https://web.archive.org/web/20201112023149/https://" +"hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html) by Herman " +"J. Radtke III" +msgstr "" + +#: src/idioms/coercion-arguments.md:138 +msgid "" +"[Steve Klabnik's Blogpost on 'When should I use String vs &str?'](https://" +"archive.ph/LBpD0)" +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 mutable `String`, or using its `+` operator. However, it is often more " +"convenient to use `format!`, especially where there is a mix of literal and " +"non-literal strings." +msgstr "" + +#: src/idioms/concat-format.md:14 +msgid "" +"// 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" +msgstr "" + +#: src/idioms/concat-format.md:20 +msgid "// But using format! is better.\n" +msgstr "" + +#: src/idioms/concat-format.md:21 +msgid "\"Hello {name}!\"" +msgstr "" + +#: src/idioms/concat-format.md:25 src/idioms/deref.md:43 +#: src/idioms/dtor-finally.md:46 src/idioms/mem-replace.md:91 +#: src/idioms/on-stack-dyn-dispatch.md:43 src/idioms/ffi/errors.md:128 +#: src/idioms/ffi/accepting-strings.md:65 src/idioms/ffi/passing-strings.md:66 +#: src/idioms/pass-var-to-closure.md:48 src/idioms/rustdoc-init.md:77 +#: src/idioms/temporary-mutability.md:38 +#: src/idioms/return-consumed-arg-on-error.md:55 +#: src/patterns/behavioural/newtype.md:55 src/patterns/behavioural/RAII.md:79 +#: src/patterns/behavioural/strategy.md:98 +#: src/patterns/creational/builder.md:68 +#: src/patterns/structural/compose-structs.md:106 +#: src/patterns/structural/small-crates.md:13 +#: src/patterns/structural/unsafe-mods.md:12 src/patterns/ffi/export.md:113 +#: src/patterns/ffi/wrappers.md:64 src/anti_patterns/deny-warnings.md:16 +#: src/anti_patterns/deref.md:69 src/functional/generics-type-classes.md:209 +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:30 src/idioms/deref.md:50 +#: src/idioms/dtor-finally.md:51 src/idioms/mem-replace.md:95 +#: src/idioms/on-stack-dyn-dispatch.md:49 src/idioms/ffi/errors.md:133 +#: src/idioms/ffi/accepting-strings.md:136 +#: src/idioms/ffi/passing-strings.md:101 src/idioms/pass-var-to-closure.md:57 +#: src/idioms/priv-extend.md:104 src/idioms/rustdoc-init.md:81 +#: src/idioms/temporary-mutability.md:42 +#: src/idioms/return-consumed-arg-on-error.md:59 +#: src/patterns/behavioural/newtype.md:66 +#: src/patterns/behavioural/strategy.md:107 +#: src/patterns/creational/builder.md:76 +#: src/patterns/structural/compose-structs.md:111 +#: src/patterns/structural/small-crates.md:22 +#: src/patterns/structural/unsafe-mods.md:18 src/patterns/ffi/export.md:236 +#: src/patterns/ffi/wrappers.md:70 src/anti_patterns/deref.md:81 +#: src/functional/generics-type-classes.md:220 +msgid "Disadvantages" +msgstr "" + +#: src/idioms/concat-format.md:32 +msgid "" +"It is usually not the most efficient way to combine strings - a series of " +"`push` operations on a mutable string is usually the most efficient " +"(especially if the string has been pre-allocated to the expected size)." +msgstr "" + +#: src/idioms/ctor.md:1 +msgid "Constructors" +msgstr "" + +#: src/idioms/ctor.md:5 +msgid "" +"Rust does not have constructors as a language construct. Instead, the " +"convention is to use an [associated function](https://doc.rust-lang.org/" +"stable/book/ch05-03-method-syntax.html#associated-functions) `new` to create " +"an object:" +msgstr "" + +#: src/idioms/ctor.md:10 +msgid "" +"/// Time in seconds.\n" +"///\n" +"/// # Example\n" +"///\n" +"/// ```\n" +"/// let s = Second::new(42);\n" +"/// assert_eq!(42, s.value());\n" +"/// ```\n" +msgstr "" + +#: src/idioms/ctor.md:23 +msgid "" +"// Constructs a new instance of [`Second`].\n" +" // Note this is an associated function - no self.\n" +msgstr "" + +#: src/idioms/ctor.md:29 src/idioms/ctor.md:54 src/idioms/ctor.md:85 +msgid "/// Returns the value in seconds.\n" +msgstr "" + +#: src/idioms/ctor.md:36 +msgid "Default Constructors" +msgstr "" + +#: src/idioms/ctor.md:38 +msgid "" +"Rust supports default constructors with the [`Default`](https://doc.rust-" +"lang.org/stable/std/default/trait.Default.html) trait:" +msgstr "" + +#: src/idioms/ctor.md:41 src/idioms/ctor.md:71 +msgid "" +"/// Time in seconds.\n" +"///\n" +"/// # Example\n" +"///\n" +"/// ```\n" +"/// let s = Second::default();\n" +"/// assert_eq!(0, s.value());\n" +"/// ```\n" +msgstr "" + +#: src/idioms/ctor.md:67 +msgid "" +"`Default` can also be derived if all types of all fields implement " +"`Default`, like they do with `Second`:" +msgstr "" + +#: src/idioms/ctor.md:92 +msgid "" +"**Note:** It is common and expected for types to implement both `Default` " +"and an empty `new` constructor. `new` is the constructor convention in Rust, " +"and users expect it to exist, so if it is reasonable for the basic " +"constructor to take no arguments, then it 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 can now be used where a `Default` implementation is required, most " +"prominently, any of the [`*or_default` functions in the standard library]" +"(https://doc.rust-lang.org/stable/std/?search=or_default)." +msgstr "" + +#: src/idioms/ctor.md:103 +msgid "" +"The [default idiom](default.md) for a more in-depth description of the " +"`Default` trait." +msgstr "" + +#: src/idioms/ctor.md:106 +msgid "" +"The [builder pattern](../patterns/creational/builder.md) for constructing " +"objects where there are multiple configurations." +msgstr "" + +#: src/idioms/ctor.md:109 +msgid "" +"[API Guidelines/C-COMMON-TRAITS](https://rust-lang.github.io/api-guidelines/" +"interoperability.html#types-eagerly-implement-common-traits-c-common-traits) " +"for implementing both, `Default` and `new`." +msgstr "" + +#: src/idioms/default.md:1 +msgid "The `Default` Trait" +msgstr "" + +#: src/idioms/default.md:5 +msgid "" +"Many types in Rust have a [constructor](ctor.md). However, this is " +"_specific_ to the type; Rust cannot abstract over \"everything that has a " +"`new()` method\". To allow this, the [`Default`](https://doc.rust-lang.org/" +"stable/std/default/trait.Default.html) trait was conceived, which can be " +"used with containers and other generic types (e.g. see " +"[`Option::unwrap_or_default()`](https://doc.rust-lang.org/stable/std/option/" +"enum.Option.html#method.unwrap_or_default)). 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 " +"`Default` for contained `Default` types, one can automatically " +"`#[derive(Default)]` for structs whose fields all implement it, so the more " +"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 " +"`default()` method does not. There can even be multiple constructors with " +"different names, but there can only be one `Default` implementation per type." +msgstr "" + +#: src/idioms/default.md:24 +msgid "// note that we can simply auto-derive Default here.\n" +msgstr "" + +#: src/idioms/default.md:28 +msgid "// Option defaults to None\n" +msgstr "" + +#: src/idioms/default.md:30 +msgid "// Vecs default to empty vector\n" +msgstr "" + +#: src/idioms/default.md:32 +msgid "// Duration defaults to zero time\n" +msgstr "" + +#: src/idioms/default.md:34 +msgid "// bool defaults to false\n" +msgstr "" + +#: src/idioms/default.md:39 +msgid "// add setters here\n" +msgstr "" + +#: src/idioms/default.md:43 +msgid "// construct a new instance with default values\n" +msgstr "" + +#: src/idioms/default.md:45 +msgid "// do something with conf here\n" +msgstr "" + +#: src/idioms/default.md:47 +msgid "\"conf = {conf:#?}\"" +msgstr "" + +#: src/idioms/default.md:49 +msgid "" +"// partial initialization with default values, creates the same instance\n" +msgstr "" + +#: src/idioms/default.md:60 +msgid "" +"The [constructor](ctor.md) idiom is another way to generate instances that " +"may or may not be \"default\"" +msgstr "" + +#: src/idioms/default.md:62 +msgid "" +"The [`Default`](https://doc.rust-lang.org/stable/std/default/" +"trait.Default.html) documentation (scroll down for the list of implementors)" +msgstr "" + +#: src/idioms/default.md:63 +msgid "" +"[`Option::unwrap_or_default()`](https://doc.rust-lang.org/stable/std/option/" +"enum.Option.html#method.unwrap_or_default)" +msgstr "" + +#: src/idioms/default.md:64 +msgid "[`derive(new)`](https://crates.io/crates/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) trait " +"to treat collections like smart pointers, offering owning and borrowed views " +"of data." +msgstr "" + +#: src/idioms/deref.md:16 src/idioms/deref.md:23 +#: src/patterns/behavioural/RAII.md:29 src/patterns/behavioural/RAII.md:41 +#: src/patterns/behavioural/RAII.md:100 src/anti_patterns/deref.md:35 +msgid "//..\n" +msgstr "" + +#: src/idioms/deref.md:28 +msgid "" +"A `Vec` is an owning collection of `T`s, while a slice (`&[T]`) is a " +"borrowed collection of `T`s. Implementing `Deref` for `Vec` allows implicit " +"dereferencing from `&Vec` to `&[T]` and includes the relationship in auto-" +"dereferencing searches. Most methods you might expect to be implemented for " +"`Vec`s are instead 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:36 +#: src/idioms/mem-replace.md:63 src/idioms/on-stack-dyn-dispatch.md:32 +#: src/idioms/ffi/accepting-strings.md:12 src/idioms/ffi/passing-strings.md:14 +#: src/idioms/rustdoc-init.md:9 src/idioms/return-consumed-arg-on-error.md:45 +#: src/patterns/behavioural/command.md:8 +#: src/patterns/behavioural/interpreter.md:17 +#: src/patterns/behavioural/newtype.md:45 src/patterns/behavioural/RAII.md:73 +#: src/patterns/behavioural/strategy.md:21 +#: src/patterns/behavioural/visitor.md:74 src/patterns/creational/builder.md:63 +#: src/patterns/creational/fold.md:73 +#: src/patterns/structural/compose-structs.md:100 src/patterns/ffi/export.md:16 +#: 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 must account for these semantics properly to give a good user " +"experience. When implementing a data structure that owns its data, offering " +"a 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 " +"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 when bounds checking, so generic programming with data structures " +"using this pattern can get complex (see the `Borrow` and `AsRef` traits, " +"etc.)." +msgstr "" + +#: src/idioms/deref.md:56 src/idioms/dtor-finally.md:66 +#: src/idioms/mem-replace.md:105 src/idioms/on-stack-dyn-dispatch.md:66 +#: src/idioms/priv-extend.md:87 src/idioms/rustdoc-init.md:88 +#: src/patterns/behavioural/command.md:203 +#: src/patterns/behavioural/interpreter.md:105 +#: src/patterns/behavioural/newtype.md:74 src/patterns/behavioural/RAII.md:84 +#: src/patterns/behavioural/strategy.md:113 +#: src/patterns/behavioural/visitor.md:81 src/patterns/creational/builder.md:81 +#: src/patterns/creational/fold.md:85 +#: src/patterns/structural/compose-structs.md:117 +#: 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 object, whereas a collection points to many objects. From the point " +"of view of the type system, there is little difference between the two. A " +"collection owns its data if the only way to access each datum is via the " +"collection and the collection is responsible for deleting the data (even in " +"cases of shared ownership, some kind of borrowed view may be appropriate). " +"If a collection owns its data, it is usually useful to provide a view of the " +"data as borrowed so that it can be referenced multiple times." +msgstr "" + +#: src/idioms/deref.md:67 +msgid "" +"Most smart pointers (e.g., `Foo`) implement `Deref`. However, " +"collections will usually dereference to a custom type. `[T]` and `str` have " +"some language support, but in the general case, this is not necessary. " +"`Foo` can implement `Deref>` where `Bar` is a dynamically " +"sized type and `&Bar` is a borrowed view of the data in `Foo`." +msgstr "" + +#: src/idioms/deref.md:73 +msgid "" +"Commonly, ordered collections will implement `Index` for `Range`s to provide " +"slicing syntax. The target will be the borrowed view." +msgstr "" + +#: src/idioms/deref.md:78 +msgid "[Deref polymorphism anti-pattern](../anti_patterns/deref.md)." +msgstr "" + +#: src/idioms/deref.md:79 src/anti_patterns/deref.md:130 +msgid "" +"[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 " +"executed no matter how a function is exited. Instead, an object's destructor " +"can be used to run code that must be run before exit." +msgstr "" + +#: src/idioms/dtor-finally.md:13 +msgid "// some code\n" +msgstr "" + +#: src/idioms/dtor-finally.md:17 +msgid "// These don't need to be defined inside the function.\n" +msgstr "" + +#: src/idioms/dtor-finally.md:20 +msgid "// Implement a destructor for Foo.\n" +msgstr "" + +#: src/idioms/dtor-finally.md:23 +msgid "\"exit\"" +msgstr "" + +#: src/idioms/dtor-finally.md:27 +msgid "// The dtor of _exit will run however the function `bar` is exited.\n" +msgstr "" + +#: src/idioms/dtor-finally.md:29 +msgid "// Implicit return with `?` operator.\n" +msgstr "" + +#: src/idioms/dtor-finally.md:31 +msgid "// Normal return.\n" +msgstr "" + +#: src/idioms/dtor-finally.md:38 +msgid "" +"If a function has multiple return points, then executing code on exit " +"becomes difficult and repetitive (and thus bug-prone). This is especially " +"the case where return is implicit due to a macro. A common case is the `?` " +"operator which returns if the result is an `Err`, but continues if it is " +"`Ok`. `?` is used as an exception handling mechanism, but unlike Java (which " +"has `finally`), there is no way to schedule code to run in both the normal " +"and exceptional cases. Panicking will also exit a function early." +msgstr "" + +#: src/idioms/dtor-finally.md:48 +msgid "" +"Code in destructors will (nearly) always be run - copes with panics, early " +"returns, etc." +msgstr "" + +#: src/idioms/dtor-finally.md:53 +msgid "" +"It is not guaranteed that destructors will run. For example, if there is an " +"infinite loop in a function or if running a function crashes before exit. " +"Destructors are also not run in the case of a panic in an already panicking " +"thread. Therefore, destructors cannot be relied on as finalizers where it is " +"absolutely essential that finalisation happens." +msgstr "" + +#: src/idioms/dtor-finally.md:59 +msgid "" +"This pattern introduces some hard to notice, implicit code. Reading a " +"function gives no clear indication of destructors to be run on exit. This " +"can make debugging tricky." +msgstr "" + +#: src/idioms/dtor-finally.md:63 +msgid "" +"Requiring an object and `Drop` impl just for finalisation is heavy on " +"boilerplate." +msgstr "" + +#: src/idioms/dtor-finally.md:68 +msgid "" +"There is some subtlety about how exactly to store the object used as a " +"finalizer. It must be kept alive until the end of the function and must then " +"be destroyed. The object must always be a value or uniquely owned pointer " +"(e.g., `Box`). If a shared pointer (such as `Rc`) is used, then the " +"finalizer can be kept alive beyond the lifetime of the function. For similar " +"reasons, the finalizer should not be moved or returned." +msgstr "" + +#: src/idioms/dtor-finally.md:75 +msgid "" +"The finalizer must be assigned into a variable, otherwise it will be " +"destroyed immediately, rather than when it goes out of scope. The variable " +"name must start with `_` if the variable is only used as a finalizer, " +"otherwise the compiler will warn that the finalizer is never used. However, " +"do not call the variable `_` with no suffix - in that case it will be " +"destroyed immediately." +msgstr "" + +#: src/idioms/dtor-finally.md:81 +msgid "" +"In Rust, destructors are run when an object goes out of scope. This happens " +"whether we reach the end of block, there is an early return, or the program " +"panics. When panicking, Rust unwinds the stack running destructors for each " +"object in each stack frame. So, destructors get called even if the panic " +"happens in a function being called." +msgstr "" + +#: src/idioms/dtor-finally.md:87 +msgid "" +"If a destructor panics while unwinding, there is no good action to take, so " +"Rust aborts the thread immediately, without running further destructors. " +"This means that destructors are not absolutely guaranteed to run. It also " +"means that you must take extra care in your destructors not to panic, since " +"it could leave resources in an unexpected state." +msgstr "" + +#: src/idioms/dtor-finally.md:95 +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, `A { name: " +"String, x: u8 }` and `B { name: String }`. Now we want to change `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:23 +msgid "" +"// This takes out our `name` and puts 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" +msgstr "" + +#: src/idioms/mem-replace.md:34 +msgid "This also works with more variants:" +msgstr "" + +#: src/idioms/mem-replace.md:49 +msgid "" +"// 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" +msgstr "" + +#: src/idioms/mem-replace.md:65 +msgid "" +"When working with enums, we may want to change an enum value in place, " +"perhaps to another variant. This is usually done in two phases to keep the " +"borrow checker happy. In the first phase, we observe the existing value and " +"look at its parts to decide what to do next. In the second phase we may " +"conditionally change the value (as in the example above)." +msgstr "" + +#: src/idioms/mem-replace.md:71 +msgid "" +"The borrow checker won't allow us to take out `name` of the enum (because " +"_something_ must be there.) We could of course `.clone()` name and put the " +"clone 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 can avoid the extra allocation by changing `e` with only a " +"mutable borrow." +msgstr "" + +#: src/idioms/mem-replace.md:78 +msgid "" +"`mem::take` lets us swap out the value, replacing it with its default value, " +"and returning the previous value. For `String`, the default value is an " +"empty `String`, which does not need to allocate. As a result, we get the " +"original `name` _as an owned value_. We can then wrap this in another enum." +msgstr "" + +#: src/idioms/mem-replace.md:83 +msgid "" +"**NOTE:** `mem::replace` is very similar, but allows us to specify what to " +"replace the value with. An equivalent to our `mem::take` line would be " +"`mem::replace(name, String::new())`." +msgstr "" + +#: src/idioms/mem-replace.md:87 +msgid "" +"Note, however, that if we are using an `Option` and want to replace its " +"value with a `None`, `Option`’s `take()` method provides a shorter and more " +"idiomatic alternative." +msgstr "" + +#: src/idioms/mem-replace.md:93 +msgid "" +"Look ma, no allocation! Also you may feel like Indiana Jones while doing it." +msgstr "" + +#: src/idioms/mem-replace.md:97 +msgid "" +"This gets a bit wordy. Getting it wrong repeatedly will make you hate the " +"borrow checker. The compiler may fail to optimize away the double store, " +"resulting in reduced performance as opposed to what you'd do in unsafe " +"languages." +msgstr "" + +#: src/idioms/mem-replace.md:101 +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 implement " +"this, you can instead use `mem::replace`." +msgstr "" + +#: src/idioms/mem-replace.md:107 +msgid "" +"This pattern is only of interest in Rust. In GC'd languages, you'd take the " +"reference to the value by default (and the GC would keep track of refs), and " +"in other low-level languages like C you'd simply alias the pointer and fix " +"things later." +msgstr "" + +#: src/idioms/mem-replace.md:112 +msgid "" +"However, in Rust, we have to do a little more work to do this. An owned " +"value may only have one owner, so to take it out, we need to put something " +"back in – like Indiana Jones, replacing the artifact with a bag of sand." +msgstr "" + +#: src/idioms/mem-replace.md:118 +msgid "" +"This gets rid of the [Clone to satisfy the borrow checker](../anti_patterns/" +"borrow_clone.md) anti-pattern in a specific case." +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:5 +msgid "" +"We can dynamically dispatch over multiple values, however, to do so, we need " +"to declare multiple variables to bind differently-typed objects. To extend " +"the lifetime as necessary, we can use deferred conditional initialization, " +"as seen below:" +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:17 +#: src/idioms/on-stack-dyn-dispatch.md:20 +#: src/idioms/on-stack-dyn-dispatch.md:56 +msgid "\"-\"" +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:18 +msgid "// We need to describe the type to get dynamic dispatch.\n" +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:25 +#: src/idioms/on-stack-dyn-dispatch.md:60 +msgid "// Read from `readable` here.\n" +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:34 +msgid "" +"Rust monomorphises code by default. This means a copy of the code will be " +"generated for each type it is used with and optimized independently. While " +"this allows for very fast code on the hot path, it also bloats the code in " +"places where performance is not of the essence, thus costing compile time " +"and cache usage." +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:40 +msgid "" +"Luckily, Rust allows us to use dynamic dispatch, but we have to explicitly " +"ask for it." +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:45 +msgid "" +"We do not need to allocate anything on the heap. Neither do we need to " +"initialize something we won't use later, nor do we need to monomorphize the " +"whole code that follows to work with both `File` or `Stdin`." +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:51 +msgid "" +"Before Rust 1.79.0, the code needed two `let` bindings with deferred " +"initialization, which made up more moving parts than the `Box`\\-based " +"version:" +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:55 +msgid "// We still need to ascribe the type for dynamic dispatch.\n" +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:64 +msgid "Luckily, this disadvantage is now gone. Yay!" +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:68 +msgid "" +"Since Rust 1.79.0, the compiler will automatically extend the lifetimes of " +"temporary values within `&` or `&mut` as long as possible within the scope " +"of the function." +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:72 +msgid "" +"This means we can simply use a `&mut` value here without worrying about " +"placing the contents into some `let` binding (which would have been needed " +"for deferred initialization, which was the solution used before that change)." +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:76 +msgid "" +"We still have a place for each value (even if that place is temporary), the " +"compiler knows the size of each value and each borrowed value outlives all " +"references borrowed from it." +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:82 +msgid "" +"[Finalisation in destructors](dtor-finally.md) and [RAII guards](../patterns/" +"behavioural/RAII.md) can benefit from tight control over lifetimes." +msgstr "" + +#: src/idioms/on-stack-dyn-dispatch.md:85 +msgid "" +"For conditionally filled `Option<&T>`s of (mutable) references, one can " +"initialize an `Option` directly and use its [`.as_ref()`](https://" +"doc.rust-lang.org/std/option/enum.Option.html#method.as_ref) method to get " +"an 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. However, there are several " +"idioms here that can act as pointers, and avoid 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 "" +"[Idiomatic Errors](./errors.md) - Error handling with integer codes and " +"sentinel return values (such as `NULL` pointers)" +msgstr "" + +#: src/idioms/ffi/intro.md:12 +msgid "[Accepting Strings](./accepting-strings.md) with minimal unsafe code" +msgstr "" + +#: src/idioms/ffi/intro.md:14 +msgid "[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. " +"However, Rust's type system allows much more rich error information to be " +"captured and propagated 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 in a usable way:" +msgstr "" + +#: src/idioms/ffi/errors.md:12 +msgid "Flat Enums should be converted to integers and returned as codes." +msgstr "" + +#: src/idioms/ffi/errors.md:13 +msgid "" +"Structured Enums should be converted to an integer code with a string error " +"message for detail." +msgstr "" + +#: src/idioms/ffi/errors.md:15 +msgid "" +"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:44 +#: src/patterns/ffi/wrappers.md:24 +msgid "Code Example" +msgstr "" + +#: src/idioms/ffi/errors.md:19 +msgid "Flat Enums" +msgstr "" + +#: src/idioms/ffi/errors.md:23 +msgid "// user attempted a write operation\n" +msgstr "" + +#: src/idioms/ffi/errors.md:24 +msgid "// user should read the C errno() for what it was\n" +msgstr "" + +#: src/idioms/ffi/errors.md:25 +msgid "// user should run a repair tool to recover it\n" +msgstr "" + +#: src/idioms/ffi/errors.md:35 +msgid "Structured Enums" +msgstr "" + +#: src/idioms/ffi/errors.md:42 +msgid "// message describing the issue\n" +msgstr "" + +#: src/idioms/ffi/errors.md:61 src/idioms/ffi/accepting-strings.md:47 +#: src/idioms/ffi/accepting-strings.md:79 src/idioms/ffi/passing-strings.md:33 +#: src/patterns/ffi/export.md:154 src/patterns/ffi/export.md:158 +#: src/patterns/ffi/export.md:165 +msgid "\"C\"" +msgstr "" + +#: src/idioms/ffi/errors.md:64 +msgid "" +"// SAFETY: we assume that the lifetime of `e` is greater than\n" +" // the current stack frame.\n" +msgstr "" + +#: src/idioms/ffi/errors.md:70 +msgid "\"cannot write to read-only database\"" +msgstr "" + +#: src/idioms/ffi/errors.md:73 +msgid "\"I/O Error: {e}\"" +msgstr "" + +#: src/idioms/ffi/errors.md:76 +msgid "\"File corrupted, run repair: {}\"" +msgstr "" + +#: src/idioms/ffi/errors.md:83 +msgid "" +"// SAFETY: copying error_bytes to an allocated buffer with a '\\0'\n" +" // byte at the end.\n" +msgstr "" + +#: src/idioms/ffi/errors.md:99 +msgid "Custom Error Types" +msgstr "" + +#: src/idioms/ffi/errors.md:109 src/idioms/ffi/accepting-strings.md:48 +#: src/idioms/ffi/accepting-strings.md:83 src/patterns/creational/builder.md:30 +#: src/patterns/ffi/export.md:137 src/patterns/ffi/export.md:139 +msgid "/* ... */" +msgstr "" + +#: src/idioms/ffi/errors.md:111 +msgid "/* Create a second version which is exposed as a C structure */" +msgstr "" + +#: src/idioms/ffi/errors.md:130 +msgid "" +"This ensures that the foreign language has clear access to error information " +"while not compromising the Rust code's API at all." +msgstr "" + +#: src/idioms/ffi/errors.md:135 +msgid "" +"It's a lot of typing, and some types may not be able to be converted easily " +"to C." +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:5 +msgid "" +"When accepting strings via FFI through pointers, there are two principles " +"that should be followed:" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:8 +msgid "Keep foreign strings \"borrowed\", rather than copying them directly." +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:9 +msgid "" +"Minimize the amount of complexity and `unsafe` code involved in converting " +"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" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:17 +msgid "" +"C strings can contain any arbitrary non-zero byte while Rust strings must be " +"UTF-8" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:19 +msgid "" +"C strings are accessed and manipulated using `unsafe` pointer operations " +"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` called `CString` and `&CStr`, that allow us to avoid a lot of the " +"complexity 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 " +"strings between Rust and C is a zero-cost operation." +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:34 +#: src/idioms/ffi/accepting-strings.md:77 src/idioms/ffi/passing-strings.md:31 +#: src/idioms/ffi/passing-strings.md:80 src/patterns/ffi/wrappers.md:114 +msgid "// other module content\n" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:36 +msgid "" +"/// 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" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:50 +msgid "" +"// SAFETY: The caller has already guaranteed this is okay (see the\n" +" // `# Safety` section of the doc-comment).\n" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:55 +#: src/idioms/ffi/accepting-strings.md:105 +msgid "\"FFI string conversion failed\"" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:67 +msgid "The example is written to ensure that:" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:69 src/idioms/ffi/passing-strings.md:70 +msgid "The `unsafe` block is as small as possible." +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:70 +msgid "" +"The pointer with an \"untracked\" lifetime becomes a \"tracked\" shared " +"reference" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:72 +msgid "Consider an alternative, where the string is actually copied:" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:80 +msgid "" +"// DO NOT USE THIS CODE.\n" +" // IT IS UGLY, VERBOSE, AND CONTAINS A SUBTLE BUG.\n" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:85 +msgid "/* SAFETY: strlen is what it is, I guess? */" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:92 +msgid "" +"// SAFETY: copying from a foreign pointer expected to live\n" +" // for the entire stack frame into owned memory\n" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:116 +msgid "This code is inferior to the original in two respects:" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:118 +msgid "" +"There is much more `unsafe` code, and more importantly, more invariants it " +"must uphold." +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:120 +msgid "" +"Due to the extensive arithmetic required, there is a bug in this version " +"that cases Rust `undefined behaviour`." +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:123 +msgid "" +"The bug here is a simple mistake in pointer arithmetic: the string was " +"copied, all `msg_len` bytes of it. However, the `NUL` terminator at the end " +"was not." +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:126 +msgid "" +"The Vector then had its size _set_ to the length of the _zero padded string_ " +"-- rather than _resized_ to it, which could have added a zero at the end. As " +"a result, the last byte in the Vector is uninitialized memory. When the " +"`CString` is created at the bottom of the block, its read of the Vector will " +"cause `undefined behaviour`!" +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:132 +msgid "" +"Like many such issues, this would be difficult issue to track down. " +"Sometimes it would panic because the string was not `UTF-8`, sometimes it " +"would put a weird character at the end of the string, sometimes it would " +"just completely crash." +msgstr "" + +#: src/idioms/ffi/accepting-strings.md:138 +#: src/idioms/ffi/passing-strings.md:103 +msgid "None?" +msgstr "" + +#: src/idioms/ffi/passing-strings.md:5 +msgid "" +"When passing strings to FFI functions, there are four principles that should " +"be followed:" +msgstr "" + +#: src/idioms/ffi/passing-strings.md:8 +msgid "Make the lifetime of owned strings as long as possible." +msgstr "" + +#: src/idioms/ffi/passing-strings.md:9 +msgid "Minimize `unsafe` code during the conversion." +msgstr "" + +#: src/idioms/ffi/passing-strings.md:10 +msgid "" +"If the C code can modify the string data, use `Vec` instead of `CString`." +msgstr "" + +#: src/idioms/ffi/passing-strings.md:11 +msgid "" +"Unless the Foreign Function API requires it, the ownership of the string " +"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` " +"types. However, there are different approaches one can take with strings " +"that 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 " +"`unsafe` code. However, a secondary caveat is that _the object must live " +"long enough_, meaning the lifetime should be maximized. In addition, the " +"documentation explains that \"round-tripping\" a `CString` after " +"modification is UB, so additional work is necessary in that case." +msgstr "" + +#: src/idioms/ffi/passing-strings.md:42 +msgid "" +"// SAFETY: calling an FFI whose documentation says the pointer is\n" +" // const, so no modification should occur\n" +msgstr "" + +#: src/idioms/ffi/passing-strings.md:48 +msgid "// The lifetime of c_err continues until here\n" +msgstr "" + +#: src/idioms/ffi/passing-strings.md:54 +msgid "" +"// SAFETY: calling an FFI whose documentation implies\n" +" // that the input need only live as long as the call\n" +msgstr "" + +#: src/idioms/ffi/passing-strings.md:68 +msgid "The example is written in a way to ensure that:" +msgstr "" + +#: src/idioms/ffi/passing-strings.md:71 +msgid "The `CString` lives long enough." +msgstr "" + +#: src/idioms/ffi/passing-strings.md:72 +msgid "Errors with typecasts are always propagated when possible." +msgstr "" + +#: src/idioms/ffi/passing-strings.md:74 +msgid "" +"A common mistake (so common it's in the documentation) is to not use the " +"variable in the first block:" +msgstr "" + +#: src/idioms/ffi/passing-strings.md:84 +msgid "// SAFETY: whoops, this contains a dangling pointer!\n" +msgstr "" + +#: src/idioms/ffi/passing-strings.md:92 +msgid "" +"This code will result in a dangling pointer, because the lifetime of the " +"`CString` is not extended by the pointer creation, unlike if a reference " +"were created." +msgstr "" + +#: src/idioms/ffi/passing-strings.md:96 +msgid "" +"Another issue frequently raised is that the initialization of a 1k vector of " +"zeroes is \"slow\". However, recent versions of Rust actually optimize that " +"particular macro to a call to `zmalloc`, meaning it is as fast as the " +"operating 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 " +"element. In particular, it implements the `IntoIterator` trait, and as such " +"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:23 +msgid "Examples" +msgstr "" + +#: src/idioms/option-iter.md:11 +msgid "" +"Since `Option` implements `IntoIterator`, it can be used as an argument to " +"[`.extend()`](https://doc.rust-lang.org/std/iter/" +"trait.Extend.html#tymethod.extend):" +msgstr "" + +#: src/idioms/option-iter.md:15 src/idioms/option-iter.md:31 +msgid "\"Turing\"" +msgstr "" + +#: src/idioms/option-iter.md:16 src/idioms/option-iter.md:32 +msgid "\"Curry\"" +msgstr "" + +#: src/idioms/option-iter.md:16 src/idioms/option-iter.md:32 +msgid "\"Kleene\"" +msgstr "" + +#: src/idioms/option-iter.md:16 src/idioms/option-iter.md:32 +msgid "\"Markov\"" +msgstr "" + +#: src/idioms/option-iter.md:19 +msgid "// equivalent to\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 " +"pass it to [`.chain()`](https://doc.rust-lang.org/std/iter/" +"trait.Iterator.html#method.chain):" +msgstr "" + +#: src/idioms/option-iter.md:35 +msgid "\"{logician} is a logician\"" +msgstr "" + +#: src/idioms/option-iter.md:39 +msgid "" +"Note that if the `Option` is always `Some`, then it is more idiomatic to use " +"[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) on the " +"element instead." +msgstr "" + +#: src/idioms/option-iter.md:43 +msgid "" +"Also, since `Option` implements `IntoIterator`, it's possible to iterate " +"over it using a `for` loop. This is equivalent to matching it with `if let " +"Some(..)`, and in most cases you should prefer the latter." +msgstr "" + +#: src/idioms/option-iter.md:49 +msgid "" +"[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) is an " +"iterator which yields exactly one element. It's a more readable alternative " +"to `Some(foo).into_iter()`." +msgstr "" + +#: src/idioms/option-iter.md:53 +msgid "" +"[`Iterator::filter_map`](https://doc.rust-lang.org/std/iter/" +"trait.Iterator.html#method.filter_map) is a version of [`Iterator::map`]" +"(https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map), " +"specialized to mapping functions which return `Option`." +msgstr "" + +#: src/idioms/option-iter.md:58 +msgid "" +"The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides " +"functions for converting an `Option` to a zero- or one-element slice." +msgstr "" + +#: src/idioms/option-iter.md:61 +msgid "" +"[Documentation for `Option`](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 " +"a `move`\\-closure to move the whole environment. However, often you want to " +"move just some variables to the closure, give it a copy of some data, pass " +"by reference, or perform some other transformation." +msgstr "" + +#: src/idioms/pass-var-to-closure.md:10 +msgid "Use variable rebinding in a separate scope for that." +msgstr "" + +#: src/idioms/pass-var-to-closure.md:14 +msgid "Use" +msgstr "" + +#: src/idioms/pass-var-to-closure.md:23 +msgid "// `num1` is moved\n" +msgstr "" + +#: src/idioms/pass-var-to-closure.md:24 +msgid "// `num2` is cloned\n" +msgstr "" + +#: src/idioms/pass-var-to-closure.md:25 +msgid "// `num3` is borrowed\n" +msgstr "" + +#: src/idioms/pass-var-to-closure.md:32 +msgid "instead of" +msgstr "" + +#: src/idioms/pass-var-to-closure.md:50 +msgid "" +"Copied data are grouped together with the closure definition, so their " +"purpose is more clear, and they will be dropped immediately even if they are " +"not consumed by the closure." +msgstr "" + +#: src/idioms/pass-var-to-closure.md:54 +msgid "" +"The closure uses the same variable names as the surrounding code, whether " +"data are copied or moved." +msgstr "" + +#: src/idioms/pass-var-to-closure.md:59 +msgid "Additional indentation of the 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 " +"fields to a public struct or new variants to an enum without breaking " +"backwards 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. For " +"extensive documentation on all the places where `#[non_exhaustive]` can be " +"used, see [the docs](https://doc.rust-lang.org/reference/attributes/" +"type_system.html#the-non_exhaustive-attribute)." +msgstr "" + +#: src/idioms/priv-extend.md:16 +msgid "" +"You may add a private field to a struct to prevent it from being directly " +"instantiated or matched against (see Alternative)" +msgstr "" + +#: src/idioms/priv-extend.md:23 +msgid "// Public struct.\n" +msgstr "" + +#: src/idioms/priv-extend.md:41 +msgid "" +"// Because S is `#[non_exhaustive]`, it cannot be named here and\n" +" // we must use `..` in the pattern.\n" +msgstr "" + +#: src/idioms/priv-extend.md:47 +msgid "\"it's an A\"" +msgstr "" + +#: src/idioms/priv-extend.md:48 +msgid "\"it's a b\"" +msgstr "" + +#: src/idioms/priv-extend.md:50 +msgid "// .. required because this variant is non-exhaustive as well\n" +msgstr "" + +#: src/idioms/priv-extend.md:51 +msgid "\"it's a c\"" +msgstr "" + +#: src/idioms/priv-extend.md:53 +msgid "" +"// The wildcard match is required because more variants may be\n" +" // added in the future\n" +msgstr "" + +#: src/idioms/priv-extend.md:55 +msgid "\"it's a new variant\"" +msgstr "" + +#: src/idioms/priv-extend.md:60 +msgid "Alternative: `Private fields` for structs" +msgstr "" + +#: src/idioms/priv-extend.md:62 +msgid "" +"`#[non_exhaustive]` only works across crate boundaries. Within a crate, the " +"private field method may be used." +msgstr "" + +#: src/idioms/priv-extend.md:65 +msgid "" +"Adding a field to a struct is a mostly backwards compatible change. However, " +"if a client uses a pattern to deconstruct a struct instance, they might name " +"all the fields in the struct and adding a new one would break that pattern. " +"The client could name some fields and use `..` in the pattern, in which case " +"adding another field is backwards compatible. Making at least one of the " +"struct's fields private forces clients to use the latter form of patterns, " +"ensuring that the struct is future-proof." +msgstr "" + +#: src/idioms/priv-extend.md:73 +msgid "" +"The downside of this approach is that you might need to add an otherwise " +"unneeded field to the struct. You can use the `()` type so that there is no " +"runtime overhead and prepend `_` to the field name to avoid the unused field " +"warning." +msgstr "" + +#: src/idioms/priv-extend.md:81 +msgid "" +"// Because `b` is private, you cannot match on `S` without using `..` and " +"`S`\n" +" // cannot be directly instantiated or matched against\n" +msgstr "" + +#: src/idioms/priv-extend.md:89 +msgid "" +"On `struct`s, `#[non_exhaustive]` allows adding additional fields in a " +"backwards compatible way. It will also prevent clients from using the struct " +"constructor, even if all the fields are public. This may be helpful, but " +"it's worth considering if you _want_ an additional field to be found by " +"clients as a compiler error rather than something that may be silently " +"undiscovered." +msgstr "" + +#: src/idioms/priv-extend.md:95 +msgid "" +"`#[non_exhaustive]` can be applied to enum variants as well. A " +"`#[non_exhaustive]` variant behaves in the same way as a `#[non_exhaustive]` " +"struct." +msgstr "" + +#: src/idioms/priv-extend.md:99 +msgid "" +"Use this deliberately and with caution: incrementing the major version when " +"adding fields or variants is often a better option. `#[non_exhaustive]` may " +"be appropriate in scenarios where you're modeling an external resource that " +"may change out-of-sync with your library, but is not a general purpose tool." +msgstr "" + +#: src/idioms/priv-extend.md:106 +msgid "" +"`#[non_exhaustive]` can make your code much less ergonomic to use, " +"especially when forced to handle unknown enum variants. It should only be " +"used when these sorts of evolutions are required **without** incrementing " +"the major version." +msgstr "" + +#: src/idioms/priv-extend.md:110 +msgid "" +"When `#[non_exhaustive]` is applied to `enum`s, it forces clients to handle " +"a wildcard variant. If there is no sensible action to take in this case, " +"this may lead to awkward code and code paths that are only executed in " +"extremely rare circumstances. If a client decides to `panic!()` in this " +"scenario, it may have been better to expose this error at compile time. In " +"fact, `#[non_exhaustive]` forces clients to handle the \"Something else\" " +"case; there is rarely a sensible action to take in this scenario." +msgstr "" + +#: src/idioms/priv-extend.md:120 +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:5 +msgid "" +"If a struct takes significant effort to initialize when writing docs, it can " +"be quicker to wrap your example with a helper function which takes the " +"struct as an argument." +msgstr "" + +#: src/idioms/rustdoc-init.md:11 +msgid "" +"Sometimes there is a struct with multiple or complicated parameters and " +"several methods. Each of these methods should have examples." +msgstr "" + +#: src/idioms/rustdoc-init.md:14 +msgid "For example:" +msgstr "" + +#: src/idioms/rustdoc-init.md:23 +msgid "" +"/// Sends a request over the connection.\n" +" ///\n" +" /// # Example\n" +" /// ```no_run\n" +" /// # // Boilerplate are required to get an example working.\n" +" /// # let stream = TcpStream::connect(\"127.0.0.1:34254\");\n" +" /// # let connection = Connection { name: \"foo\".to_owned(), stream };\n" +" /// # let request = Request::new(\"RequestId\", RequestType::Get, " +"\"payload\");\n" +" /// let response = connection.send_request(request);\n" +" /// assert!(response.is_ok());\n" +" /// ```\n" +msgstr "" + +#: src/idioms/rustdoc-init.md:35 src/idioms/rustdoc-init.md:40 +#: src/idioms/rustdoc-init.md:68 +msgid "// ...\n" +msgstr "" + +#: src/idioms/rustdoc-init.md:38 +msgid "/// Oh no, all that boilerplate needs to be repeated here!\n" +msgstr "" + +#: src/idioms/rustdoc-init.md:47 +msgid "" +"Instead of typing all of this boilerplate to create a `Connection` and " +"`Request`, it is easier to just create a wrapping helper function which " +"takes them as arguments:" +msgstr "" + +#: src/idioms/rustdoc-init.md:58 +msgid "" +"/// Sends a request over the connection.\n" +" ///\n" +" /// # Example\n" +" /// ```\n" +" /// # fn call_send(connection: Connection, request: Request) {\n" +" /// let response = connection.send_request(request);\n" +" /// assert!(response.is_ok());\n" +" /// # }\n" +" /// ```\n" +msgstr "" + +#: src/idioms/rustdoc-init.md:73 +msgid "" +"**Note** in the above example the line `assert!(response.is_ok());` will not " +"actually run while testing because it is inside a function which is never " +"invoked." +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:83 +msgid "" +"As example is in a function, the code will not be tested. Though it will " +"still be checked to make sure it compiles when running a `cargo test`. So " +"this pattern is most useful when you need `no_run`. With this, you do not " +"need to add `no_run`." +msgstr "" + +#: src/idioms/rustdoc-init.md:90 +msgid "If assertions are not required this pattern works well." +msgstr "" + +#: src/idioms/rustdoc-init.md:92 +msgid "" +"If they are, an alternative can be to create a public method to create a " +"helper instance which is annotated with `#[doc(hidden)]` (so that users " +"won't see it). Then this method can be called inside of rustdoc because it " +"is part of the crate's public API." +msgstr "" + +#: src/idioms/temporary-mutability.md:5 +msgid "" +"Often it is necessary to prepare and process some data, but after that data " +"are only inspected and never modified. The intention can be made explicit by " +"redefining 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 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:24 src/idioms/temporary-mutability.md:34 +msgid "// Here `data` is immutable.\n" +msgstr "" + +#: src/idioms/temporary-mutability.md:28 +msgid "Using variable rebinding:" +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. 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 an error." +msgstr "" + +#: src/idioms/return-consumed-arg-on-error.md:12 +msgid "\"using {value} in a meaningful way\"" +msgstr "" + +#: src/idioms/return-consumed-arg-on-error.md:13 +msgid "// Simulate non-deterministic fallible action.\n" +msgstr "" + +#: src/idioms/return-consumed-arg-on-error.md:28 +msgid "\"imagine this is very long string\"" +msgstr "" + +#: src/idioms/return-consumed-arg-on-error.md:31 +msgid "// Try to send value two times.\n" +msgstr "" + +#: src/idioms/return-consumed-arg-on-error.md:41 +msgid "\"success: {success}\"" +msgstr "" + +#: src/idioms/return-consumed-arg-on-error.md:47 +msgid "" +"In case of error you may want to try some alternative way or to retry action " +"in case of non-deterministic function. But if the argument is always " +"consumed, you are forced to clone it on every call, which is not very " +"efficient." +msgstr "" + +#: src/idioms/return-consumed-arg-on-error.md:51 +msgid "" +"The standard library uses this approach in e.g. `String::from_utf8` method. " +"When given a vector that doesn't contain valid UTF-8, a `FromUtf8Error` is " +"returned. 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:3 +msgid "" +"[Design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) are " +"\"general reusable solutions to a commonly occurring problem within a given " +"context in software design\". Design patterns are a great way to describe " +"the culture of a programming language. Design patterns are very language-" +"specific - what is a pattern in one language may be unnecessary in another " +"due to a 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. " +"However, they are a great way to share intermediate and advanced level " +"knowledge about a programming language." +msgstr "" + +#: src/patterns/index.md:16 +msgid "" +"Rust has many unique features. These features give us great benefit by " +"removing whole classes of problems. Some of them are also patterns that are " +"_unique_ to Rust." +msgstr "" + +#: src/patterns/index.md:20 +msgid "YAGNI" +msgstr "" + +#: src/patterns/index.md:22 +msgid "" +"YAGNI is an acronym that stands for `You Aren't Going to Need It`. It's a " +"vital software design principle to apply as you write code." +msgstr "" + +#: src/patterns/index.md:25 +msgid "The best code I ever wrote was code I never wrote." +msgstr "" + +#: src/patterns/index.md:27 +msgid "" +"If we apply YAGNI to design patterns, we see that the features of Rust allow " +"us to throw out many patterns. For instance, there is no need for the " +"[strategy pattern](https://en.wikipedia.org/wiki/Strategy_pattern) 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. " +"By doing so, these patterns increase flexibility in carrying out " +"communication." +msgstr "" + +#: src/patterns/behavioural/command.md:5 +msgid "" +"The basic idea of the Command pattern is to separate out actions into its " +"own 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. We want these actions or commands to be executed or invoked in some " +"order later at different time. These commands may also be triggered as a " +"result of some event. For example, when a user pushes a button, or on " +"arrival of a data packet. In addition, these commands might be undoable. " +"This may come in useful for operations of an editor. We might want to store " +"logs of executed commands so that 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 " +"operations is a command which knows how to undo the command, e.g., `drop " +"table` and `remove field`. When a user invokes a database migration " +"operation then each command is executed in the defined order, and when the " +"user invokes the rollback 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 " +"`execute` and `rollback`. All command `structs` must implement this trait." +msgstr "" + +#: src/patterns/behavioural/command.md:40 +#: src/patterns/behavioural/command.md:90 +#: src/patterns/behavioural/command.md:143 +#: src/patterns/behavioural/command.md:145 +#: src/patterns/behavioural/command.md:196 +#: src/patterns/behavioural/command.md:198 +msgid "\"create table\"" +msgstr "" + +#: src/patterns/behavioural/command.md:43 +#: src/patterns/behavioural/command.md:91 +#: src/patterns/behavioural/command.md:143 +#: src/patterns/behavioural/command.md:146 +#: src/patterns/behavioural/command.md:196 +#: src/patterns/behavioural/command.md:199 +msgid "\"drop table\"" +msgstr "" + +#: src/patterns/behavioural/command.md:50 +#: src/patterns/behavioural/command.md:90 +#: src/patterns/behavioural/command.md:134 +#: src/patterns/behavioural/command.md:145 +#: src/patterns/behavioural/command.md:187 +#: src/patterns/behavioural/command.md:198 +msgid "\"add field\"" +msgstr "" + +#: src/patterns/behavioural/command.md:53 +#: src/patterns/behavioural/command.md:91 +#: src/patterns/behavioural/command.md:138 +#: src/patterns/behavioural/command.md:146 +#: src/patterns/behavioural/command.md:191 +#: src/patterns/behavioural/command.md:199 +msgid "\"remove field\"" +msgstr "" + +#: src/patterns/behavioural/command.md:76 +msgid "// reverse iterator's direction\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 a " +"different function and store function pointers to invoke these functions " +"later at a different time. Since function pointers implement all three " +"traits `Fn`, `FnMut`, and `FnOnce` we could as well pass and store closures " +"instead of function pointers." +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 each " +"command implementing the `Fn` trait separately in vectors." +msgstr "" + +#: src/patterns/behavioural/command.md:205 +msgid "" +"If our commands are small and may be defined as functions or passed as a " +"closure then using function pointers might be preferable since it does not " +"exploit dynamic dispatch. But if our command is a whole struct with a bunch " +"of functions and variables defined as separated module then using trait " +"objects would be more suitable. A case of application can be found in " +"[`actix`](https://actix.rs/), which uses trait objects when it registers a " +"handler function for routes. In case of using `Fn` trait objects we can " +"create and use commands in the same 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 " +"simplicity and organisation. Static dispatch gives faster performance, while " +"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)" +msgstr "" + +#: src/patterns/behavioural/command.md:222 +msgid "" +"[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:5 +msgid "" +"If a problem occurs very often and requires long and repetitive steps to " +"solve it, then the problem instances might be expressed in a simple language " +"and an interpreter object could solve it by interpreting the sentences " +"written in this 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)," +msgstr "" + +#: src/patterns/behavioural/interpreter.md:14 +msgid "A grammar for this language," +msgstr "" + +#: src/patterns/behavioural/interpreter.md:15 +msgid "An interpreter that solves the problem instances." +msgstr "" + +#: src/patterns/behavioural/interpreter.md:19 +msgid "" +"Our goal is to translate simple mathematical expressions into postfix " +"expressions (or [Reverse Polish notation](https://en.wikipedia.org/wiki/" +"Reverse_Polish_notation)) For simplicity, our expressions consist of ten " +"digits `0`, ..., `9` and two operations `+`, `-`. For example, the " +"expression `2 + 4` is translated into `2 4 +`." +msgstr "" + +#: src/patterns/behavioural/interpreter.md:26 +msgid "Context Free Grammar for our problem" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:28 +msgid "" +"Our task is translating infix expressions into postfix ones. Let's define a " +"context free grammar for a set of infix expressions over `0`, ..., `9`, `+`, " +"and `-`, where:" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:32 +msgid "Terminal symbols: `0`, `...`, `9`, `+`, `-`" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:33 +msgid "Non-terminal symbols: `exp`, `term`" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:34 +msgid "Start symbol is `exp`" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:35 +msgid "And the following are production rules" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:44 +msgid "" +"**NOTE:** This grammar should be further transformed depending on what we " +"are going to do with it. For example, we might need to remove left " +"recursion. For more details please see [Compilers: Principles,Techniques, " +"and Tools](https://en.wikipedia.org/wiki/" +"Compilers:_Principles,_Techniques,_and_Tools) (aka Dragon Book)." +msgstr "" + +#: src/patterns/behavioural/interpreter.md:50 +msgid "Solution" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:52 +msgid "" +"We simply implement a recursive descent parser. For simplicity's sake, the " +"code panics when an expression is syntactically wrong (for example `2-34` or " +"`2+5-` are wrong according to the grammar definition)." +msgstr "" + +#: src/patterns/behavioural/interpreter.md:74 +msgid "'+'" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:74 +msgid "'-'" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:78 +msgid "\"Unexpected symbol '{op}'\"" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:86 +msgid "\"Unexpected symbol '{ch}'\"" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:87 +msgid "\"Unexpected end of string\"" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:93 +msgid "\"2+3\"" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:96 +msgid "\"23+\"" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:98 +msgid "\"1-2+3-4\"" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:101 +msgid "\"12-3+4-\"" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:107 +msgid "" +"There may be a wrong perception that the Interpreter design pattern is about " +"design grammars for formal languages and implementation of parsers for these " +"grammars. In fact, this pattern is about expressing problem instances in a " +"more specific way and implementing functions/classes/structs that solve " +"these problem instances. Rust language has `macro_rules!` that allow us to " +"define special syntax and rules on how to expand this syntax into source " +"code." +msgstr "" + +#: src/patterns/behavioural/interpreter.md:114 +msgid "" +"In the following example we create a simple `macro_rules!` that computes " +"[Euclidean length](https://en.wikipedia.org/wiki/Euclidean_distance) of `n` " +"dimensional vectors. Writing `norm!(x,1,2)` might be easier to express and " +"more efficient than packing `x,1,2` into a `Vec` and calling a function " +"computing the length." +msgstr "" + +#: src/patterns/behavioural/interpreter.md:146 +msgid "" +"[Interpreter pattern](https://en.wikipedia.org/wiki/Interpreter_pattern)" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:147 +msgid "" +"[Context free grammar](https://en.wikipedia.org/wiki/Context-free_grammar)" +msgstr "" + +#: src/patterns/behavioural/interpreter.md:148 +msgid "[macro_rules!](https://doc.rust-lang.org/rust-by-example/macros.html)" +msgstr "" + +#: src/patterns/behavioural/newtype.md:3 +msgid "" +"What if in some cases we want a type to behave similar to another type or " +"enforce some behaviour at compile time when using only type aliases would " +"not be enough?" +msgstr "" + +#: src/patterns/behavioural/newtype.md:7 +msgid "" +"For example, if we want to create a custom `Display` implementation for " +"`String` 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** " +"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. " +"This creates a new type, rather than an alias to a type (`type` items)." +msgstr "" + +#: src/patterns/behavioural/newtype.md:22 +msgid "// Create Newtype Password to override the Display trait for String\n" +msgstr "" + +#: src/patterns/behavioural/newtype.md:28 +msgid "\"****************\"" +msgstr "" + +#: src/patterns/behavioural/newtype.md:33 +msgid "\"ThisIsMyPassword\"" +msgstr "" + +#: src/patterns/behavioural/newtype.md:35 +msgid "\"unsecured_password: {unsecured_password}\"" +msgstr "" + +#: src/patterns/behavioural/newtype.md:36 +msgid "\"secured_password: {secured_password}\"" +msgstr "" + +#: src/patterns/behavioural/newtype.md:47 +msgid "" +"The primary motivation for newtypes is abstraction. It allows you to share " +"implementation details between types while precisely controlling the " +"interface. By using a newtype rather than exposing the implementation type " +"as part of an API, it allows you to change implementation backwards " +"compatibly." +msgstr "" + +#: src/patterns/behavioural/newtype.md:52 +msgid "" +"Newtypes can be used for distinguishing units, e.g., wrapping `f64` to give " +"distinguishable `Miles` and `Kilometres`." +msgstr "" + +#: src/patterns/behavioural/newtype.md:57 +msgid "" +"The wrapped and wrapper types are not type compatible (as opposed to using " +"`type`), so users of the newtype will never 'confuse' the wrapped and " +"wrapper types." +msgstr "" + +#: src/patterns/behavioural/newtype.md:61 +msgid "Newtypes are a zero-cost abstraction - there is no runtime overhead." +msgstr "" + +#: src/patterns/behavioural/newtype.md:63 +msgid "" +"The privacy system ensures that users cannot access the wrapped type (if the " +"field is private, which it is by default)." +msgstr "" + +#: src/patterns/behavioural/newtype.md:68 +msgid "" +"The downside of newtypes (especially compared with type aliases), is that " +"there is no special language support. This means there can be _a lot_ of " +"boilerplate. You need a 'pass through' method for every method you want to " +"expose on the wrapped type, and an impl for every trait you want to also be " +"implemented for the wrapper type." +msgstr "" + +#: src/patterns/behavioural/newtype.md:76 +msgid "" +"Newtypes are very common in Rust code. Abstraction or representing units are " +"the most common uses, but they can be used for other reasons:" +msgstr "" + +#: src/patterns/behavioural/newtype.md:79 +msgid "" +"restricting functionality (reduce the functions exposed or traits " +"implemented)," +msgstr "" + +#: src/patterns/behavioural/newtype.md:81 +msgid "making a type with copy semantics have move semantics," +msgstr "" + +#: src/patterns/behavioural/newtype.md:82 +msgid "" +"abstraction by providing a more concrete type and thus hiding internal " +"types, e.g.," +msgstr "" + +#: src/patterns/behavioural/newtype.md:89 +msgid "" +"Here, `Bar` might be some public, generic type and `T1` and `T2` are some " +"internal types. Users of our module shouldn't know that we implement `Foo` " +"by using a `Bar`, but what we're really hiding here is the types `T1` and " +"`T2`, and how they are used with `Bar`." +msgstr "" + +#: src/patterns/behavioural/newtype.md:96 +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)" +msgstr "" + +#: src/patterns/behavioural/newtype.md:97 +msgid "[Newtypes in Haskell](https://wiki.haskell.org/Newtype)" +msgstr "" + +#: src/patterns/behavioural/newtype.md:98 +msgid "" +"[Type aliases](https://doc.rust-lang.org/stable/book/ch19-04-advanced-" +"types.html#creating-type-synonyms-with-type-aliases)" +msgstr "" + +#: src/patterns/behavioural/newtype.md:99 +msgid "" +"[derive_more](https://crates.io/crates/derive_more), a crate for deriving " +"many builtin traits on newtypes." +msgstr "" + +#: src/patterns/behavioural/newtype.md:101 +msgid "" +"[The Newtype Pattern In Rust](https://web.archive.org/web/20230519162111/" +"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](https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) " +"stands for \"Resource Acquisition is Initialisation\" which is a terrible " +"name. The essence of the pattern is that resource initialisation is done in " +"the constructor of an object and finalisation in the destructor. This " +"pattern is extended in Rust by using a RAII object as a guard of some " +"resource and relying on the type system to ensure that access is always " +"mediated by the guard object." +msgstr "" + +#: src/patterns/behavioural/RAII.md:14 +msgid "" +"Mutex guards are the classic example of this pattern from the std library " +"(this is a simplified version of the real implementation):" +msgstr "" + +#: src/patterns/behavioural/RAII.md:23 +msgid "" +"// We keep a reference to our data: T here.\n" +" //..\n" +msgstr "" + +#: src/patterns/behavioural/RAII.md:31 +msgid "// Locking the mutex is explicit.\n" +msgstr "" + +#: src/patterns/behavioural/RAII.md:35 +msgid "" +"// Lock the underlying OS mutex.\n" +" //..\n" +msgstr "" + +#: src/patterns/behavioural/RAII.md:38 +msgid "// MutexGuard keeps a reference to self\n" +msgstr "" + +#: src/patterns/behavioural/RAII.md:45 +msgid "// Destructor for unlocking the mutex.\n" +msgstr "" + +#: src/patterns/behavioural/RAII.md:49 +msgid "" +"// Unlock the underlying OS mutex.\n" +" //..\n" +msgstr "" + +#: src/patterns/behavioural/RAII.md:53 +msgid "" +"// Implementing Deref means we can treat MutexGuard like a pointer to T.\n" +msgstr "" + +#: src/patterns/behavioural/RAII.md:65 +msgid "" +"// 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" +msgstr "" + +#: src/patterns/behavioural/RAII.md:69 +msgid "" +"// x is unlocked when we exit this function and xx's destructor is " +"executed.\n" +msgstr "" + +#: src/patterns/behavioural/RAII.md:75 +msgid "" +"Where a resource must be finalised after use, RAII can be used to do this " +"finalisation. If it is an error to access that resource after finalisation, " +"then this pattern can be used to prevent such errors." +msgstr "" + +#: src/patterns/behavioural/RAII.md:81 +msgid "" +"Prevents errors where a resource is not finalised and where a resource is " +"used after finalisation." +msgstr "" + +#: src/patterns/behavioural/RAII.md:86 +msgid "" +"RAII is a useful pattern for ensuring resources are properly deallocated or " +"finalised. We can make use of the borrow checker in Rust to statically " +"prevent errors stemming from using resources after finalisation takes place." +msgstr "" + +#: src/patterns/behavioural/RAII.md:90 +msgid "" +"The core aim of the borrow checker is to ensure that references to data do " +"not outlive that data. The RAII guard pattern works because the guard object " +"contains a reference to the underlying resource and only exposes such " +"references. Rust ensures that the guard cannot outlive the underlying " +"resource and that references to the resource mediated by the guard cannot " +"outlive the guard. To see how this works it is helpful to examine the " +"signature of `deref` without lifetime elision:" +msgstr "" + +#: src/patterns/behavioural/RAII.md:104 +msgid "" +"The returned reference to the resource has the same lifetime as `self` " +"(`'a`). The borrow checker therefore ensures that the lifetime of the " +"reference to `T` is shorter than the lifetime of `self`." +msgstr "" + +#: src/patterns/behavioural/RAII.md:108 +msgid "" +"Note that implementing `Deref` is not a core part of this pattern, it only " +"makes using the guard object more ergonomic. Implementing a `get` method on " +"the guard works just as well." +msgstr "" + +#: src/patterns/behavioural/RAII.md:114 +msgid "[Finalisation in destructors idiom](../../idioms/dtor-finally.md)" +msgstr "" + +#: src/patterns/behavioural/RAII.md:116 +msgid "" +"RAII is a common pattern in C++: [cppreference.com](http://" +"en.cppreference.com/w/cpp/language/raii), [wikipedia](https://" +"en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)." +msgstr "" + +#: src/patterns/behavioural/RAII.md:122 +msgid "" +"[Style guide entry](https://doc.rust-lang.org/1.0.0/style/ownership/" +"raii.html) (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) is a technique that enables separation of concerns. It " +"also allows to decouple software modules through [Dependency Inversion]" +"(https://en.wikipedia.org/wiki/Dependency_inversion_principle)." +msgstr "" + +#: src/patterns/behavioural/strategy.md:10 +msgid "" +"The basic idea behind the Strategy pattern is that, given an algorithm " +"solving a particular problem, we define only the skeleton of the algorithm " +"at an abstract level, and we separate the specific algorithm’s " +"implementation into different parts." +msgstr "" + +#: src/patterns/behavioural/strategy.md:15 +msgid "" +"In this way, a client using the algorithm may choose a specific " +"implementation, while the general algorithm workflow remains the same. In " +"other words, the abstract specification of the class does not depend on the " +"specific implementation of the derived class, but specific implementation " +"must adhere to the abstract specification. This is why we call it " +"\"Dependency Inversion\"." +msgstr "" + +#: src/patterns/behavioural/strategy.md:23 +msgid "" +"Imagine we are working on a project that generates reports every month. We " +"need the reports to be generated in different formats (strategies), e.g., in " +"`JSON` or `Plain Text` formats. But things vary over time, and we don't know " +"what kind of requirement we may get in the future. For example, we may need " +"to generate our report in a completely new format, or just modify one of the " +"existing formats." +msgstr "" + +#: src/patterns/behavioural/strategy.md:32 +msgid "" +"In this example our invariants (or abstractions) are `Formatter` and " +"`Report`, while `Text` and `Json` are our strategy structs. These strategies " +"have to implement the `Formatter` trait." +msgstr "" + +#: src/patterns/behavioural/strategy.md:48 +msgid "" +"// Write should be used but we kept it as String to ignore error handling\n" +msgstr "" + +#: src/patterns/behavioural/strategy.md:50 +msgid "// backend operations...\n" +msgstr "" + +#: src/patterns/behavioural/strategy.md:52 +msgid "\"one\"" +msgstr "" + +#: src/patterns/behavioural/strategy.md:53 +msgid "\"two\"" +msgstr "" + +#: src/patterns/behavioural/strategy.md:54 +msgid "// generate report\n" +msgstr "" + +#: src/patterns/behavioural/strategy.md:63 +msgid "\"{k} {v}\\n\"" +msgstr "" + +#: src/patterns/behavioural/strategy.md:72 +msgid "'['" +msgstr "" + +#: src/patterns/behavioural/strategy.md:74 +msgid "r#\"{{\"{}\":\"{}\"}}\"#" +msgstr "" + +#: src/patterns/behavioural/strategy.md:76 +msgid "','" +msgstr "" + +#: src/patterns/behavioural/strategy.md:79 +msgid "// remove extra , at the end\n" +msgstr "" + +#: src/patterns/behavioural/strategy.md:81 +msgid "']'" +msgstr "" + +#: src/patterns/behavioural/strategy.md:86 +msgid "\"\"" +msgstr "" + +#: src/patterns/behavioural/strategy.md:88 +msgid "\"one 1\"" +msgstr "" + +#: src/patterns/behavioural/strategy.md:89 +msgid "\"two 2\"" +msgstr "" + +#: src/patterns/behavioural/strategy.md:91 +msgid "// reuse the same buffer\n" +msgstr "" + +#: src/patterns/behavioural/strategy.md:93 +msgid "r#\"{\"one\":\"1\"}\"#" +msgstr "" + +#: src/patterns/behavioural/strategy.md:94 +msgid "r#\"{\"two\":\"2\"}\"#" +msgstr "" + +#: src/patterns/behavioural/strategy.md:100 +msgid "" +"The main advantage is separation of concerns. For example, in this case " +"`Report` does not know anything about specific implementations of `Json` and " +"`Text`, whereas the output implementations does not care about how data is " +"preprocessed, stored, and fetched. The only thing they have to know is a " +"specific trait to implement and its method defining the concrete algorithm " +"implementation processing the result, i.e., `Formatter` and `format(...)`." +msgstr "" + +#: src/patterns/behavioural/strategy.md:109 +msgid "" +"For each strategy there must be implemented at least one module, so number " +"of modules increases with number of strategies. If there are many strategies " +"to choose from then users have to know how strategies differ from one " +"another." +msgstr "" + +#: src/patterns/behavioural/strategy.md:115 +msgid "" +"In the previous example all strategies are implemented in a single file. " +"Ways of providing different strategies includes:" +msgstr "" + +#: src/patterns/behavioural/strategy.md:118 +msgid "" +"All in one file (as shown in this example, similar to being separated as " +"modules)" +msgstr "" + +#: src/patterns/behavioural/strategy.md:120 +msgid "" +"Separated as modules, E.g. `formatter::json` module, `formatter::text` module" +msgstr "" + +#: src/patterns/behavioural/strategy.md:121 +msgid "Use compiler feature flags, E.g. `json` feature, `text` feature" +msgstr "" + +#: src/patterns/behavioural/strategy.md:122 +msgid "Separated as crates, E.g. `json` crate, `text` crate" +msgstr "" + +#: src/patterns/behavioural/strategy.md:124 +msgid "" +"Serde crate is a good example of the `Strategy` pattern in action. Serde " +"allows [full customization](https://serde.rs/custom-serialization.html) of " +"the serialization behavior by manually implementing `Serialize` and " +"`Deserialize` traits for our type. For example, we could easily swap " +"`serde_json` with `serde_cbor` since they expose similar methods. Having " +"this makes the helper crate `serde_transcode` much more useful and ergonomic." +msgstr "" + +#: src/patterns/behavioural/strategy.md:131 +msgid "" +"However, we don't need to use traits in order to design this pattern in Rust." +msgstr "" + +#: src/patterns/behavioural/strategy.md:133 +msgid "" +"The following toy example demonstrates the idea of the Strategy pattern " +"using Rust `closures`:" +msgstr "" + +#: src/patterns/behavioural/strategy.md:164 +msgid "In fact, Rust already uses this idea for `Options`'s `map` method:" +msgstr "" + +#: src/patterns/behavioural/strategy.md:168 +msgid "\"Rust\"" +msgstr "" + +#: src/patterns/behavioural/strategy.md:180 +msgid "[Strategy Pattern](https://en.wikipedia.org/wiki/Strategy_pattern)" +msgstr "" + +#: src/patterns/behavioural/strategy.md:181 +msgid "" +"[Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection)" +msgstr "" + +#: src/patterns/behavioural/strategy.md:182 +msgid "" +"[Policy Based Design](https://en.wikipedia.org/wiki/Modern_C++_Design#Policy-" +"based_design)" +msgstr "" + +#: src/patterns/behavioural/strategy.md:183 +msgid "" +"[Implementing a TCP server for Space Applications in Rust using the Strategy " +"Pattern](https://web.archive.org/web/20231003171500/https://robamu.github.io/" +"posts/rust-strategy-pattern/)" +msgstr "" + +#: src/patterns/behavioural/visitor.md:5 +msgid "" +"A visitor encapsulates an algorithm that operates over a heterogeneous " +"collection of objects. It allows multiple different algorithms to be written " +"over the same data without having to modify the data (or their primary " +"behaviour)." +msgstr "" + +#: src/patterns/behavioural/visitor.md:10 +msgid "" +"Furthermore, the visitor pattern allows separating the traversal of a " +"collection of objects from the operations performed on each object." +msgstr "" + +#: src/patterns/behavioural/visitor.md:16 +msgid "// The data we will visit\n" +msgstr "" + +#: src/patterns/behavioural/visitor.md:33 +msgid "// The abstract visitor\n" +msgstr "" + +#: src/patterns/behavioural/visitor.md:47 +msgid "" +"// An example concrete implementation - walks the AST interpreting it as " +"code.\n" +msgstr "" + +#: src/patterns/behavioural/visitor.md:71 +msgid "" +"One could implement further visitors, for example a type checker, without " +"having to modify the AST data." +msgstr "" + +#: src/patterns/behavioural/visitor.md:76 +msgid "" +"The visitor pattern is useful anywhere that you want to apply an algorithm " +"to heterogeneous data. If data is homogeneous, you can use an iterator-like " +"pattern. Using a visitor object (rather than a functional approach) allows " +"the visitor to be stateful and thus communicate information between nodes." +msgstr "" + +#: src/patterns/behavioural/visitor.md:83 +msgid "" +"It is common for the `visit_*` methods to return void (as opposed to in the " +"example). In that case it is possible to factor out the traversal code and " +"share it between algorithms (and also to provide noop default methods). In " +"Rust, the common way to do this is to provide `walk_*` functions for each " +"datum. For example," +msgstr "" + +#: src/patterns/behavioural/visitor.md:105 +msgid "" +"In other languages (e.g., Java) it is common for data to have an `accept` " +"method which performs the same duty." +msgstr "" + +#: src/patterns/behavioural/visitor.md:110 +msgid "The visitor pattern is a common pattern in most OO languages." +msgstr "" + +#: src/patterns/behavioural/visitor.md:112 +msgid "[Wikipedia article](https://en.wikipedia.org/wiki/Visitor_pattern)" +msgstr "" + +#: src/patterns/behavioural/visitor.md:114 +msgid "" +"The [fold](../creational/fold.md) pattern is similar to visitor but produces " +"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 in a manner suitable to the situation. The basic form of object " +"creation could result in design problems or in added complexity to the " +"design. Creational design patterns solve this problem by somehow controlling " +"this object creation." +msgstr "" + +#: src/patterns/creational/builder.md:5 +msgid "Construct an object with calls to a builder helper." +msgstr "" + +#: src/patterns/creational/builder.md:12 +msgid "// Lots of complicated fields.\n" +msgstr "" + +#: src/patterns/creational/builder.md:17 +msgid "// This method will help users to discover the builder\n" +msgstr "" + +#: src/patterns/creational/builder.md:25 +msgid "// Probably lots of optional fields.\n" +msgstr "" + +#: src/patterns/creational/builder.md:31 +msgid "// Set the minimally required fields of Foo.\n" +msgstr "" + +#: src/patterns/creational/builder.md:33 +msgid "\"X\"" +msgstr "" + +#: src/patterns/creational/builder.md:38 +msgid "" +"// Set the name on the builder itself, and return the builder by value.\n" +msgstr "" + +#: src/patterns/creational/builder.md:43 +msgid "" +"// 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" +msgstr "" + +#: src/patterns/creational/builder.md:47 +msgid "" +"// Create a Foo from the FooBuilder, applying all settings in FooBuilder\n" +" // to Foo.\n" +msgstr "" + +#: src/patterns/creational/builder.md:56 src/patterns/creational/builder.md:58 +msgid "\"Y\"" +msgstr "" + +#: src/patterns/creational/builder.md:65 +msgid "" +"Useful when you would otherwise require many constructors or where " +"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 " +"function." +msgstr "" + +#: src/patterns/creational/builder.md:83 +msgid "" +"This pattern is seen more frequently in Rust (and for simpler objects) than " +"in many other languages because Rust lacks overloading. Since you can only " +"have a single method with a given name, having multiple constructors is less " +"nice in 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, rather than being just a builder. For example, see " +"[`std::process::Command`](https://doc.rust-lang.org/std/process/" +"struct.Command.html) is a builder for [`Child`](https://doc.rust-lang.org/" +"std/process/struct.Child.html) (a process). In these cases, the `T` and " +"`TBuilder` naming pattern is not used." +msgstr "" + +#: src/patterns/creational/builder.md:95 +msgid "" +"The example takes and returns the builder by value. It is often more " +"ergonomic (and more efficient) to take and return the builder as a mutable " +"reference. The borrow checker makes this work naturally. This approach has " +"the advantage that one can write code like" +msgstr "" + +#: src/patterns/creational/builder.md:107 +msgid "as well as the `FooBuilder::new().a().b().build()` style." +msgstr "" + +#: src/patterns/creational/builder.md:111 +msgid "" +"[Description in the style guide](https://web.archive.org/web/20210104103100/" +"https://doc.rust-lang.org/1.12.0/style/ownership/builders.html)" +msgstr "" + +#: src/patterns/creational/builder.md:112 +msgid "" +"[derive_builder](https://crates.io/crates/derive_builder), a crate for " +"automatically implementing this pattern while avoiding the boilerplate." +msgstr "" + +#: src/patterns/creational/builder.md:114 +msgid "" +"[Constructor pattern](../../idioms/ctor.md) for when construction is simpler." +msgstr "" + +#: src/patterns/creational/builder.md:115 +msgid "" +"[Builder pattern (wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern)" +msgstr "" + +#: src/patterns/creational/builder.md:116 +msgid "" +"[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:5 +msgid "" +"Run an algorithm over each item in a collection of data to create a new " +"item, 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 " +"in the Rust compiler, although it appears to me to be more like a map than a " +"fold in the usual sense. See the discussion below for more details." +msgstr "" + +#: src/patterns/creational/fold.md:15 +msgid "// The data we will fold, a simple AST.\n" +msgstr "" + +#: src/patterns/creational/fold.md:32 +msgid "// The abstract folder\n" +msgstr "" + +#: src/patterns/creational/fold.md:38 +msgid "" +"// A leaf node just returns the node itself. In some cases, we can do this\n" +" // to inner nodes too.\n" +msgstr "" + +#: src/patterns/creational/fold.md:41 +msgid "// Create a new inner node by folding its children.\n" +msgstr "" + +#: src/patterns/creational/fold.md:54 +msgid "// An example concrete implementation - renames every name to 'foo'.\n" +msgstr "" + +#: src/patterns/creational/fold.md:59 +msgid "\"foo\"" +msgstr "" + +#: src/patterns/creational/fold.md:61 +msgid "// Use the default methods for the other nodes.\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 one, but with every name changed to `foo`. A real life folder might have " +"some 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 " +"usually similar) data structure. For example, we could fold an AST into a " +"HIR 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 " +"each node in the structure. For simple operations on simple data structures, " +"this can be done using `Iterator::map`. For more complex operations, perhaps " +"where earlier nodes can affect the operation on later nodes, or where " +"iteration over the data structure is non-trivial, using the fold pattern is " +"more appropriate." +msgstr "" + +#: src/patterns/creational/fold.md:82 +msgid "" +"Like the visitor pattern, the fold pattern allows us to separate traversal " +"of a 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 languages, it would be more common to mutate the data structure in " +"place. The 'functional' approach is common in Rust, mostly due to the " +"preference for immutability. Using fresh data structures, rather than " +"mutating old ones, makes 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 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 exclusively, the original copy of the data structure cannot be re-used. " +"On the 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 reused; however, a node must be cloned even if unchanged, which can " +"be expensive." +msgstr "" + +#: src/patterns/creational/fold.md:104 +msgid "" +"Using a reference counted pointer gives the best of both worlds - we can " +"reuse the original data structure, and we don't need to clone unchanged " +"nodes. However, they are less ergonomic to use and mean that the data " +"structures cannot be mutable." +msgstr "" + +#: src/patterns/creational/fold.md:111 +msgid "" +"Iterators have a `fold` method, however this folds a data structure into a " +"value, rather than into a new data structure. An iterator's `map` is more " +"like 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, " +"rather than this pattern. Some functional languages have powerful constructs " +"for 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. " +"They share the concept of walking a data structure performing an operation " +"on each node. However, the visitor does not create a new data structure nor " +"consume 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 among entities." +msgstr "" + +#: src/patterns/structural/compose-structs.md:1 +msgid "Struct decomposition for independent borrowing" +msgstr "" + +#: src/patterns/structural/compose-structs.md:5 +msgid "" +"Sometimes a large struct will cause issues with the borrow checker - " +"although fields can be borrowed independently, sometimes the whole struct " +"ends up being used at once, preventing other uses. A solution might be to " +"decompose the struct into several smaller structs. Then compose these " +"together into the original struct. Then each struct can be borrowed " +"separately and have more flexible behaviour." +msgstr "" + +#: src/patterns/structural/compose-structs.md:12 +msgid "" +"This will often lead to a better design in other ways: applying this design " +"pattern often reveals smaller units of functionality." +msgstr "" + +#: src/patterns/structural/compose-structs.md:17 +msgid "" +"Here is a contrived example of where the borrow checker foils us in our plan " +"to use a struct:" +msgstr "" + +#: src/patterns/structural/compose-structs.md:28 +msgid "\"Connection string: {}\"" +msgstr "" + +#: src/patterns/structural/compose-structs.md:29 +msgid "\"Timeout: {}\"" +msgstr "" + +#: src/patterns/structural/compose-structs.md:30 +msgid "\"Pool size: {}\"" +msgstr "" + +#: src/patterns/structural/compose-structs.md:35 +msgid "\"initial string\"" +msgstr "" + +#: src/patterns/structural/compose-structs.md:42 +#: src/patterns/structural/compose-structs.md:96 +msgid "\"new string\"" +msgstr "" + +#: src/patterns/structural/compose-structs.md:46 +msgid "The compiler throws following errors:" +msgstr "" + +#: src/patterns/structural/compose-structs.md:48 +msgid "" +"```ignore\n" +"let connection_string = &mut db.connection_string;\n" +" ------------------------- mutable borrow occurs " +"here\n" +"print_database(&db);\n" +" ^^^ immutable borrow occurs here\n" +"*connection_string = \"new string\".to_string();\n" +"------------------ mutable borrow later used here\n" +"```" +msgstr "" + +#: src/patterns/structural/compose-structs.md:57 +msgid "" +"We can apply this design pattern and refactor `Database` into three smaller " +"structs, thus solving the borrow checking issue:" +msgstr "" + +#: src/patterns/structural/compose-structs.md:61 +msgid "" +"// Database is now composed of three structs - ConnectionString, Timeout and " +"PoolSize.\n" +"// Let's decompose it into smaller structs\n" +msgstr "" + +#: src/patterns/structural/compose-structs.md:71 +msgid "// We then compose these smaller structs back into `Database`\n" +msgstr "" + +#: src/patterns/structural/compose-structs.md:78 +msgid "" +"// print_database can then take ConnectionString, Timeout and Poolsize " +"struct instead\n" +msgstr "" + +#: src/patterns/structural/compose-structs.md:81 +msgid "\"Connection string: {connection_str:?}\"" +msgstr "" + +#: src/patterns/structural/compose-structs.md:82 +msgid "\"Timeout: {timeout:?}\"" +msgstr "" + +#: src/patterns/structural/compose-structs.md:83 +msgid "\"Pool size: {pool_size:?}\"" +msgstr "" + +#: src/patterns/structural/compose-structs.md:87 +msgid "// Initialize the Database with the three structs\n" +msgstr "" + +#: src/patterns/structural/compose-structs.md:89 +msgid "\"localhost\"" +msgstr "" + +#: src/patterns/structural/compose-structs.md:102 +msgid "" +"This pattern is most useful, when you have a struct that ended up with a lot " +"of fields that you want to borrow independently. Thus having a more flexible " +"behaviour in the end." +msgstr "" + +#: src/patterns/structural/compose-structs.md:108 +msgid "" +"Decomposition of structs lets you work around limitations in the borrow " +"checker. And it often produces a better design." +msgstr "" + +#: src/patterns/structural/compose-structs.md:113 +msgid "" +"It can lead to more verbose code. And sometimes, the smaller structs are not " +"good abstractions, and so we end up with a worse design. That is probably a " +"'code smell', indicating that the program should be refactored in some way." +msgstr "" + +#: src/patterns/structural/compose-structs.md:119 +msgid "" +"This pattern is not required in languages that don't have a borrow checker, " +"so in that sense is unique to Rust. However, making smaller units of " +"functionality often leads to cleaner code: a widely acknowledged principle " +"of software engineering, independent of the language." +msgstr "" + +#: src/patterns/structural/compose-structs.md:124 +msgid "" +"This pattern relies on Rust's borrow checker to be able to borrow fields " +"independently of each other. In the example, the borrow checker knows that " +"`a.b` and `a.c` are distinct and can be borrowed independently, it does not " +"try to 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 in say C or C++. Moreover, since packages on crates.io cannot be edited " +"or removed after publication, any build that works now should continue to " +"work in the future. We should take advantage of this tooling, and use " +"smaller, more fine-grained dependencies." +msgstr "" + +#: src/patterns/structural/small-crates.md:15 +msgid "Small crates are easier to understand, and encourage more modular code." +msgstr "" + +#: src/patterns/structural/small-crates.md:16 +msgid "" +"Crates allow for re-using code between projects. For example, the `url` " +"crate was developed as part of the Servo browser engine, but has since found " +"wide use outside the project." +msgstr "" + +#: src/patterns/structural/small-crates.md:19 +msgid "" +"Since the compilation unit of Rust is the crate, splitting a project into " +"multiple crates can allow more of 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 versions of a crate at the same time. For example, the `url` " +"crate has both versions 1.0 and 0.5. Since the `Url` from `url:1.0` and the " +"`Url` from `url:0.5` are different types, an HTTP client that uses `url:0.5` " +"would not accept `Url` values from a web scraper that uses `url:1.0`." +msgstr "" + +#: src/patterns/structural/small-crates.md:29 +msgid "" +"Packages on crates.io are not curated. A crate may be poorly written, have " +"unhelpful documentation, or be outright malicious." +msgstr "" + +#: src/patterns/structural/small-crates.md:31 +msgid "" +"Two small crates may be less optimized than one large one, since the " +"compiler does not perform link-time optimization (LTO) by default." +msgstr "" + +#: src/patterns/structural/small-crates.md:36 +msgid "" +"The [`url`](https://crates.io/crates/url) crate provides tools for working " +"with URLs." +msgstr "" + +#: src/patterns/structural/small-crates.md:39 +msgid "" +"The [`num_cpus`](https://crates.io/crates/num_cpus) crate provides a " +"function to query the number of CPUs on a machine." +msgstr "" + +#: src/patterns/structural/small-crates.md:42 +msgid "" +"The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides " +"functions for converting `&T` to `&[T]`. (Historical example)" +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:5 +msgid "" +"If you have `unsafe` code, create the smallest possible module that can " +"uphold the needed invariants to build a minimal safe interface upon the " +"unsafety. Embed this into a larger module that contains only safe code and " +"presents an ergonomic interface. Note that the outer module can contain " +"unsafe functions and methods that call directly into the unsafe code. Users " +"may use this to gain speed benefits." +msgstr "" + +#: src/patterns/structural/unsafe-mods.md:14 +msgid "This restricts the unsafe code that must be audited" +msgstr "" + +#: src/patterns/structural/unsafe-mods.md:15 +msgid "" +"Writing the outer module is much easier, since you can count on the " +"guarantees of the inner module" +msgstr "" + +#: src/patterns/structural/unsafe-mods.md:20 +msgid "Sometimes, it may be hard to find a suitable interface." +msgstr "" + +#: src/patterns/structural/unsafe-mods.md:21 +msgid "The abstraction may introduce inefficiencies." +msgstr "" + +#: src/patterns/structural/unsafe-mods.md:25 +msgid "" +"The [`toolshed`](https://docs.rs/toolshed) crate contains its unsafe " +"operations in submodules, presenting a safe interface to users." +msgstr "" + +#: src/patterns/structural/unsafe-mods.md:27 +msgid "" +"`std`'s `String` class is a wrapper over `Vec` with the added invariant " +"that the contents must be valid UTF-8. The operations on `String` ensure " +"this behavior. However, users have the option of using an `unsafe` method to " +"create a `String`, in which case the onus is on them to guarantee the " +"validity of the contents." +msgstr "" + +#: src/patterns/structural/unsafe-mods.md:35 +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. However, there are several " +"idioms here that can act as pointers, and avoid traps 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 "" +"[Object-Based API](./export.md) design that has good memory safety " +"characteristics, and a clean boundary of what is safe and what is unsafe" +msgstr "" + +#: src/patterns/ffi/intro.md:12 +msgid "" +"[Type Consolidation into Wrappers](./wrappers.md) - group multiple Rust " +"types together into an opaque \"object\"" +msgstr "" + +#: src/patterns/ffi/export.md:5 +msgid "" +"When designing APIs in Rust which are exposed to other languages, there are " +"some important design principles which are contrary to normal Rust API " +"design:" +msgstr "" + +#: src/patterns/ffi/export.md:8 +msgid "" +"All Encapsulated types should be _owned_ by Rust, _managed_ by the user, and " +"_opaque_." +msgstr "" + +#: src/patterns/ffi/export.md:10 +msgid "" +"All Transactional data types should be _owned_ by the user, and " +"_transparent_." +msgstr "" + +#: src/patterns/ffi/export.md:12 +msgid "" +"All library behavior should be functions acting upon Encapsulated types." +msgstr "" + +#: src/patterns/ffi/export.md:13 +msgid "" +"All library behavior should be encapsulated into types not based on " +"structure, but _provenance/lifetime_." +msgstr "" + +#: src/patterns/ffi/export.md:18 +msgid "" +"Rust has built-in FFI support to other languages. It does this by providing " +"a way for crate authors to provide C-compatible APIs through different ABIs " +"(though that is unimportant to this practice)." +msgstr "" + +#: src/patterns/ffi/export.md:22 +msgid "" +"Well-designed Rust FFI follows C API design principles, while compromising " +"the design in Rust as little as possible. There are three goals with any " +"foreign API:" +msgstr "" + +#: src/patterns/ffi/export.md:26 +msgid "Make it easy to use in the target language." +msgstr "" + +#: src/patterns/ffi/export.md:27 +msgid "" +"Avoid the API dictating internal unsafety on the Rust side as much as " +"possible." +msgstr "" + +#: src/patterns/ffi/export.md:29 +msgid "" +"Keep the potential for memory unsafety and Rust `undefined behaviour` as " +"small as possible." +msgstr "" + +#: src/patterns/ffi/export.md:32 +msgid "" +"Rust code must trust the memory safety of the foreign language beyond a " +"certain point. However, every bit of `unsafe` code on the Rust side is an " +"opportunity for bugs, or to exacerbate `undefined behaviour`." +msgstr "" + +#: src/patterns/ffi/export.md:36 +msgid "" +"For example, if a pointer provenance is wrong, that may be a segfault due to " +"invalid memory access. But if it is manipulated by unsafe code, it could " +"become full-blown heap corruption." +msgstr "" + +#: src/patterns/ffi/export.md:40 +msgid "" +"The Object-Based API design allows for writing shims that have good memory " +"safety characteristics, and a clean boundary of what is safe and what is " +"`unsafe`." +msgstr "" + +#: src/patterns/ffi/export.md:46 +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). It is an excellent example of an \"object-based\" API." +msgstr "" + +#: src/patterns/ffi/export.md:50 +msgid "" +"Here is the definition in C, which hopefully should be easy to read for " +"those involved in FFI. The commentary below should help explain it for those " +"who miss the subtleties." +msgstr "" + +#: src/patterns/ffi/export.md:69 +msgid "This API defines two types: `DBM` and `datum`." +msgstr "" + +#: src/patterns/ffi/export.md:71 +msgid "" +"The `DBM` type was called an \"encapsulated\" type above. It is designed to " +"contain internal state, and acts as an entry point for the library's " +"behavior." +msgstr "" + +#: src/patterns/ffi/export.md:74 +msgid "" +"It is completely opaque to the user, who cannot create a `DBM` themselves " +"since they don't know its size or layout. Instead, they must call " +"`dbm_open`, and that only gives them _a pointer to one_." +msgstr "" + +#: src/patterns/ffi/export.md:78 +msgid "" +"This means all `DBM`s are \"owned\" by the library in a Rust sense. The " +"internal state of unknown size is kept in memory controlled by the library, " +"not the user. The user can only manage its life cycle with `open` and " +"`close`, and perform operations on it with the other functions." +msgstr "" + +#: src/patterns/ffi/export.md:83 +msgid "" +"The `datum` type was called a \"transactional\" type above. It is designed " +"to facilitate the exchange of information between the library and its user." +msgstr "" + +#: src/patterns/ffi/export.md:86 +msgid "" +"The database is designed to store \"unstructured data\", with no pre-defined " +"length or meaning. As a result, the `datum` is the C equivalent of a Rust " +"slice: a bunch of bytes, and a count of how many there are. The main " +"difference is that there is no type information, which is what `void` " +"indicates." +msgstr "" + +#: src/patterns/ffi/export.md:91 +msgid "" +"Keep in mind that this header is written from the library's point of view. " +"The user likely has some type they are using, which has a known size. But " +"the library does not care, and by the rules of C casting, any type behind a " +"pointer can be cast to `void`." +msgstr "" + +#: src/patterns/ffi/export.md:96 +msgid "" +"As noted earlier, this type is _transparent_ to the user. But also, this " +"type is _owned_ by the user. This has subtle ramifications, due to that " +"pointer inside it. The question is, who owns the memory that pointer points " +"to?" +msgstr "" + +#: src/patterns/ffi/export.md:100 +msgid "" +"The answer for best memory safety is, \"the user\". But in cases such as " +"retrieving a value, the user does not know how to allocate it correctly " +"(since they don't know how long the value is). In this case, the library " +"code is expected to use the heap that the user has access to -- such as the " +"C library `malloc` and `free` -- and then _transfer ownership_ in the Rust " +"sense." +msgstr "" + +#: src/patterns/ffi/export.md:106 +msgid "" +"This may all seem speculative, but this is what a pointer means in C. It " +"means the same thing as Rust: \"user defined lifetime.\" The user of the " +"library needs to read the documentation in order to use it correctly. That " +"said, there are some decisions that have fewer or greater consequences if " +"users do it wrong. Minimizing those are what this best practice is about, " +"and the key is to _transfer ownership of everything that is transparent_." +msgstr "" + +#: src/patterns/ffi/export.md:115 +msgid "" +"This minimizes the number of memory safety guarantees the user must uphold " +"to a relatively small number:" +msgstr "" + +#: src/patterns/ffi/export.md:118 +msgid "" +"Do not call any function with a pointer not returned by `dbm_open` (invalid " +"access or corruption)." +msgstr "" + +#: src/patterns/ffi/export.md:120 +msgid "Do not call any function on a pointer after close (use after free)." +msgstr "" + +#: src/patterns/ffi/export.md:121 +msgid "" +"The `dptr` on any `datum` must be `NULL`, or point to a valid slice of " +"memory at the advertised length." +msgstr "" + +#: src/patterns/ffi/export.md:124 +msgid "" +"In addition, it avoids a lot of pointer provenance issues. To understand " +"why, let us consider an alternative in some depth: key iteration." +msgstr "" + +#: src/patterns/ffi/export.md:127 +msgid "" +"Rust is well known for its iterators. When implementing one, the programmer " +"makes a separate type with a bounded lifetime to its owner, and implements " +"the `Iterator` trait." +msgstr "" + +#: src/patterns/ffi/export.md:131 +msgid "Here is how iteration would be done in Rust for `DBM`:" +msgstr "" + +#: src/patterns/ffi/export.md:149 +msgid "" +"This is clean, idiomatic, and safe. thanks to Rust's guarantees. However, " +"consider what a straightforward API translation would look like:" +msgstr "" + +#: src/patterns/ffi/export.md:155 src/patterns/ffi/export.md:162 +#: src/patterns/ffi/export.md:166 +msgid "" +"// THIS API IS A BAD IDEA! For real applications, use object-based design " +"instead.\n" +msgstr "" + +#: src/patterns/ffi/export.md:170 +msgid "" +"This API loses a key piece of information: the lifetime of the iterator must " +"not exceed the lifetime of the `Dbm` object that owns it. A user of the " +"library could use it in a way which causes the iterator to outlive the data " +"it is iterating on, resulting in reading uninitialized memory." +msgstr "" + +#: src/patterns/ffi/export.md:175 +msgid "" +"This example written in C contains a bug that will be explained afterwards:" +msgstr "" + +#: src/patterns/ffi/export.md:179 +msgid "// DO NOT USE THIS FUNCTION. IT HAS A SUBTLE BUT SERIOUS BUG!\n" +msgstr "" + +#: src/patterns/ffi/export.md:189 +msgid "// an error is indicated by -1\n" +msgstr "" + +#: src/patterns/ffi/export.md:192 +msgid "// end of the iterator\n" +msgstr "" + +#: src/patterns/ffi/export.md:204 +msgid "" +"This bug is a classic. Here's what happens when the iterator returns the end-" +"of-iteration marker:" +msgstr "" + +#: src/patterns/ffi/export.md:207 +msgid "" +"The loop condition sets `l` to zero, and enters the loop because `0 >= 0`." +msgstr "" + +#: src/patterns/ffi/export.md:208 +msgid "The length is incremented, in this case by zero." +msgstr "" + +#: src/patterns/ffi/export.md:209 +msgid "" +"The if statement is true, so the database is closed. There should be a break " +"statement here." +msgstr "" + +#: src/patterns/ffi/export.md:211 +msgid "" +"The loop condition executes again, causing a `next` call on the closed " +"object." +msgstr "" + +#: src/patterns/ffi/export.md:214 +msgid "" +"The worst part about this bug? If the Rust implementation was careful, this " +"code will work most of the time! If the memory for the `Dbm` object is not " +"immediately reused, an internal check will almost certainly fail, resulting " +"in the iterator returning a `-1` indicating an error. But occasionally, it " +"will cause a segmentation fault, or even worse, nonsensical memory " +"corruption!" +msgstr "" + +#: src/patterns/ffi/export.md:220 +msgid "" +"None of this can be avoided by Rust. From its perspective, it put those " +"objects on its heap, returned pointers to them, and gave up control of their " +"lifetimes. The C code simply must \"play nice\"." +msgstr "" + +#: src/patterns/ffi/export.md:224 +msgid "" +"The programmer must read and understand the API documentation. While some " +"consider that par for the course in C, a good API design can mitigate this " +"risk. The POSIX API for `DBM` did this by _consolidating the ownership_ of " +"the iterator with its parent:" +msgstr "" + +#: src/patterns/ffi/export.md:234 +msgid "" +"Thus, all the lifetimes were bound together, and such unsafety was prevented." +msgstr "" + +#: src/patterns/ffi/export.md:238 +msgid "" +"However, this design choice also has a number of drawbacks, which should be " +"considered as well." +msgstr "" + +#: src/patterns/ffi/export.md:241 +msgid "" +"First, the API itself becomes less expressive. With POSIX DBM, there is only " +"one iterator per object, and every call changes its state. This is much more " +"restrictive than iterators in almost any language, even though it is safe. " +"Perhaps with other related objects, whose lifetimes are less hierarchical, " +"this limitation is more of a cost than the safety." +msgstr "" + +#: src/patterns/ffi/export.md:247 +msgid "" +"Second, depending on the relationships of the API's parts, significant " +"design effort may be involved. Many of the easier design points have other " +"patterns associated with them:" +msgstr "" + +#: src/patterns/ffi/export.md:251 +msgid "" +"[Wrapper Type Consolidation](./wrappers.md) groups multiple Rust types " +"together into an opaque \"object\"" +msgstr "" + +#: src/patterns/ffi/export.md:254 +msgid "" +"[FFI Error Passing](../../idioms/ffi/errors.md) explains error handling with " +"integer codes and sentinel return values (such as `NULL` pointers)" +msgstr "" + +#: src/patterns/ffi/export.md:257 +msgid "" +"[Accepting Foreign Strings](../../idioms/ffi/accepting-strings.md) allows " +"accepting strings with minimal unsafe code, and is easier to get right than " +"[Passing Strings to FFI](../../idioms/ffi/passing-strings.md)" +msgstr "" + +#: src/patterns/ffi/export.md:261 +msgid "" +"However, not every API can be done this way. It is up to the best judgement " +"of the programmer as to who their audience is." +msgstr "" + +#: src/patterns/ffi/wrappers.md:5 +msgid "" +"This pattern is designed to allow gracefully handling multiple related " +"types, 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. This ensures " +"that many patterns of access between types can be memory safe, 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 into pointers. In Rust, a pointer means \"the user manages the " +"lifetime of the pointee.\" 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 which Rust can do nothing about. However, some API designs place " +"higher burdens 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 with an object are folded into a \"wrapper type\", while " +"keeping the Rust API clean." +msgstr "" + +#: src/patterns/ffi/wrappers.md:26 +msgid "" +"To understand this, let us look at a classic example of an API to export: " +"iteration through a collection." +msgstr "" + +#: src/patterns/ffi/wrappers.md:29 +msgid "That API looks like this:" +msgstr "" + +#: src/patterns/ffi/wrappers.md:31 +msgid "The iterator is initialized with `first_key`." +msgstr "" + +#: src/patterns/ffi/wrappers.md:32 +msgid "Each call to `next_key` will advance the iterator." +msgstr "" + +#: src/patterns/ffi/wrappers.md:33 +msgid "Calls to `next_key` if the iterator is at the end will do nothing." +msgstr "" + +#: src/patterns/ffi/wrappers.md:34 +msgid "" +"As noted above, the iterator is \"wrapped into\" the collection (unlike the " +"native Rust API)." +msgstr "" + +#: src/patterns/ffi/wrappers.md:37 +msgid "" +"If the iterator implements `nth()` efficiently, then it is possible to make " +"it ephemeral to each function call:" +msgstr "" + +#: src/patterns/ffi/wrappers.md:62 +msgid "As a result, the wrapper is simple and contains no `unsafe` code." +msgstr "" + +#: src/patterns/ffi/wrappers.md:66 +msgid "" +"This makes APIs safer to use, avoiding issues with lifetimes between types. " +"See [Object-Based APIs](./export.md) for more on the advantages and pitfalls " +"this avoids." +msgstr "" + +#: src/patterns/ffi/wrappers.md:72 +msgid "" +"Often, wrapping types is quite difficult, and sometimes a Rust API " +"compromise would make things easier." +msgstr "" + +#: src/patterns/ffi/wrappers.md:75 +msgid "" +"As an example, consider an iterator which does not efficiently implement " +"`nth()`. It would definitely be worth putting in special logic to make the " +"object handle iteration internally, or to support a different access pattern " +"efficiently that only the Foreign Function API will use." +msgstr "" + +#: src/patterns/ffi/wrappers.md:80 +msgid "Trying to Wrap Iterators (and Failing)" +msgstr "" + +#: src/patterns/ffi/wrappers.md:82 +msgid "" +"To wrap any type of iterator into the API correctly, the wrapper would need " +"to do what a C version of the code would do: erase the lifetime of the " +"iterator, and manage it manually." +msgstr "" + +#: src/patterns/ffi/wrappers.md:86 +msgid "Suffice it to say, this is _incredibly_ difficult." +msgstr "" + +#: src/patterns/ffi/wrappers.md:88 +msgid "Here is an illustration of just _one_ pitfall." +msgstr "" + +#: src/patterns/ffi/wrappers.md:90 +msgid "A first version of `MySetWrapper` would look like this:" +msgstr "" + +#: src/patterns/ffi/wrappers.md:96 +msgid "// created from a transmuted Box\n" +msgstr "" + +#: src/patterns/ffi/wrappers.md:101 +msgid "" +"With `transmute` being used to extend a lifetime, and a pointer to hide it, " +"it's ugly already. But it gets even worse: _any other operation can cause " +"Rust `undefined behaviour`_." +msgstr "" + +#: src/patterns/ffi/wrappers.md:105 +msgid "" +"Consider that the `MySet` in the wrapper could be manipulated by other " +"functions during iteration, such as storing a new value to the key it was " +"iterating over. The API doesn't discourage this, and in fact some similar C " +"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:117 +msgid "// DO NOT USE THIS CODE. IT IS UNSAFE TO DEMONSTRATE A PROBLEM.\n" +msgstr "" + +#: src/patterns/ffi/wrappers.md:120 +msgid "// SAFETY: whoops, UB occurs in here!\n" +msgstr "" + +#: src/patterns/ffi/wrappers.md:124 +msgid "/* ...check and cast key and value data... */" +msgstr "" + +#: src/patterns/ffi/wrappers.md:134 +msgid "" +"If the iterator exists when this function is called, we have violated one of " +"Rust's aliasing rules. According to Rust, the mutable reference in this " +"block must have _exclusive_ access to the object. If the iterator simply " +"exists, it's not exclusive, so we have `undefined behaviour`! [^1]" +msgstr "" + +#: src/patterns/ffi/wrappers.md:139 +msgid "" +"To avoid this, we must have a way of ensuring that mutable reference really " +"is exclusive. That basically means clearing out the iterator's shared " +"reference while it exists, and then reconstructing it. In most cases, that " +"will still be less efficient than the C version." +msgstr "" + +#: src/patterns/ffi/wrappers.md:144 +msgid "" +"Some may ask: how can C do this more efficiently? The answer is, it cheats. " +"Rust's aliasing rules are the problem, and C simply ignores them for its " +"pointers. In exchange, it is common to see code that is declared in the " +"manual as \"not thread safe\" under some or all circumstances. In fact, the " +"[GNU C library](https://manpages.debian.org/buster/manpages/" +"attributes.7.en.html) has an entire lexicon dedicated to concurrent behavior!" +msgstr "" + +#: src/patterns/ffi/wrappers.md:151 +msgid "" +"Rust would rather make everything memory safe all the time, for both safety " +"and optimizations that C code cannot attain. Being denied access to certain " +"shortcuts is the price Rust programmers need to pay." +msgstr "" + +#: src/patterns/ffi/wrappers.md:155 +msgid "" +"For the C programmers out there scratching their heads, the iterator need " +"not be read _during_ this code to cause the UB. The exclusivity rule also " +"enables compiler optimizations which may cause inconsistent observations by " +"the iterator's shared reference (e.g. stack spills or reordering " +"instructions for efficiency). These observations may happen _any time after_ " +"the mutable reference is created." +msgstr "" + +#: src/anti_patterns/index.md:3 +msgid "" +"An [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern) is a solution " +"to a \"recurring problem that is usually ineffective and risks being highly " +"counterproductive\". Just as valuable as knowing how to solve a problem, is " +"knowing how _not_ to solve it. Anti-patterns give us great counter-examples " +"to consider relative to design patterns. Anti-patterns are not confined to " +"code. For example, a process can be an anti-pattern, too." +msgstr "" + +#: src/anti_patterns/borrow_clone.md:5 +msgid "" +"The borrow checker prevents Rust users from developing otherwise unsafe code " +"by ensuring that either: only one mutable reference exists, or potentially " +"many but all immutable references exist. If the code written does not hold " +"true to these conditions, this anti-pattern arises when the developer " +"resolves the compiler error by cloning the variable." +msgstr "" + +#: src/anti_patterns/borrow_clone.md:14 +msgid "// define any variable\n" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:16 +msgid "// Borrow `x` -- but clone it first\n" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:19 +msgid "" +"// 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" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:23 +msgid "\"{x}\"" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:24 +msgid "" +"// perform some action on the borrow to prevent rust from optimizing this\n" +"//out of existence\n" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:32 +msgid "" +"It is tempting, particularly for beginners, to use this pattern to resolve " +"confusing issues with the borrow checker. However, there are serious " +"consequences. Using `.clone()` causes a copy of the data to be made. Any " +"changes between the two are not synchronized -- as if two completely " +"separate variables exist." +msgstr "" + +#: src/anti_patterns/borrow_clone.md:38 +msgid "" +"There are special cases -- `Rc` is designed to handle clones " +"intelligently. It internally manages exactly one copy of the data. Invoking " +"`.clone()` on `Rc` produces a new `Rc` instance, which points to the same " +"data as the source `Rc`, while increasing a reference count. The same " +"applies to `Arc`, the thread-safe counterpart of `Rc`." +msgstr "" + +#: src/anti_patterns/borrow_clone.md:44 +msgid "" +"In general, clones should be deliberate, with full understanding of the " +"consequences. If a clone is used to make a borrow checker error disappear, " +"that's a good indication this anti-pattern may be in use." +msgstr "" + +#: src/anti_patterns/borrow_clone.md:48 +msgid "" +"Even though `.clone()` is an indication of a bad pattern, sometimes **it is " +"fine to write inefficient code**, in cases such as when:" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:51 +msgid "the developer is still new to ownership" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:52 +msgid "" +"the code doesn't have great speed or memory constraints (like hackathon " +"projects or prototypes)" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:54 +msgid "" +"satisfying the borrow checker is really complicated, and you prefer to " +"optimize readability over performance" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:57 +msgid "" +"If an unnecessary clone is suspected, The [Rust Book's chapter on Ownership]" +"(https://doc.rust-lang.org/book/ownership.html) should be understood fully " +"before assessing whether the clone is required or not." +msgstr "" + +#: src/anti_patterns/borrow_clone.md:62 +msgid "" +"Also be sure to always run `cargo clippy` in your project, which will detect " +"some cases in which `.clone()` is not necessary." +msgstr "" + +#: src/anti_patterns/borrow_clone.md:67 +msgid "" +"[`mem::{take(_), replace(_)}` to keep owned values in changed enums](../" +"idioms/mem-replace.md)" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:68 +msgid "" +"[`Rc` documentation, which handles .clone() intelligently](http://" +"doc.rust-lang.org/std/rc/)" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:69 +msgid "" +"[`Arc` documentation, a thread-safe reference-counting pointer](https://" +"doc.rust-lang.org/std/sync/struct.Arc.html)" +msgstr "" + +#: src/anti_patterns/borrow_clone.md:70 +msgid "" +"[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 " +"warnings. So they annotate their crate root with the following:" +msgstr "" + +#: src/anti_patterns/deny-warnings.md:12 +msgid "// 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 Rust's famed stability. Sometimes new features or old misfeatures need a " +"change in how things are done, thus lints are written that `warn` for a " +"certain grace 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 method. This was deemed a bad idea, but in order to make the transition " +"smooth, the `overlapping-inherent-impls` lint was introduced to give a " +"warning to those 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 " +"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](https://" +"github.com/rust-lang/rust-clippy)) can no longer be used unless the " +"annotation is removed. This is mitigated with [\\--cap-lints](https://" +"doc.rust-lang.org/rustc/lints/levels.html#capping-lints). The `--cap-" +"lints=warn` command line argument, turns all `deny` lint errors into " +"warnings." +msgstr "" + +#: src/anti_patterns/deny-warnings.md:42 +#: src/functional/generics-type-classes.md:226 +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 setting from the code, and second, we can name the lints we want to " +"deny 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 " +"Travis, but remember that this may break the build when something changes) " +"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. " +"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:81 +msgid "" +"In addition, the following `allow`ed lints may be a good idea to `deny`:" +msgstr "" + +#: src/anti_patterns/deny-warnings.md:96 +msgid "Some may also want to add `missing-copy-implementations` to their list." +msgstr "" + +#: src/anti_patterns/deny-warnings.md:98 +msgid "" +"Note that we explicitly did not add the `deprecated` lint, as it is fairly " +"certain that there will be more deprecated APIs in the future." +msgstr "" + +#: src/anti_patterns/deny-warnings.md:103 +msgid "" +"[A collection of all clippy lints](https://rust-lang.github.io/rust-clippy/" +"master)" +msgstr "" + +#: src/anti_patterns/deny-warnings.md:104 +msgid "" +"[deprecate attribute](https://doc.rust-lang.org/reference/" +"attributes.html#deprecation) documentation" +msgstr "" + +#: src/anti_patterns/deny-warnings.md:105 +msgid "" +"Type `rustc -W help` for a list of lints on your system. Also type `rustc --" +"help` for a general list of options" +msgstr "" + +#: src/anti_patterns/deny-warnings.md:107 +msgid "" +"[rust-clippy](https://github.com/rust-lang/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 methods." +msgstr "" + +#: src/anti_patterns/deref.md:10 +msgid "" +"Sometimes we want to emulate the following common pattern from OO languages " +"such as Java:" +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:56 +msgid "" +"There is no struct inheritance in Rust. Instead we use composition and " +"include an instance of `Foo` in `Bar` (since the field is a value, it is " +"stored inline, so if there were fields, they would have the same layout in " +"memory as the Java 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` as the target (returning the embedded `Foo` field). That means that " +"when we dereference a `Bar` (for example, using `*`) then we will get a " +"`Foo`. That is pretty weird. Dereferencing usually gives a `T` from a " +"reference to `T`, here we have two unrelated types. However, since the dot " +"operator does implicit dereferencing, it means that the method call will " +"search for methods on `Foo` as well as `Bar`." +msgstr "" + +#: src/anti_patterns/deref.md:71 +msgid "You save a little boilerplate, e.g.," +msgstr "" + +#: src/anti_patterns/deref.md:83 +msgid "" +"Most importantly this is a surprising idiom - future programmers reading " +"this in code will not expect this to happen. That's because we are misusing " +"the `Deref` trait rather than using it as intended (and documented, etc.). " +"It's also because 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 " +"inheritance in Java or C++ does. Furthermore, traits implemented by `Foo` " +"are not automatically implemented for `Bar`, so this pattern interacts badly " +"with 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 regards to `self`. Usually it remains a reference to the sub-class, " +"with this 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 " +"interfaces, class-based privacy, or other inheritance-related features. So, " +"it gives an experience that will be subtly surprising to programmers used to " +"Java inheritance, etc." +msgstr "" + +#: src/anti_patterns/deref.md:104 +msgid "" +"There is no one good alternative. Depending on the exact circumstances it " +"might be better to re-implement using traits or to write out the facade " +"methods to dispatch to `Foo` manually. We do intend to add a mechanism for " +"inheritance similar to this to Rust, but it is likely to be some time before " +"it reaches stable Rust. See these [blog](http://aturon.github.io/blog/" +"2015/09/18/reuse/) [posts](http://smallcultfollowing.com/babysteps/blog/" +"2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/) and this " +"[RFC issue](https://github.com/rust-lang/rfcs/issues/349) for more details." +msgstr "" + +#: src/anti_patterns/deref.md:113 +msgid "" +"The `Deref` trait is designed for the implementation of custom pointer " +"types. The intention is that it will take a pointer-to-`T` to a `T`, not " +"convert between different types. It is a shame that this isn't (probably " +"cannot be) enforced by the trait definition." +msgstr "" + +#: src/anti_patterns/deref.md:118 +msgid "" +"Rust tries to strike a careful balance between explicit and implicit " +"mechanisms, favouring explicit conversions between types. Automatic " +"dereferencing in the dot operator is a case where the ergonomics strongly " +"favour an implicit mechanism, but the intention is that this is limited to " +"degrees of indirection, not conversion between arbitrary types." +msgstr "" + +#: src/anti_patterns/deref.md:126 +msgid "[Collections are smart pointers idiom](../idioms/deref.md)." +msgstr "" + +#: src/anti_patterns/deref.md:127 +msgid "" +"Delegation crates for less boilerplate like [delegate](https://crates.io/" +"crates/delegate) or [ambassador](https://crates.io/crates/ambassador)" +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 [functional programming]" +"(https://en.wikipedia.org/wiki/Functional_programming) paradigms." +msgstr "" + +#: src/functional/index.md:7 +msgid "" +"In computer science, _functional programming_ is a programming paradigm " +"where programs are constructed by applying and composing functions. It is a " +"declarative programming paradigm in which function definitions are trees of " +"expressions that each return a value, rather than a sequence of imperative " +"statements which change the state of the program." +msgstr "" + +#: src/functional/paradigms.md:3 +msgid "" +"One of the biggest hurdles to understanding functional programs when coming " +"from an imperative background is the shift in thinking. Imperative programs " +"describe **how** to do something, whereas declarative programs describe " +"**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:15 +msgid "\"{sum}\"" +msgstr "" + +#: src/functional/paradigms.md:18 +msgid "" +"With imperative programs, we have to play compiler to see what is happening. " +"Here, we start with a `sum` of `0`. Next, we iterate through the range from " +"1 to 10. Each time through the loop, we add the corresponding value in the " +"range. Then we print it out." +msgstr "" + +#: src/functional/paradigms.md:23 +msgid "`i`" +msgstr "" + +#: src/functional/paradigms.md:23 +msgid "`sum`" +msgstr "" + +#: src/functional/paradigms.md:25 src/functional/paradigms.md:59 +#: src/functional/paradigms.md:60 +msgid "1" +msgstr "" + +#: src/functional/paradigms.md:26 src/functional/paradigms.md:60 +msgid "2" +msgstr "" + +#: src/functional/paradigms.md:26 src/functional/paradigms.md:27 +#: src/functional/paradigms.md:60 src/functional/paradigms.md:61 +msgid "3" +msgstr "" + +#: src/functional/paradigms.md:27 src/functional/paradigms.md:30 +#: src/functional/paradigms.md:61 src/functional/paradigms.md:62 +#: src/functional/paradigms.md:64 +msgid "6" +msgstr "" + +#: src/functional/paradigms.md:28 src/functional/paradigms.md:62 +msgid "4" +msgstr "" + +#: src/functional/paradigms.md:28 src/functional/paradigms.md:34 +#: src/functional/paradigms.md:62 src/functional/paradigms.md:63 +#: src/functional/paradigms.md:68 +msgid "10" +msgstr "" + +#: src/functional/paradigms.md:29 src/functional/paradigms.md:63 +msgid "5" +msgstr "" + +#: src/functional/paradigms.md:29 src/functional/paradigms.md:63 +#: src/functional/paradigms.md:64 +msgid "15" +msgstr "" + +#: src/functional/paradigms.md:30 src/functional/paradigms.md:64 +#: src/functional/paradigms.md:65 +msgid "21" +msgstr "" + +#: src/functional/paradigms.md:31 src/functional/paradigms.md:65 +msgid "7" +msgstr "" + +#: src/functional/paradigms.md:31 src/functional/paradigms.md:65 +#: src/functional/paradigms.md:66 +msgid "28" +msgstr "" + +#: src/functional/paradigms.md:32 src/functional/paradigms.md:66 +msgid "8" +msgstr "" + +#: src/functional/paradigms.md:32 src/functional/paradigms.md:66 +#: src/functional/paradigms.md:67 +msgid "36" +msgstr "" + +#: src/functional/paradigms.md:33 src/functional/paradigms.md:67 +msgid "9" +msgstr "" + +#: src/functional/paradigms.md:33 src/functional/paradigms.md:67 +#: src/functional/paradigms.md:68 +msgid "45" +msgstr "" + +#: src/functional/paradigms.md:34 src/functional/paradigms.md:68 +msgid "55" +msgstr "" + +#: src/functional/paradigms.md:36 +msgid "" +"This is how most of us start out programming. We learn that a program is a " +"set of steps." +msgstr "" + +#: src/functional/paradigms.md:39 +msgid "Declarative" +msgstr "" + +#: src/functional/paradigms.md:42 +msgid "\"{}\"" +msgstr "" + +#: src/functional/paradigms.md:45 +msgid "" +"Whoa! This is really different! What's going on here? Remember that with " +"declarative programs we are describing **what** to do, rather than **how** " +"to do it. `fold` is a function that [composes](https://en.wikipedia.org/wiki/" +"Function_composition) 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`) " +"with a range from 1 to 10. The `0` is the starting point, so `a` is `0` at " +"first. `b` is the first element of the range, `1`. `0 + 1 = 1` is the " +"result. So now we `fold` again, with `a = 1`, `b = 2` and so `1 + 2 = 3` is " +"the next result. This process continues until we get to the last element in " +"the range, `10`." +msgstr "" + +#: src/functional/paradigms.md:57 +msgid "`a`" +msgstr "" + +#: src/functional/paradigms.md:57 +msgid "`b`" +msgstr "" + +#: src/functional/paradigms.md:57 +msgid "result" +msgstr "" + +#: src/functional/paradigms.md:59 +msgid "0" +msgstr "" + +#: src/functional/generics-type-classes.md:5 +msgid "" +"Rust's type system is designed more like functional languages (like Haskell) " +"rather than imperative languages (like Java and C++). As a result, Rust can " +"turn many kinds of programming problems into \"static typing\" problems. " +"This is one of the biggest wins of choosing a functional language, and is " +"critical to many 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 " +"example, generic types are a meta-programming construct for the compiler. " +"`vector` and `vector` in C++ are just two different copies of the " +"same boilerplate code for a `vector` type (known as a `template`) with two " +"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 as a \"type class constraint\", and each different parameter " +"filled in by an end user _actually changes the type_. In other words, " +"`Vec` and `Vec` _are two different types_, which are recognized " +"as distinct by all parts of the type system." +msgstr "" + +#: src/functional/generics-type-classes.md:23 +msgid "" +"This is called **monomorphization**, where different types are created from " +"**polymorphic** code. This special behavior requires `impl` blocks to " +"specify generic parameters. Different values for the generic type cause " +"different types, 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. However, this allows the attachment of not only additional behavior " +"to 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, " +"where new members can be added to objects willy-nilly by any constructor. " +"However, unlike those languages, all of Rust's additional methods can be " +"type checked when they are used, because their generics are statically " +"defined. That 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. " +"Because of the software involved, there are two different protocols you need " +"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 " +"them. It will have protocol handlers and listen for both kinds of requests. " +"The main application logic will then allow a lab administrator to configure " +"storage 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 " +"information, no matter what protocol they came from: an authentication " +"method, and a file name to retrieve. A straightforward implementation would " +"look something like this:" +msgstr "" + +#: src/functional/generics-type-classes.md:66 +msgid "" +"This design might work well enough. But now suppose you needed to support " +"adding metadata that was _protocol specific_. For example, with NFS, you " +"wanted to determine what their mount point was in order to enforce " +"additional security rules." +msgstr "" + +#: src/functional/generics-type-classes.md:71 +msgid "" +"The way the current struct is designed leaves the protocol decision until " +"runtime. That means any method that applies to one protocol and not the " +"other 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:85 +msgid "// ... other methods ...\n" +msgstr "" + +#: src/functional/generics-type-classes.md:87 +msgid "" +"/// Gets an NFS mount point if this is an NFS request. Otherwise,\n" +" /// return None.\n" +msgstr "" + +#: src/functional/generics-type-classes.md:95 +msgid "" +"Every caller of `mount_point()` must check for `None` and write code to " +"handle it. This is true even if they know only NFS requests are ever used in " +"a given 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 " +"request types were confused. After all, the entire path of the user's code, " +"including what functions from the library they use, will know whether a " +"request 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 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:114 +msgid "// NFS session management omitted\n" +msgstr "" + +#: src/functional/generics-type-classes.md:118 +msgid "// no authentication in bootp\n" +msgstr "" + +#: src/functional/generics-type-classes.md:120 +msgid "" +"// private module, lest outside users invent their own protocol kinds!\n" +msgstr "" + +#: src/functional/generics-type-classes.md:149 +msgid "// no additional metadata\n" +msgstr "" + +#: src/functional/generics-type-classes.md:159 +msgid "// keep internal to prevent impls\n" +msgstr "" + +#: src/functional/generics-type-classes.md:160 +msgid "// re-export so callers can see them\n" +msgstr "" + +#: src/functional/generics-type-classes.md:166 +msgid "// all common API parts go into a generic impl block\n" +msgstr "" + +#: src/functional/generics-type-classes.md:177 +msgid "// all protocol-specific impls go into their own block\n" +msgstr "" + +#: src/functional/generics-type-classes.md:186 +msgid "// your code here\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 " +"type;" +msgstr "" + +#: src/functional/generics-type-classes.md:197 +msgid "\"/secure\"" +msgstr "" + +#: src/functional/generics-type-classes.md:197 +msgid "\"Access denied\"" +msgstr "" + +#: src/functional/generics-type-classes.md:198 +msgid "// continue on...\n" +msgstr "" + +#: src/functional/generics-type-classes.md:200 +msgid "// Rest of the code here\n" +msgstr "" + +#: src/functional/generics-type-classes.md:205 +msgid "" +"They would get a syntax error. The type `FileDownloadRequest` does " +"not implement `mount_point()`, only the type `FileDownloadRequest` " +"does. And that is created by the NFS module, not the BOOTP module of course!" +msgstr "" + +#: src/functional/generics-type-classes.md:211 +msgid "" +"First, it allows fields that are common to multiple states to be de-" +"duplicated. By making the non-shared fields generic, they are implemented " +"once." +msgstr "" + +#: src/functional/generics-type-classes.md:214 +msgid "" +"Second, it makes the `impl` blocks easier to read, because they are broken " +"down by state. Methods common to all states are typed once in one block, and " +"methods unique to one state are in a separate block." +msgstr "" + +#: src/functional/generics-type-classes.md:218 +msgid "" +"Both of these mean there are fewer lines of code, and they are better " +"organized." +msgstr "" + +#: src/functional/generics-type-classes.md:222 +msgid "" +"This currently increases the size of the binary, due to the way " +"monomorphization is implemented in the compiler. Hopefully the " +"implementation will be able to improve in the future." +msgstr "" + +#: src/functional/generics-type-classes.md:228 +msgid "" +"If a type seems to need a \"split API\" due to construction or partial " +"initialization, consider the [Builder Pattern](../patterns/creational/" +"builder.md) instead." +msgstr "" + +#: src/functional/generics-type-classes.md:232 +msgid "" +"If the API between types does not change -- only the behavior does -- then " +"the [Strategy Pattern](../patterns/behavioural/strategy.md) is better used " +"instead." +msgstr "" + +#: src/functional/generics-type-classes.md:238 +msgid "This pattern is used throughout the standard library:" +msgstr "" + +#: src/functional/generics-type-classes.md:240 +msgid "" +"`Vec` can be cast from a String, unlike every other type of `Vec`.[^1]" +msgstr "" + +#: src/functional/generics-type-classes.md:241 +msgid "" +"Iterators can be cast into a binary heap, but only if they contain a type " +"that implements the `Ord` trait.[^2]" +msgstr "" + +#: src/functional/generics-type-classes.md:243 +msgid "" +"The `to_string` method was specialized for `Cow` only of type `str`.[^3]" +msgstr "" + +#: src/functional/generics-type-classes.md:245 +msgid "It is also used by several popular crates to allow API flexibility:" +msgstr "" + +#: src/functional/generics-type-classes.md:247 +msgid "" +"The `embedded-hal` ecosystem used for embedded devices makes extensive use " +"of this pattern. For example, it allows statically verifying the " +"configuration of device registers used to control embedded pins. When a pin " +"is put into a mode, it returns a `Pin` struct, whose generic " +"determines the functions usable in that mode, which are not on the `Pin` " +"itself. [^4]" +msgstr "" + +#: src/functional/generics-type-classes.md:253 +msgid "" +"The `hyper` HTTP client library uses this to expose rich APIs for different " +"pluggable requests. Clients with different connectors have different methods " +"on them as well as different trait implementations, while a core set of " +"methods apply to any connector. [^5]" +msgstr "" + +#: src/functional/generics-type-classes.md:258 +msgid "" +"The \"type state\" pattern -- where an object gains and loses API based on " +"an internal state or invariant -- is implemented in Rust using the same " +"basic concept, and a slightly different technique. [^6]" +msgstr "" + +#: src/functional/generics-type-classes.md:262 +msgid "" +"See: [impl From\\ for Vec\\](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\\ FromIterator\\ for BinaryHeap\\](https://" +"web.archive.org/web/20201030132806/https://doc.rust-lang.org/stable/src/" +"alloc/collections/binary_heap.rs.html#1330-1335)" +msgstr "" + +#: src/functional/generics-type-classes.md:268 +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:271 +msgid "" +"Example: [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:274 +msgid "" +"See: [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:277 +msgid "" +"See: [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/) and [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/optics.md:1 +msgid "Functional Language Optics" +msgstr "" + +#: src/functional/optics.md:3 +msgid "" +"Optics is a type of API design that is common to functional languages. This " +"is a pure functional concept that is not frequently used in Rust." +msgstr "" + +#: src/functional/optics.md:6 +msgid "" +"Nevertheless, exploring the concept may be helpful to understand other " +"patterns in Rust APIs, such as [visitors](../patterns/behavioural/" +"visitor.md). They also have niche use cases." +msgstr "" + +#: src/functional/optics.md:10 +msgid "" +"This is quite a large topic, and would require actual books on language " +"design to fully get into its abilities. However their applicability in Rust " +"is much simpler." +msgstr "" + +#: src/functional/optics.md:14 +msgid "" +"To explain the relevant parts of the concept, the `Serde`\\-API will be used " +"as an example, as it is one that is difficult for many to understand from " +"simply the API documentation." +msgstr "" + +#: src/functional/optics.md:18 +msgid "" +"In the process, different specific patterns, called Optics, will be covered. " +"These are _The Iso_, _The Poly Iso_, and _The Prism_." +msgstr "" + +#: src/functional/optics.md:21 +msgid "An API Example: Serde" +msgstr "" + +#: src/functional/optics.md:23 +msgid "" +"Trying to understand the way _Serde_ works by only reading the API is a " +"challenge, especially the first time. Consider the `Deserializer` trait, " +"implemented by any library which parses a new data format:" +msgstr "" + +#: src/functional/optics.md:39 src/functional/optics.md:61 +#: src/functional/optics.md:379 src/functional/optics.md:401 +msgid "// remainder omitted\n" +msgstr "" + +#: src/functional/optics.md:43 +msgid "And here's the definition of the `Visitor` trait passed in generically:" +msgstr "" + +#: src/functional/optics.md:65 +msgid "" +"There is a lot of type erasure going on here, with multiple levels of " +"associated types being passed back and forth." +msgstr "" + +#: src/functional/optics.md:68 +msgid "" +"But what is the big picture? Why not just have the `Visitor` return the " +"pieces the caller needs in a streaming API, and call it a day? Why all the " +"extra pieces?" +msgstr "" + +#: src/functional/optics.md:72 +msgid "" +"One way to understand it is to look at a functional languages concept called " +"_optics_." +msgstr "" + +#: src/functional/optics.md:75 +msgid "" +"This is a way to do composition of behavior and proprieties that is designed " +"to facilitate patterns common to Rust: failure, type transformation, etc.[^1]" +msgstr "" + +#: src/functional/optics.md:78 +msgid "" +"The Rust language does not have very good support for these directly. " +"However, they appear in the design of the language itself, and their " +"concepts can help to understand some of Rust's APIs. As a result, this " +"attempts to explain the concepts with the way Rust does it." +msgstr "" + +#: src/functional/optics.md:83 +msgid "" +"This will perhaps shed light on what those APIs are achieving: specific " +"properties of composability." +msgstr "" + +#: src/functional/optics.md:86 +msgid "Basic Optics" +msgstr "" + +#: src/functional/optics.md:88 +msgid "The Iso" +msgstr "" + +#: src/functional/optics.md:90 +msgid "" +"The Iso is a value transformer between two types. It is extremely simple, " +"but a conceptually important building block." +msgstr "" + +#: src/functional/optics.md:93 +msgid "" +"As an example, suppose that we have a custom Hash table structure used as a " +"concordance for a document.[^2] It uses strings for keys (words) and a list " +"of indexes for values (file offsets, for instance)." +msgstr "" + +#: src/functional/optics.md:97 +msgid "" +"A key feature is the ability to serialize this format to disk. A \"quick and " +"dirty\" approach would be to implement a conversion to and from a string in " +"JSON format. (Errors are ignored for the time being, they will be handled " +"later.)" +msgstr "" + +#: src/functional/optics.md:101 +msgid "To write it in a normal form expected by functional language users:" +msgstr "" + +#: src/functional/optics.md:110 +msgid "" +"The Iso is thus a pair of functions which convert values of different types: " +"`serialize` and `deserialize`." +msgstr "" + +#: src/functional/optics.md:113 +msgid "A straightforward implementation:" +msgstr "" + +#: src/functional/optics.md:129 +msgid "// invalid concordances are empty\n" +msgstr "" + +#: src/functional/optics.md:136 +msgid "" +"This may seem rather silly. In Rust, this type of behavior is typically done " +"with traits. After all, the standard library has `FromStr` and `ToString` in " +"it." +msgstr "" + +#: src/functional/optics.md:139 +msgid "But that is where our next subject comes in: Poly Isos." +msgstr "" + +#: src/functional/optics.md:141 +msgid "Poly Isos" +msgstr "" + +#: src/functional/optics.md:143 +msgid "" +"The previous example was simply converting between values of two fixed " +"types. This next block builds upon it with generics, and is more interesting." +msgstr "" + +#: src/functional/optics.md:146 +msgid "" +"Poly Isos allow an operation to be generic over any type while returning a " +"single type." +msgstr "" + +#: src/functional/optics.md:149 +msgid "" +"This brings us closer to parsing. Consider what a basic parser would do " +"ignoring error cases. Again, this is its normal form:" +msgstr "" + +#: src/functional/optics.md:159 +msgid "Here we have our first generic, the type `T` being converted." +msgstr "" + +#: src/functional/optics.md:161 +msgid "" +"In Rust, this could be implemented with a pair of traits in the standard " +"library: `FromStr` and `ToString`. The Rust version even handles errors:" +msgstr "" + +#: src/functional/optics.md:176 +msgid "" +"Unlike the Iso, the Poly Iso allows application of multiple types, and " +"returns them generically. This is what you would want for a basic string " +"parser." +msgstr "" + +#: src/functional/optics.md:179 +msgid "" +"At first glance, this seems like a good option for writing a parser. Let's " +"see it in action:" +msgstr "" + +#: src/functional/optics.md:208 src/functional/optics.md:282 +msgid "\"hello\"" +msgstr "" + +#: src/functional/optics.md:210 +msgid "\"Our Test Struct as JSON: {}\"" +msgstr "" + +#: src/functional/optics.md:214 +msgid "That seems quite logical. However, there are two problems with this." +msgstr "" + +#: src/functional/optics.md:216 +msgid "" +"First, `to_string` does not indicate to API users, \"this is JSON.\" Every " +"type would need to agree on a JSON representation, and many of the types in " +"the Rust standard library already don't. Using this is a poor fit. This can " +"easily be resolved with our own trait." +msgstr "" + +#: src/functional/optics.md:221 +msgid "But there is a second, subtler problem: scaling." +msgstr "" + +#: src/functional/optics.md:223 +msgid "" +"When every type writes `to_string` by hand, this works. But if every single " +"person who wants their type to be serializable has to write a bunch of code " +"-- and possibly different JSON libraries -- to do it themselves, it will " +"turn into a mess very quickly!" +msgstr "" + +#: src/functional/optics.md:228 +msgid "" +"The answer is one of Serde's two key innovations: an independent data model " +"to represent Rust data in structures common to data serialization languages. " +"The result is that it can use Rust's code generation abilities to create an " +"intermediary conversion type it calls a `Visitor`." +msgstr "" + +#: src/functional/optics.md:233 +msgid "" +"This means, in normal form (again, skipping error handling for simplicity):" +msgstr "" + +#: src/functional/optics.md:247 +msgid "" +"The result is one Poly Iso and one Iso (respectively). Both of these can be " +"implemented with traits:" +msgstr "" + +#: src/functional/optics.md:263 +msgid "" +"Because there is a uniform set of rules to transform Rust structures to the " +"independent form, it is even possible to have code generation creating the " +"`Visitor` associated with type `T`:" +msgstr "" + +#: src/functional/optics.md:268 +msgid "// the \"Serde\" derive creates the trait impl block\n" +msgstr "" + +#: src/functional/optics.md:273 +msgid "// user writes this macro to generate an associated visitor type\n" +msgstr "" + +#: src/functional/optics.md:278 +msgid "But let's actually try that approach." +msgstr "" + +#: src/functional/optics.md:284 +msgid "\"Our Test Struct as JSON: {a_data}\"" +msgstr "" + +#: src/functional/optics.md:290 +msgid "" +"It turns out that the conversion isn't symmetric after all! On paper it is, " +"but with the auto-generated code the name of the actual type necessary to " +"convert all the way from `String` is hidden. We'd need some kind of " +"`generated_visitor_for!` macro to obtain the type name." +msgstr "" + +#: src/functional/optics.md:295 +msgid "It's wonky, but it works... until we get to the elephant in the room." +msgstr "" + +#: src/functional/optics.md:297 +msgid "" +"The only format currently supported is JSON. How would we support more " +"formats?" +msgstr "" + +#: src/functional/optics.md:299 +msgid "" +"The current design requires completely re-writing all of the code generation " +"and creating a new Serde trait. That is quite terrible and not extensible at " +"all!" +msgstr "" + +#: src/functional/optics.md:302 +msgid "In order to solve that, we need something more powerful." +msgstr "" + +#: src/functional/optics.md:304 +msgid "Prism" +msgstr "" + +#: src/functional/optics.md:306 +msgid "" +"To take format into account, we need something in normal form like this:" +msgstr "" + +#: src/functional/optics.md:315 +msgid "" +"This construct is called a Prism. It is \"one level higher\" in generics " +"than Poly Isos (in this case, the \"intersecting\" type F is the key)." +msgstr "" + +#: src/functional/optics.md:318 +msgid "" +"Unfortunately because `Visitor` is a trait (since each incarnation requires " +"its own custom code), this would require a kind of generic type boundary " +"that Rust does not support." +msgstr "" + +#: src/functional/optics.md:322 +msgid "" +"Fortunately, we still have that `Visitor` type from before. What is the " +"`Visitor` doing? It is attempting to allow each data structure to define the " +"way it is itself parsed." +msgstr "" + +#: src/functional/optics.md:326 +msgid "" +"Well what if we could add one more interface for the generic format? Then " +"the `Visitor` is just an implementation detail, and it would \"bridge\" the " +"two APIs." +msgstr "" + +#: src/functional/optics.md:329 +msgid "In normal form:" +msgstr "" + +#: src/functional/optics.md:348 +msgid "" +"And what do you know, a pair of Poly Isos at the bottom which can be " +"implemented as traits!" +msgstr "" + +#: src/functional/optics.md:351 +msgid "Thus we have the Serde API:" +msgstr "" + +#: src/functional/optics.md:353 +msgid "" +"Each type to be serialized implements `Deserialize` or `Serialize`, " +"equivalent to the `Serde` class" +msgstr "" + +#: src/functional/optics.md:355 +msgid "" +"They get a type (well two, one for each direction) implementing the " +"`Visitor` trait, which is usually (but not always) done through code " +"generated by a derive macro. This contains the logic to construct or " +"destruct between the data type and the format of the Serde data model." +msgstr "" + +#: src/functional/optics.md:359 +msgid "" +"The type implementing the `Deserializer` trait handles all details specific " +"to the format, being \"driven by\" the `Visitor`." +msgstr "" + +#: src/functional/optics.md:362 +msgid "" +"This splitting and Rust type erasure is really to achieve a Prism through " +"indirection." +msgstr "" + +#: src/functional/optics.md:365 +msgid "You can see it on the `Deserializer` trait" +msgstr "" + +#: src/functional/optics.md:383 +msgid "And the visitor:" +msgstr "" + +#: src/functional/optics.md:405 +msgid "And the trait `Deserialize` implemented by the macros:" +msgstr "" + +#: src/functional/optics.md:415 +msgid "This has been abstract, so let's look at a concrete example." +msgstr "" + +#: src/functional/optics.md:417 +msgid "" +"How does actual Serde deserialize a bit of JSON into `struct Concordance` " +"from earlier?" +msgstr "" + +#: src/functional/optics.md:420 +msgid "" +"The user would call a library function to deserialize the data. This would " +"create a `Deserializer` based on the JSON format." +msgstr "" + +#: src/functional/optics.md:422 +msgid "" +"Based on the fields in the struct, a `Visitor` would be created (more on " +"that in a moment) which knows how to create each type in a generic data " +"model that was needed to represent it: `Vec` (list), `u64` and `String`." +msgstr "" + +#: src/functional/optics.md:425 +msgid "The deserializer would make calls to the `Visitor` as it parsed items." +msgstr "" + +#: src/functional/optics.md:426 +msgid "" +"The `Visitor` would indicate if the items found were expected, and if not, " +"raise an error to indicate deserialization has failed." +msgstr "" + +#: src/functional/optics.md:429 +msgid "For our very simple structure above, the expected pattern would be:" +msgstr "" + +#: src/functional/optics.md:431 +msgid "" +"Begin visiting a map (_Serde_'s equivalent to `HashMap` or JSON's " +"dictionary)." +msgstr "" + +#: src/functional/optics.md:433 +msgid "Visit a string key called \"keys\"." +msgstr "" + +#: src/functional/optics.md:434 +msgid "Begin visiting a map value." +msgstr "" + +#: src/functional/optics.md:435 +msgid "For each item, visit a string key then an integer value." +msgstr "" + +#: src/functional/optics.md:436 src/functional/optics.md:443 +msgid "Visit the end of the map." +msgstr "" + +#: src/functional/optics.md:437 +msgid "Store the map into the `keys` field of the data structure." +msgstr "" + +#: src/functional/optics.md:438 +msgid "Visit a string key called \"value_table\"." +msgstr "" + +#: src/functional/optics.md:439 +msgid "Begin visiting a list value." +msgstr "" + +#: src/functional/optics.md:440 +msgid "For each item, visit an integer." +msgstr "" + +#: src/functional/optics.md:441 +msgid "Visit the end of the list" +msgstr "" + +#: src/functional/optics.md:442 +msgid "Store the list into the `value_table` field." +msgstr "" + +#: src/functional/optics.md:445 +msgid "But what determines which \"observation\" pattern is expected?" +msgstr "" + +#: src/functional/optics.md:447 +msgid "" +"A functional programming language would be able to use currying to create " +"reflection of each type based on the type itself. Rust does not support " +"that, so every single type would need to have its own code written based on " +"its fields and their properties." +msgstr "" + +#: src/functional/optics.md:452 +msgid "_Serde_ solves this usability challenge with a derive macro:" +msgstr "" + +#: src/functional/optics.md:464 +msgid "" +"That macro simply generates an impl block causing the struct to implement a " +"trait called `Deserialize`." +msgstr "" + +#: src/functional/optics.md:467 +msgid "" +"This is the function that determines how to create the struct itself. Code " +"is generated based on the struct's fields. When the parsing library is " +"called - in our example, a JSON parsing library - it creates a " +"`Deserializer` and calls `Type::deserialize` with it as a parameter." +msgstr "" + +#: src/functional/optics.md:472 +msgid "" +"The `deserialize` code will then create a `Visitor` which will have its " +"calls \"refracted\" by the `Deserializer`. If everything goes well, " +"eventually that `Visitor` will construct a value corresponding to the type " +"being parsed and return it." +msgstr "" + +#: src/functional/optics.md:477 +msgid "" +"For a complete example, see the [_Serde_ documentation](https://serde.rs/" +"deserialize-struct.html)." +msgstr "" + +#: src/functional/optics.md:480 +msgid "" +"The result is that types to be deserialized only implement the \"top layer\" " +"of the API, and file formats only need to implement the \"bottom layer\". " +"Each piece can then \"just work\" with the rest of the ecosystem, since " +"generic types will bridge them." +msgstr "" + +#: src/functional/optics.md:485 +msgid "" +"In conclusion, Rust's generic-inspired type system can bring it close to " +"these concepts and use their power, as shown in this API design. But it may " +"also need procedural macros to create bridges for its generics." +msgstr "" + +#: src/functional/optics.md:489 +msgid "" +"If you are interested in learning more about this topic, please check the " +"following section." +msgstr "" + +#: src/functional/optics.md:492 +msgid "See Also" +msgstr "" + +#: src/functional/optics.md:494 +msgid "" +"[lens-rs crate](https://crates.io/crates/lens-rs) for a pre-built lenses " +"implementation, with a cleaner interface than these examples" +msgstr "" + +#: src/functional/optics.md:496 +msgid "" +"[Serde](https://serde.rs) itself, which makes these concepts intuitive for " +"end users (i.e. defining the structs) without needing to understand the " +"details" +msgstr "" + +#: src/functional/optics.md:498 +msgid "" +"[luminance](https://github.com/phaazon/luminance-rs) is a crate for drawing " +"computer graphics that uses similar API design, including procedural macros " +"to create full prisms for buffers of different pixel types that remain " +"generic" +msgstr "" + +#: src/functional/optics.md:501 +msgid "" +"[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) that is very readable even " +"without Scala expertise." +msgstr "" + +#: src/functional/optics.md:503 +msgid "" +"[Paper: Profunctor Optics: Modular Data Accessors](https://web.archive.org/" +"web/20220701102832/https://arxiv.org/ftp/arxiv/papers/1703/1703.10857.pdf)" +msgstr "" + +#: src/functional/optics.md:505 +msgid "" +"[Musli](https://github.com/udoprog/musli) is a library which attempts to use " +"a similar structure with a different approach, e.g. doing away with the " +"visitor" +msgstr "" + +#: src/functional/optics.md:508 +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/functional/optics.md:510 +msgid "" +"[Concordance on Wikipedia](https://en.wikipedia.org/wiki/" +"Concordance_(publishing))" +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 " +"Nicholas Cameron at the PDRust (2016)" +msgstr "" + +#: src/additional_resources/index.md:9 +msgid "" +"[Writing Idiomatic Libraries in Rust](https://www.youtube.com/watch?" +"v=0zOg8_B71gE) by Pascal Hertleif at RustFest (2017)" +msgstr "" + +#: src/additional_resources/index.md:11 +msgid "" +"[Rust Programming Techniques](https://www.youtube.com/watch?v=vqavdUGKeb4) " +"by 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: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): A class should only have a single responsibility, " +"that is, only changes to one part of the software's specification should be " +"able to affect the specification of the class." +msgstr "" + +#: src/additional_resources/design-principles.md:13 +msgid "" +"[Open/Closed Principle (OCP)](https://en.wikipedia.org/wiki/" +"Open%E2%80%93closed_principle): \"Software entities ... should be open for " +"extension, but closed for modification.\"" +msgstr "" + +#: src/additional_resources/design-principles.md:16 +msgid "" +"[Liskov Substitution Principle (LSP)](https://en.wikipedia.org/wiki/" +"Liskov_substitution_principle): \"Objects in a program should be replaceable " +"with instances of their subtypes without altering the correctness of that " +"program.\"" +msgstr "" + +#: src/additional_resources/design-principles.md:19 +msgid "" +"[Interface Segregation Principle (ISP)](https://en.wikipedia.org/wiki/" +"Interface_segregation_principle): \"Many client-specific interfaces are " +"better than one general-purpose interface.\"" +msgstr "" + +#: src/additional_resources/design-principles.md:22 +msgid "" +"[Dependency Inversion Principle (DIP)](https://en.wikipedia.org/wiki/" +"Dependency_inversion_principle): One should \"depend upon abstractions, \\" +"[not\\] concretions.\"" +msgstr "" + +#: src/additional_resources/design-principles.md:25 +msgid "" +"[CRP (Composite Reuse Principle) or Composition over inheritance](https://" +"en.wikipedia.org/wiki/Composition_over_inheritance)" +msgstr "" + +#: src/additional_resources/design-principles.md:27 +msgid "" +"“a the principle that classes should favor polymorphic behavior and code " +"reuse by their composition (by containing instances of other classes that " +"implement the desired functionality) over inheritance from a base or parent " +"class” - Knoernschild, Kirk (2002). Java Design - Objects, UML, and Process" +msgstr "" + +#: src/additional_resources/design-principles.md:32 +msgid "" +"[DRY (Don’t Repeat Yourself)](https://en.wikipedia.org/wiki/" +"Don%27t_repeat_yourself)" +msgstr "" + +#: src/additional_resources/design-principles.md:34 +msgid "" +"\"Every piece of knowledge must have a single, unambiguous, authoritative " +"representation within a system\"" +msgstr "" + +#: src/additional_resources/design-principles.md:37 +msgid "[KISS principle](https://en.wikipedia.org/wiki/KISS_principle)" +msgstr "" + +#: src/additional_resources/design-principles.md:39 +msgid "" +"most systems work best if they are kept simple rather than made complicated; " +"therefore, simplicity should be a key goal in design, and unnecessary " +"complexity should be avoided" +msgstr "" + +#: src/additional_resources/design-principles.md:43 +msgid "[Law of Demeter (LoD)](https://en.wikipedia.org/wiki/Law_of_Demeter)" +msgstr "" + +#: src/additional_resources/design-principles.md:45 +msgid "" +"a given object should assume as little as possible about the structure or " +"properties of anything else (including its subcomponents), in accordance " +"with the principle of \"information hiding\"" +msgstr "" + +#: src/additional_resources/design-principles.md:49 +msgid "" +"[Design by contract (DbC)](https://en.wikipedia.org/wiki/Design_by_contract)" +msgstr "" + +#: src/additional_resources/design-principles.md:51 +msgid "" +"software designers should define formal, precise and verifiable interface " +"specifications for software components, which extend the ordinary definition " +"of abstract data types with preconditions, postconditions and invariants" +msgstr "" + +#: src/additional_resources/design-principles.md:55 +msgid "" +"[Encapsulation](https://en.wikipedia.org/wiki/" +"Encapsulation_(computer_programming))" +msgstr "" + +#: src/additional_resources/design-principles.md:57 +msgid "" +"bundling of data with the methods that operate on that data, or the " +"restricting of direct access to some of an object's components. " +"Encapsulation is used to hide the values or state of a structured data " +"object inside a class, preventing unauthorized parties' direct access to " +"them." +msgstr "" + +#: src/additional_resources/design-principles.md:62 +msgid "" +"[Command-Query-Separation (CQS)](https://en.wikipedia.org/wiki/" +"Command%E2%80%93query_separation)" +msgstr "" + +#: src/additional_resources/design-principles.md:64 +msgid "" +"“Functions should not produce abstract side effects...only commands " +"(procedures) will be permitted to produce side effects.” - Bertrand Meyer: " +"Object-Oriented Software Construction" +msgstr "" + +#: src/additional_resources/design-principles.md:68 +msgid "" +"[Principle of least astonishment (POLA)](https://en.wikipedia.org/wiki/" +"Principle_of_least_astonishment)" +msgstr "" + +#: src/additional_resources/design-principles.md:70 +msgid "" +"a component of a system should behave in a way that most users will expect " +"it to behave. The behavior should not astonish or surprise users" +msgstr "" + +#: src/additional_resources/design-principles.md:73 +msgid "Linguistic-Modular-Units" +msgstr "" + +#: src/additional_resources/design-principles.md:75 +msgid "" +"“Modules must correspond to syntactic units in the language used.” - " +"Bertrand Meyer: Object-Oriented Software Construction" +msgstr "" + +#: src/additional_resources/design-principles.md:78 +msgid "Self-Documentation" +msgstr "" + +#: src/additional_resources/design-principles.md:80 +msgid "" +"“The designer of a module should strive to make all information about the " +"module part of the module itself.” - Bertrand Meyer: Object-Oriented " +"Software Construction" +msgstr "" + +#: src/additional_resources/design-principles.md:84 +msgid "Uniform-Access" +msgstr "" + +#: src/additional_resources/design-principles.md:86 +msgid "" +"“All services offered by a module should be available through a uniform " +"notation, which does not betray whether they are implemented through storage " +"or through computation.” - Bertrand Meyer: Object-Oriented Software " +"Construction" +msgstr "" + +#: src/additional_resources/design-principles.md:90 +msgid "Single-Choice" +msgstr "" + +#: src/additional_resources/design-principles.md:92 +msgid "" +"“Whenever a software system must support a set of alternatives, one and only " +"one module in the system should know their exhaustive list.” - Bertrand " +"Meyer: Object-Oriented Software Construction" +msgstr "" + +#: src/additional_resources/design-principles.md:96 +msgid "Persistence-Closure" +msgstr "" + +#: src/additional_resources/design-principles.md:98 +msgid "" +"“Whenever a storage mechanism stores an object, it must store with it the " +"dependents of that object. Whenever a retrieval mechanism retrieves a " +"previously stored object, it must also retrieve any dependent of that object " +"that has not yet been retrieved.” - Bertrand Meyer: Object-Oriented Software " +"Construction" +msgstr "" From 2af4b234874a3ab7203d71f5921cff54459168f0 Mon Sep 17 00:00:00 2001 From: Nuga Date: Fri, 7 Aug 2026 12:05:18 +0200 Subject: [PATCH 2/3] Introduction and idioms definition --- po/fr.po | 75 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/po/fr.po b/po/fr.po index 3babf5fc..07519059 100644 --- a/po/fr.po +++ b/po/fr.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Rust Design Patterns\n" "POT-Creation-Date: 2025-05-17T14:07:35+09:00\n" -"PO-Revision-Date: 2026-08-06 10:44+0200\n" +"PO-Revision-Date: 2026-08-07 12:03+0200\n" "Last-Translator: Rémi \n" "Language-Team: French \n" "Language: fr\n" @@ -26,7 +26,7 @@ msgstr "Traductions" #: src/SUMMARY.md:5 src/idioms/index.md:1 msgid "Idioms" -msgstr "Bonnes pratiques" +msgstr "Idiomes" #: src/SUMMARY.md:6 src/idioms/coercion-arguments.md:1 msgid "Use borrowed types for arguments" @@ -211,7 +211,7 @@ msgstr "Principes de conception" #: src/intro.md:3 msgid "Participation" -msgstr "" +msgstr "Participation" #: src/intro.md:5 msgid "" @@ -219,20 +219,25 @@ msgid "" "[contribution guidelines](https://github.com/rust-unofficial/patterns/blob/" "master/CONTRIBUTING.md)." msgstr "" +"Si vous souhaitez contribuer à la rédaction de ce livre, consultez les " +"[règles de contribution](https://github.com/rust-unofficial/patterns/blob/" +"master/CONTRIBUTING.md)." #: src/intro.md:8 msgid "News" -msgstr "" +msgstr "Nouveautés" #: src/intro.md:10 msgid "" "**2024-03-17**: You can now download the book in PDF format from [this link]" "(https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf)." msgstr "" +"**2024-03-17**: Le livre est désormais disponible en PDF via [ce lien]" +"(https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf)." #: src/intro.md:13 msgid "Design patterns" -msgstr "" +msgstr "Patrons de conception" #: src/intro.md:15 msgid "" @@ -242,6 +247,12 @@ msgid "" "abstract from these particularities to find the common practices that are " "generically applicable." msgstr "" +"Dans le monde du développement logiciel, malgré la diversité des " +"environnements et des pratiques, on rencontre souvent les même types de " +"problèmes. Bien qu'il soit toujours important de tenir compte des détails " +"d'implémentation, il est possible de s'affranchir de ces détails en se " +"reposant sur des pratiques standard applicables à un grand nombre de " +"situations." #: src/intro.md:20 msgid "" @@ -251,6 +262,12 @@ msgid "" "language for developers, making them an excellent tool for effective " "communication when problem-solving in teams." msgstr "" +"Les patrons de conception sont un ensemble de solutions testées et " +"approuvées, applicables à certains des problèmes récurrents qu'on rencontre " +"dans l'ingénierie logicielle. Ils permettent de créer des logiciels plus " +"modulaires, facilement maintenables et extensibles. De plus, ces patrons " +"forment un langage commun permettant une communication efficace au sein des " +"équipes de développeurs." #: src/intro.md:26 msgid "" @@ -258,10 +275,14 @@ msgid "" "crucial to focus on why you choose a particular pattern rather than just on " "how to implement it.[^1]" msgstr "" +"Mais rappelez-vous que chaque patron de conception possède ses propres " +"avantages et inconvénients. Il est crucial de déterminer la raison qui " +"motive le choix d'un patron plutôt que de se concentrer uniquement sur son " +"implémentation.[^1]" #: src/intro.md:30 src/patterns/index.md:14 msgid "Design patterns in Rust" -msgstr "" +msgstr "Les patrons de conception en Rust" #: src/intro.md:32 msgid "" @@ -272,6 +293,13 @@ msgid "" "decided to write this book. We hope you enjoy reading it! The book is " "divided in three main chapters:" msgstr "" +"Rust n'est pas à proprement parler un langage orienté objet. La combinaison " +"de ses caractéristiques telles que les éléments de programmation " +"fonctionnelle, le système de typage fort et le vérificateur d'emprunt, le " +"rendent unique. Pour cette raison, les patrons de conception en Rust varient " +"par rapport aux langages de programmation orientés objet traditionnels. " +"C'est pour cela que nous avons décidé d'écrire ce livre. Nous espérons qu'il " +"vous plaira ! Le livre est divisé en trois chapitres :" #: src/intro.md:39 msgid "" @@ -279,12 +307,17 @@ msgid "" "social norms of the community. You should break them only if you have a good " "reason for it." msgstr "" +"[Idiomes](./idioms/index.md): recommandations à suivre lors du " +"développement. Ce sont les normes sociales de la communauté. Il vaut mieux " +"les respecter à moins d'avoir une bonne raison de faire autrement." #: src/intro.md:42 msgid "" "[Design patterns](./patterns/index.md): methods to solve common problems " "when coding." msgstr "" +"[Patrons de conception](./patterns/index.md): méthodes pour résoudre des " +"problèmes classiques lors du développement." #: src/intro.md:44 msgid "" @@ -292,6 +325,10 @@ msgid "" "when coding. However, while design patterns give us benefits, anti-patterns " "create more problems." msgstr "" +"[Anti-patrons](./anti_patterns/index.md): méthodes pour résoudre des " +"problèmes classiques lors du développement. Mais là où les patrons de " +"conception nous simplifient la tâche, les anti-patrons créent plus de " +"problèmes." #: src/intro.md:48 msgid "" @@ -306,20 +343,26 @@ msgid "" "repository](https://github.com/google/mdbook-i18n-helpers#creating-and-" "updating-translations)" msgstr "" +"Nous utilisons [mdbook-i18n-helper](https://github.com/google/mdbook-i18n-" +"helpers) pour les traductions. Si vous souhaitez _ajouter_ ou _modifier_ une " +"traduction, référez-vous à [leur dépôt GitHub](https://github.com/google/" +"mdbook-i18n-helpers#creating-and-updating-translations)." #: src/translations.md:8 msgid "External translations" -msgstr "" +msgstr "Traductions externes" #: src/translations.md:10 msgid "[简体中文](https://fomalhauthmj.github.io/patterns/)" -msgstr "" +msgstr "[简体中文](https://fomalhauthmj.github.io/patterns/)" #: src/translations.md:12 msgid "" "If you want to add a translation, please open an issue in the [main " "repository](https://github.com/rust-unofficial/patterns)." msgstr "" +"Si vous souhaitez ajouter une traduction, veuillez ouvrir une _issue_ dans " +"le [dépôt principal](https://github.com/rust-unofficial/patterns)." #: src/idioms/index.md:3 msgid "" @@ -328,6 +371,10 @@ msgid "" "idiomatic code allows other developers to understand better what is " "happening." msgstr "" +"Les [idiomes](https://fr.wikipedia.org/wiki/Idiome_de_programmation) sont " +"des pratiques répandues, des règles et des patterns largement approuvés par " +"une communauté. Suivre ces bonnes pratiques permet d'écrire du code " +"compréhensible facilement par les autres développeurs." #: src/idioms/index.md:7 msgid "" @@ -336,6 +383,10 @@ msgid "" "developer. So, since we have this abstraction layer, why not make it more " "readable?" msgstr "" +"Après tout, l'ordinateur ne se préoccupe que du code machine généré par le " +"compilateur. Le code source, lui, bénéficie avant tout aux développeurs. " +"Puisque ce niveau d'abstraction nous est offert, pourquoi ne pas le rendre " +"le plus lisible possible ?" #: src/idioms/index.md:11 msgid "" @@ -344,10 +395,16 @@ msgid "" "are kept simple rather than made complicated; therefore, simplicity should " "be a key goal in design, and unnecessary complexity should be avoided\"." msgstr "" +"Gardez en tête le [principe KISS](https://fr.wikipedia.org/wiki/" +"Principe_KISS): \"Keep It Simple, Stupid\" (Ne complique pas les choses, " +"idiot !). Il stipule que \"la plupart des systèmes fonctionnent mieux s'ils " +"restent simples plutôt que d'être fait de manière alambiquée. La simplicité " +"devrait donc être un objectif clé de la conception et toute complexité " +"superflue devrait être évitée\"." #: src/idioms/index.md:16 msgid "Code is there for humans, not computers, to understand." -msgstr "" +msgstr "Le code est fait pour être lu par des humains, pas par des machines." #: src/idioms/coercion-arguments.md:3 src/idioms/concat-format.md:3 #: src/idioms/ctor.md:3 src/idioms/default.md:3 src/idioms/deref.md:3 From 0f3efb766c38c6ccbbac48b50c1f1f167448bf72 Mon Sep 17 00:00:00 2001 From: Nuga Date: Sun, 9 Aug 2026 10:45:02 +0200 Subject: [PATCH 3/3] Idioms Updated messages.pot Idioms 2.1 to 2.9 Idioms --- po/fr.mo | Bin 0 -> 79850 bytes po/fr.po | 1112 +++++++++++++++++++++++++++++++++++++++-------- po/messages.pot | 223 +++++++--- 3 files changed, 1100 insertions(+), 235 deletions(-) create mode 100644 po/fr.mo diff --git a/po/fr.mo b/po/fr.mo new file mode 100644 index 0000000000000000000000000000000000000000..39bdeca21ec15bdfa438f6660c5bb5cce1dd8246 GIT binary patch literal 79850 zcmc${37lM6S@(YfC=fx$L3YHO45Yh5syfNcu=LC@B%NfYXR?v*FpOd7s;;`-U6bmn zrk3vXjDzeTZX>wkf(SALGOr6Fh^QDBd{snVTu@QA5m6C&6@gdK|M&Mi=iGa%(_!)D z|Nr+VH&4~Ad(S=RInVw)=iI-!^nO2>@OSmLBzY|G3lB_^*Yo+WAF8uSvij&Gxi9d! z0S5W>Ol0yVz-rb%)w@WH@6z+*uECAab40`S$qIpBW+cLHa3B*|sKHK6+W zV?d4LT|ge0ydU^V;J*NcuNQIC8t}Eib>O48`5f^3fogv{$k6!}puXP=yb^f*6O!Zx z;PZf0;O_&U4E!AMe*yRM@Sg+TZ_NAq3&7X${e8fv0@ufr%+iD0w1wENoIh1fe!}W2BhoB%YplW zZw5{RKLq?b;3ZFFOxt)a5L6`dAX|8NAyDK058yk1{YsMD#C4MlI^+AxXhi+^BvAeR zFCa}M-%Mw>1D_7O7kDFZA8;T4y$9F;GUQ}Go!LcuXMpPG3orM1z7zN=zP}Ur4Zvqy z;dFir@HE$FK+(-R81zf{{e4eLl4;WmgpXGMg}*lguK~Uf_$J^bQ{KN{1L`^N2JQgbcVa&H|4x&Ia%ioPQ$^7ruWBD15yisP;bs zTm^m-sOz5dv?O^La1BTolJ5p;e7^^L0Pv5)?|%W*{r?Pn4Dj;-J`ASQ`F+3xz^j4x z13nM<&%hS}g~#60ljNhoHv&Hd{9Z0jf!%}N&pUyl=hp(?1$;a3k-*!Tti!+`0Dcho zm%yiNOOm%8ayj*Bew5s~&k<;Y^A7}m5tv=)blrfsU(fGv2Hp*vy&*~N0Dcj8lIw22 z(dqRMkHQ0dfB7-T@7s_2JpB&vIh=nV@Uz^v?<8{uoOlMb2K+DnQ$L>pF+Cc1E08WG zF9E(0`1`OTP_SL%S~p3jhCh#_|4NK+WI%p6&elAm9VJ?oyz}|JYkx-uy05^wED# zlKc(uCBR1koAdAh*FO&^x_M>I&%Y+XUj>Tp-Vb~z@MA#T_c@^G=+e65ZyY#IJ68Zf zL2}E2>#Ls!GNj~>fcFA-HJ~xzgPKY50pMQ)@8rI>X3!(>x}_xf4$i-DIZ6Hmc%N3# zC%~WO`v-wP1$^~csc|PziU<#aIa)g%~fKLQI2l#EY z_X^+(fcFm2MVwz+gI9s~U3dAm1f1mioxokd-vmC7>pu=W#`ndIB!L8zw*YSf-j~k2 ziQmrvFXQ|DzdcE6z$XHq1pIEG@Nym~{52r@j{!dlr2!43ZKLRDUzW5>^=k^yvlYD<7@V>ww2ByGQ1AiL$Yrrdj&v}XS z$*X|x;rqS77VW*|r9KajdwG)lJLh)+cLTo#r0eaPQD=KGHC zWcHkTN{#W0VB)<)O>GvkdA>fVQ2hRiV1YQGt+MVbF;I{)|t>k?HPJBPt@csF~ zbHHzUWs#R&hYzt0{nB}LC$|De821`T%PX% zUds6n@ausu06rG@a^NoD>w$XC9|F~{KMn8$0e&#R4+nT}fS&*|WyvRjuL0ivlh7^W zdn`ozCw!mf1>z6y3iB_zl3n0;-*l z0}lW%`5)eoQ^2p|`ws$N4BlT2RD0dD+|HVb1>m z@YjGJ0&2WJ@vBbfzYP3#u74*`dT@%1exBd&0@=3!Z~k?c-@gLf$M*xj;dI{zuJZlG zz{9}L04IT0{iegSzz6XC)xaMDz7F^>;8pK(dG-w8llcBp;A!AHfea~m=x@2c{QUs` z95}`Kdx3N*Nzc2!`5WN3@cmzbHv_-vw;f++fsf?-OMsfEp9Jc;Zw&A^f#16gngZ_N zeD=GJkCy?zk?%hR+zz}4_%pz_12wK&evfAZzXvFJbr10V!0qq$ab61iX1+fLsORnl z?gU;P;5_ibe19SEIPgxO=;UvKkETEO0-w(J;u?3d_VA)KAvCxE2p#bz&7XK3zYqL%?IImVCQdK zp7j6L`SA~dnxBsXo4_vsKMkyZ2>Rms*$+eSz?Xa^Nrs&N?T<1J;MB*Q&R!2Z#`k{& zHtvIOcQ5*t>wn_oE{{I=_uz)#ANC2C53d0J4!@88gU{Ta4+y6Q1jOZ-VgYF!0)Hs9{|3L@4NoZ`RpEGi|-!-Cj5TGXXq>N#(#JEc*bYJ z9p8_A4trF;{~wnh|Mnk@hwpcM!N>cOFFN1c3A~%8j{hh25P16>a68}E5hf1>z7TjR z@P~je1>OyO0C4YpwwWA#D)17%p9H3~Uk5gUFTC%zmLfUJd^Y9!bxZYA9=|(iyyoM_$hw>d*D9K|HY--l4am_jPs`e`#?l* z@^e6qyY|i8$MqivzK-uV;Pf8m`=@}QG`aGT+syvk|EO(Ao%4@?d7r`gjmKT;V@c*Cr z$Asy(`4dl_;gIaQp5u2p-pC=`KuTuA^U-{m=K>Kk`QHoqB$*=l@EDG#a)`H1aln>F zHy`A){@%uch_gRf&HmoS|3Aecy!|jojYEIm&9Q?+d>;QGyW|h}0-Ghj1H1~TzXt+E z*PrKrMC=dJGTvU~+cJmvZPtEqS+}3h?+o8XljXl}<%{SB^TO!;XTpz<1|l-d7SQ~E zh~qfN>p8w5Jog9qyvkAMfGth0^3m)+$j|=%h5vt)$MM%3FVYwOc5wY8fZ~~#+Zq4wVWFK{`1~fq8-+vMKSPrR&9|V4udH}?$7661wI0JGf;nj%yEx>a{KH7;q#|~kLUO{j{9)^2Y|2PcnAj~*>vn5 z^7&I7zs(^XsJ~Zo{0+x9aNNM5zu$6@AfoNB!T;aRQRR3E#}_zS9Ptm;m0Zo2T^t_? zCowbZ4>Mup@4xu=jU2zhagJjz2P(~U{%$^(|4>c#_qY6yIFsxL!Sz|Y-A!-r)K{`QcJO^>@^>ol$$@Zj!<*b*b>-9co7JIF%(`;{~4exZ?=+zfewckwhZq4yqXNk5N^-iZd zNY{I^sU~kbUWPMtPko7^}e3W2p7|9(%S{6F1uE}%FeY0fZN;MrB@XXb=R|YU*o;~4oAdTI+l#pIWmqGN0(zb zmh9fWfA9V)Dtj-l?0fR=-Ban!-C;_n(@u9iZFbi??QXrP@uz1Ny4|yBtCOBQbR=Eu z_EzeHTgI0MgVp}j#J5683hG+dI_o6W2_m7Y1>XM{YZyOIui_11tx7B3e zE3577TsqiT&C-SLu+!|{GF~m73>^&{gJG}Up0ryl^uFTPRacr5JpTGtXE3#UcRI&7 z>&>-#XHZ|t((Yo~Qp+n@XCOlC_R?n7Ypv;X?NGK@AGQZI&C6i9K1esZ!=85`qHh5z z>O&RlMm_cNJ+ayPKx9o5z3jQeR!*8K60NZ9l8` z8q3!dZQHCIKQVV$XsNAaD^pXjRlDBEY{W3+M%r(!wA%IFo^)Y2Nb9iKdY=JnUizz9 zqqVrf$U%%zz1?bET&uT-@Dc=4O%HTZjhj;pRTm0}{>pO~nLn2vV`nYukQ5N4r{6|r)snP%tc7h*!>Yg1*N&F2`}87!A( zNw>fW*~;o*Bdzg(n(>%XQ@2+Qr)>V6`@%1}YE3kwsqLhvpju60Q`FGwhhC&D8!&vX zU;Ev(1+`g+5fS}vM|0!-WLl9Etw#Cb!j&)to2K>N(oiJYH#x;42Wfvi>|TCJwLC-rHXo*=dADPpBd_oEbEUv4#)ghGp1XNU=b2yKVDw<4+>_3vOT(<+zt%3EOb!|B}hGqdURi9?6Iz0l^&T*~Rw*B!liPx{Qmrw*Q&J-jD9 zaQqNg9-lifb9^>Ekj|byICu1Ldhqmhp-}{nkwQSS(cEoWj|oJ#*wAL8IACN*$Vf(_ z(j(ojH=}Eitpg+lqO4;Kl-91TrQOwx2SAV3)Nu*scDTq-omjo#@yELzfAWd-4kWqU zT19cTvpy0Zj09#Dftjciqt()djnr7z*?k>~H`Qk74(Kt8lo)az?=q##O+8&1ny8^y zi|A3NY)?Au@Hhw}~)-VnX(p)o@_46l1 zbNlrTzj?KbIs-4Q3;G}v!KDp!ztU~CP}kmRml$ccfmJj5;O^>%28_Xlc39XLKqW{F zF%%M?yBWs9aFL01lB}m=&)z$>dGNX~l`ddxSWla98XjSjj)B$fWf%!*97Zm+d8}}? zxos2X*6sieDizo`3jsm2pqhIyV(23(tlQfd85+cgP+;chR_I&11wFu)qT8CQx+Rl> z=!@lgCx0~Z#inW4gPxJM#WP2T27Po_O)w*b!2Y0))DoAYgpH2EAa_{D<`_kZ|LMcL z>_8CPhNZD=moe**!uISa&C}XKy=O{U*Jc5?YN|Y##yk^fJ!o|hyYSzj)i$<@Pc}O4 zj0MUBZzxTE^x$ zVkgXl>szECWG9KFK1EuC8^uogV+t5#XHTIPt$)%CS!cL{4C-Mw57Kd0SHfZWUPi~{ zLuU++!Pa(XwZQ5&CXDN|{ZylOd8gT4?8?RwGYr;6iXBGnwu$_bDQlfxtJPWnKi(X+k+a1BX13H)^$Ftnr2HETR8_0A9!Z{*6eoedTZ zo~J=G%(nb>d~CsKf|{*9zCmNz36MMc zP;xuJzrOi)iHEK4twARHjB{4HYgyBJqI3K0TmyMrI(fOBT)@+W2mM-H6BLImlzzcU zcuDOzAtoso>+QZP+hPVb889-2<2|lB`_>t>algBgp~#pcyND(hi)W44&UVKNN>#2) zz@pJAcx)l&yblGNA^qg2V8pLt4%UZ*ZpFNtEIky+sZhGu#Yi0#21bGj5rm#SZ?)bV z;O`+IT7s?HT$^k$Ao$b-sjH~IOJ_IWtR)SUrkmbPS<2{(fyfyKtp^9%Z5`}tyTvXF zic8wxNM>4^s?!~xFylEIoVe~6-hx1_%lsf%0P8SqP+AW&QWCahEuZ>V{N8XtX3_Y1f^CF&zFgPY6aJOK_`i0$MOx)=Y(PXui{!%T9m7>{- z3|h0&(#{ad4=N;Yz2aw#_%Os;_yPI!&{@SDw!GFgq|~#>2FC>|Rr}K2r5n~wAj6=t z>dcy!GsRe%(a<#`iazEVN~09|C(~1AygCiIk;rr0z32yA&q@83&vM^(-FsPj_*`9< zvcB1wTCHYK(yC7Y#eIOOsUQy}qI4s2KI;wUv*+#@-;1kNwFl!Y`mbul`t~(=u$<5< z_FwqeEB0UHxmU*k%KG|xwbfbdKDUb9Il0J~Rv)7&*u z%LH9;A!^3idUh>F9VEldIYNR3A4Au>7qKh$68827n={_(G}=StWKf4~lU(KsiS&aw zEH&mKlB{1%k10YUvD|I;74}J2T1(4==-2ZUm_t3Xz!4lL4P@QL@`J5|^>e``hMRsB zyoQj)3ZVh{_~S$e!l~8(Swa7d-^yNx;gUy7E+7}}0<(Y=MhG`7wt94Y0jvG&RC1uv z$Z!n7k{f0H- zF$wh^TaYv6@HD^zs2~F8w#Z5y`X$aI=}*TIuLzGNg0lFvpby8>L?vxNM8sWY+=z_N*a_@2$>LDgvbb&;cZkgi$MhcM$7{+ zgVCh@&@oIH~$7u)6QhgX778i$%ACEm)3*CkHbqAoJ1gt3LUuRaBj`4NN8D8Z66g zsWIgQb6{p@0skeKo)}Gl{!rfSDpGXl|@9ReKcn-i)shE=W5TcD4&tX z38&~2j6h*kUoLN-8QVv*cNE7Fq?UUWW)o@#QCe3D!3*x4?WVa58Y%mtp3 zVc}+-wN|g&QA|rB)wM2DSxry$>|yc-q&mQg{2`_@ig)mWjGKH+r`xGmVA-N=TeQ2P-a`GS=Z;jKl1$6N)kO5cR-bH*rq{_L zZ7gSvvvBLQRB|x8{R`@$2vG?OcnISi(nsx$2^7Au43AK>s-n4Mu1&_Qg6{^Fpj{b+ zqP`9qOp~4han`;m`ia z&zk?f{T$pS{k+0Mng(T;h^S;gDpXRmYXi(Rv=nqRI~PpQQ$+Eynh`SzyETQ#WW-56 z_BSw<&Pf-8Vlp)7S!)T@6lj*LY-Q^j$ci#4GQ|kcsB0ZXRv{3zxyXe&xT3`U7;KCBr2KD5CT-|;S61&;hJA;_W2Slyvm6|msyk1Vn`LPqC7;@ znx^b_tXKSmd|e&(Y!0IWYqTMCH>tRQT&OsO>2LPBt7^VQdZDR&6dDb+WO+KfP^9W~ zPZ&T|1NHIe_nRXlCu!8gH9QkjCbHS--z%3Blz_;FMQW6D@CfErn$O5RR z(_j+|ug^(qyqd%?&lAXcB$GZXbbr#+Zl@o=hh+W*-wodq z`H|lw_RJxVtz5u0xxwm`jA5#EBq3FO@bYjGNW2 zkaYB--LkNG*VM>Y5N+sTK2g~@n9gi%d3n7|R<@Z@@Mau?9%`(vey=FCtc?0lQ8!7h zX7n?lSUR9yGOH`%!0cRuVif6Li#F-%jKm2Z2f9^l4H1!se77{h=qe1}Y%VC5u=xru zVnB1=C4P|t$VM(E4k+nMo{D5&O zx0g9R(rq{S&yqCJ5l1vEA~v`#IEz>BBHUtb&3H(vPS946f>4|^x(tNekY`Ri`OON| zG|7=Q+6>UJiTW2w3aTU{Qkv@dgOC$uvW zj2{hLx{pryeU_WfrM8BvaEQ|QIJ=7y@C{5{72m+Oc>uAQHSp1Veg@qsLz8(4Bm)9L zGjyfL^gtSDVx!h(O(~8z=E?$}G4dr0f|f>HK(^!i_wKuLq8Ru^;%9sJ?b}Bf?ecwB zJT;G>!5bJ6y?S$SHnY&3nws3pzssqtkua*P^(%a;v^td@JX(o^>Koc7B;BvKM$#Lq z=_zX{otc@jF4@eM6X7%r99HHSc8@-5Gs z_sq=eMM{j)ahP)=ITFe=pcxTb11>Ahoa}X%$nj!DFLAmjAtj11Y3+F<`61G!7z>iZ zGBiwm6vmu}d8QWhT+QpsR5^zDQf-%t!%E%_(1G_5S5+BO{;ea>?GvRl*- z=SjA` zhk+_R=QSNDQ#nx8B#(~-MS<3jkuNMb#XN{s4B#1KDve50%?~0#E7P)^U#RO?!HKm% zo`tz2a_o_A3vo{fmJ!~w=R^xnPPOQjHbL2fvh;N4BhP=82Z}JP$=BA?8)y)$d0B|A z6w;Muf-+=8o3*k~ryLI-5l%0SuFNiOZ^@35D`KAeh)6-7xl}>8dZU=gku_|NYr6si z$(-PF{$W8$(M6-#Beq6lB5LuEiB$_}a3V4wt{7nyPZbBfDv4;pr6|;78jk3T&A0P- zwJYjUs5{v3raw%}2vr{Nj*n#uL#MbGkFLIIy^AeW6H|Y5py3sNAxCEr?O4hHNpb7>vQx;`g zbbc;%0V1?HP#jL}pm&S@!54JHkiKAsqD<;?ArL0xu%j3fD94K^H6q?Luh@tdL#PLf zsWm8*-(=1)tL9cX`Wc#GgRxlznUF<@cxHG zcLh-+V=Wj3A$w=omCa}+z09pe$5C=t5#pviB#h{95x|s&l~u8d?PliWxV}?^3(XFf zDi}+h3|SWGIJ4X(^yf~$LcPHy4ADxFd!AEqOOgDiLZnCox?*;(-Nuz-&~hc32nBlg zrfA6JCa6(Axn33tR$tIH5ItV5YErn+f$tU~uj1{%9zhSFB#p*wmP!+CVGo;qwKwgvDXm~tSUwFtFVhm1o02N^ie7%gVhW9E)rb~n^BvDAMl`(9|zY-4!;|kpcX0^Dg#)H6+ zbrmE(;TlE0P4J1%_qe0yn!x!V=>};<0bZ7xvPi8Pq5I&;zWNl)+58i(v_Oh4;; z9`Y3dB#5K^0N^dYe#U~J(TtBGy&#KH*9+-7kree&i zx^=>3Fj0|s^FGoFB3c?tR*-3zRm;UnmD<2GEXxV2W?k+pjtL(L-3VcDHo+_Y*XJH} zN@j>8Xncg9EQ7K+u-SUB$edXSxFiU8D>5;6l$2!wYD6{F2L@+6mI~Hlj>P(96-7*F?zx*daz9d0irN!P)$Rpzdf%Nf zj1$d_?#N?OmrRj5KkmTfD49M!^kR;w<2WZZgfE1maCNVoO8g$i6vsX6drDad)&MPQ zPCyUqT#pX61=LKkHM$Iak|J79VPOX;bVo|aAS=G93Ca->ECREF{9#)>XuLF}U~7f@ zWcn<~O@ucp!P|faK#H0vEK?{!I!Gc;OU$flA5mnIUINRa43bT%ukeZpD9U2Av^C2E_At>unPj3-116(hh#J{mTWOs#m}fu{W}Ph{?Dxl`5TsLXdFYCKVz)r>5n z0cOPJ>%a=H$Bi%%G}_`U5sP(H*sOvKR1q>}*wBifU5G~a-5%-2w$^ltfoql%MLt-B zV$;p41_045rMA$oc)1WDQc>+tE*X*G)VgI8MhDOyHl&GH(+iANWil&dxV4PSms1d1 z-GLHDBZ$t#Zs4uGMTkUR7P7KQwo}$JjSX=^l*V+ITea#&Fph{DtRf~YA*OKoykdX7C9=9}_yA z2sAAxc}XBgRh$!1HBntO=aU1A;!24Y%TdF^(%&jvE*WVnEJH{!cp@R>7$U&Xt_YQf zGuB21r^|RUA6kA7^3{A`6I$}w;M$l+@Un+s7X<{4XVs-De6C))yq%iDRPWVS=Zp27 zU)FQVd*1!h@%{^1o*>R}ysHIYkfLdha-V|%Qx=551SuPI$GmdFtYyQFgs!MTzxKIVU|)0rGnOA>Ky2w$|za&QFy%ry7m~Rq?MtOEc2oh3-3@u z?Zg;kflAett`_OlS8PmZESD!N`T;RWq0y#Voi&-|CUKbn<)PGcSYtI!N@4>vI#Y^a zyfVPKC9o={;$U)sV_0Q0yv6YNbqs@1cUL=d8x!8h$KA?2EjzR6hPyG}#Kup?eB{quy<0 zx%{uRW+@CqDVPY=oJPsfl|(tMt`gF88EQ&2cqf>RiV6jd1-XbMJ5(jIbU<}%aR^-H zNZD!>2kSkCNwUsufEwSu#ySdd^MLx8Z5VTO*{6S(-xjVMnT@ESjI8Ny?1g5SaG`m3 z$?L zBIR(p2-KVddr;~3ybCVa?Ha@_?zpUn5NE9l6QX34elW44!D`;2r=)8#JV1jJy!l4f zTuWJI4MwykReYw#qWh^SxfxSa68T>?>8eX77dus59JB^jr3MwJBt!|lr+eZ`L3PIa zjG`AahOAsE1ZPHMupm9@g2#(#?8`GkzNIF5&>4B3o{p5rX%N3i)5ug{JXa#LV9cC)$Ve^=^fqdK~ z5?X3O;g-6m{G8Y^ILp?O1(#5;d1E8bvcb#PM8u#*w6Kwfgaj$bR9}oeXhD>l(^5fS z##$;>Gzw?Hoyx3*$_|C)Y!qmqQ5wt1i9Bs5q&fRaDr(lwDn=vwMlOrTaLh)E@`#wi zCWU25ji~>EoQ3lG8MZZ)XkjCIg*b*Lt@yI;DIDliF%W*ki-p)c^q0$9>yg(=`J8xx zDKv%EARUI@k@mg0DlW3uuoHXyM1%l9nd?VcT zOfBog0w64ekLe{*{!3i$V84V?E&D~im^E|1&z{PvmQbZ2QeqlcEz>zfU}GaaLN8P+ zq6#1@-{zM*$t+K=-fS&V>v8J9%uIS63(cE+Mt-j>XnG;KGdIr6&cX(v`lc`qvrcur zb+$#>SF7$Ta`-l>tLO8pC#KS!=KRi3l5hCd<`%=%RudDHb5uaIsB|)Z-f6K0k3=H< zl&@VN0T5)9tKGAtN)!mR%u>l`wrXxO9aL?0TgabB_Q zTvN^&QqmF-HVjZI?Ue6?AeOZ{IRt^OvFL7cD&!K)J%~QFOTUpk@Rv;jL*^)ASq~f1 zFEk9IqbwoPX|-D=0cAc!WK8Kg=M(0TPsHk6&v2f&wig^3!AdV6PR>B%o42Vb=;)#@ zhVna;jpe;pY9k-7#HoZ5R7-Xgtrqns6JY}r_{f)L>iHg|pV~CaAlZ$`M^}~9Y^unt z`MM&-x6G0?GL0pVp2S4LYu5oQ4YYtrDNf29ht=x^n)2QdmMU@sCUl`J@MV!K#Y~GQ z#tLVhEyrAaJQfclLOG~F$H9a%*)wVmm*PWt!p%)ArQd?BQZh4*e@spnx&m*e*Cp_T zoQgJ$X)RMJPy~z+cvO7jEq?@XA_GuVG2x+v~!YIj0UetW(Sq*h9&$iX*^*hukMe9ae+?rk&bw9 zk@>7>z}A>3Y=;2^uS*)K#jqh)%#B(>@-ksqi@Ic;Tf0h$A@3P&YhY_rkUiS}N;!8~ zIp$b->}*A0G*HP>nM z11F(qaWg|bhAFoj2e^I4EXz%oN2z`_sRQ6YEwGaQR+z}dU`g95^5Kh^tZ%`XT*lsK zCYDKlgjxv_hII%f?;0bu?OJ4Wqc!3p4BLk%5@AR(DTAQ0KC41#;7JOZQasilt@0Ih zHpC>1h5Fe*%YiY)^j3z&JtgsK16Fs6!mY1BK5CPz(A>pCFjL7a;kFnNQ$>%qKsdIc z3QzfBO7Ka9jAOkh7d)7-6;)<;*!D}c1L^H%B~ArbSeBgL97Ic!F~GwD(OTyb?cKA4%!S+h7F|i0s6kM0mN1YC z5|UXfS25ZgT^{DEDxKy=-7c#OcKH#*d2W8PD!*$hPRvJeaS376cDeH>v@zfd<9x=~ zT&U@@%yl$oqqw2J*3IZ<6n6AhOCv{Afz&R3V_v~!MFKv8FB|J>PMUvZF`BAbfK9Jy z9c;KRt$IV031B#~#3ZgEaSG0>*XaT*K@l6ZrEF(7C5c(SK9u&jjHiBR3C47ht*L~a zGziE&uZFkhn0bKNjsaxe5@PL$wnq{c?E+y@v6G0+5%J7b^a+Xy6@F1gm5K<}5K9BS zvL}D`h&>;@Uh{TBX3LjTxmd!OXUi3yqPU#eD-EL1L3!I;DCrJg+qzasH;PXP+Do}` zxA_L+p7}?#;vE{{S#ldu7d@pAU!)|#V(_CO4~5QUfl3i$WMeTBn4D2YwbZwfL7LQ~ zYcWcMfK?a(Z4vFC`UsxggHdr!Sio*^2D#fRUa-Kec^eXgxWTc^%Tg0iI^;%0_=Y}M zn2|-2@gtXeS^4G@F%QGQ%z})?O@mmOWZ#nVlxLdbYGY5DE$dGt;bUL#6zR ze1j;G44#S>(S(Y+k!#2Xd78mj=tbt6w-tD+wrynyug<5H%1GLhN_z|5SrcB$Dc$0Q zgr4`%u9uLiH3mhADYS1^dO#9_+aV@*B&ZYCdQPHKL9m8Si;jt^QeL5LSww%f0aozm z)m~xSa;?a5AHXBK=_bWAExd|ukO)aHc1N4-56 zu2bsEMwpvKdTdY&!6IYuQbHWL#Nq12)>7D>g|NyT_}MzIM%6#DN(u5hkuq9}Wem|2 zh04VHd0CF6EaNMc1?&uV)=qy+_~s4YG9JF>1EJOdUx!xNd}tM!g`*c2lSMKsqH3<7 zt=%9aLik(h(qP=WpspABmr5S1N>CsQc8X;iVns>`PjT68}?19#PCo?nW3FOnn72{^Wsm0_Qz&JI$VQbDTHfl?oIClz)&waft6FfafV3JlO{XOh z!ixPO4IXyDjkf<~HG?=msLI$wS)=(KF}yc*)6WJS_KCS||@qSU|43fubK-$$^B_;E^O@ z%?-C~S+Beaq23K>8t2Mrr#5fiF0JJ~5e|%`Ebzeu5I?kqn+&7eOWhN~3|hMld9Z_) zoX#-e`AurjcLY(3C2|S7;9AgaqzCGib&o)1pG{Ax7i2fK(6;2umqn3JeeQ!BRp$KV0wZiUfE)M17fdNb`&>FDVxi-}RGeOMq`r9zb~jTcMd zQGW!9w>ON0q>amU&AHBU`j&2Vm8~EErhsix9+Y?tg$NC%Jcg@m7vePU?OGbWKU`q3 znaUPy4=5GK5uvwLsghvW+$Kq*8rovM(JbK!2wlr`VC52t_iarzXQjHV7+o-tYu(}k zbI)=rwwz#mo?TLGWr5RYTb3g-Jd{b&OfD#e++m~LSe~GTj+7`+pb$LGFkSg|F}zwk z)$rZVG&EC;9uz4^Gx(3Cp)F(^+JswU%XMzhOL2e%2IwTxRNJ!4RA(P?;;g!*XgMTj zFz=uXmr1hVe6^0tC+6Q4u}GJOV7N_ioLyv`Z$hAUb*FCW+nq6!j>E%n(8` zB+6feNbfK>CDX#Pe?(h&fVr|fh|+6viFDGa7xSdoVy(ZYqqL_{h!mU1s7~dTw zZ+-KYyJ*%BklqTVh2cSi!j(sW)QXr$Yg){@=C=t?_NpgW}lmRto)$87nM*0Zg0ff@ z)Pl^gCe-f87nxGpVS6%qL$$bPqE+B)xpq7s)^Z0*@(e~W56z0(kYa(jEOuTClG7|b z={lLzkX+Ap6nEjTY(nfWE(rz>#A!B&sfv;9%Honfw}dTFV&&~xUIr>Wumz?rzLl8_ zJz>VyImm}F-4Zf|W+8a^of17`)nF;BL$;~}i_p5I9XK_sFdxgY2^@yJ8K|E3pX42!^VR);<#zQ z$i}=#3tj}d8p6NKuVT1X0qUjFY%LJ(clCy5l(X#tEJ#^4dyEcWeU!&;w8p4`28WT$=56vG zyj;&>!+7kc`@9Ym4!I?fD$EE0mI8ZQ)l6s?lYX8E&X?tI}(D5Pez5SL`4 z$cP4MDj>DI10f8K_Kj%<+0il!#59&&S9d*A8t29d4xGY@CZbD1FhG(lDIH+PzVO+!^i`}9oG;EPn*b~K~ z0J3HjIujB^G#)Ih=9hYfCw4c5AECm`wXW^DqCJ99D{<9)C{e?s4jV

DC4x#Bsk?7^%;$J58$bwrcpAyRvqMkf{}Lhlxo0>l=%HAgEX zl1v#uSJ*+e{|tL7uTN>jA!ZW$9AbkCbA}Z*K_O}z5^5eYtU;)ayGjEs(p6?|W~Rozuixh!>nHfr_H%f1c#UXwWG?=qt_y ze40PP6Eyyeh=meIB2z-4kUAR(60X#MI1x=ue5^IC?Y)WEu~4g-icu9qqP;RHWGJ|o z9_npqBa!n!Bz>s|i2~a*&!hK7DW+*kDJF zI<274i!~|(^nwi(Cz3NqES*v8Ls<$7kU7Wrs#qA8s!r7bh}_QDS_ExwVedRG;Vh5& zQ$3)I>=v2ixOZ+>}Y6;BU!I*G{AKJ!gBG zNU=%Ts+_(plL0nB>FS)ggIN9miGDM_LezCwpKN@mc(mo2h~&zX2sVIia3-H9I1kdf zc|YUpRJLB|ak5xOGH>Hy^5~uOD3Tn@1|(@gCcIV}o^ThL0MiGDjf?BNkdDjk{lwV) zDrd_F6UDqe1XE4#3?OHxQ_~HM3i61WVx9%DN`7+ z9`11`KRGiy00rrdEF|u<&JrL$NVz8QWi53~$IQkF1TkX!)(At{p2L9pACD zx;%OG;Oe2h5N>S-9BPxPsVR1D<@5YXef7(Vgi`rwyx&z-C_gQl3h&H8726B3q37}= zzZTD;4J=m+YKO`(rj?UcVw_ufkV&z}TVD0V42A-z|8JL^^H|7O3q(=Br+!-Q3ks+vJfd%%k=71Ej(&uYrl4C^Q`@O+;Yi)F~)wVXg{RivbvEhQaa z>~<%rh|})8nx}FE{C@nN=YQ;-ulm^A-u!nz^s<5y7g=E1UZ#9|dF9rUITVElW3@H3 zosDtj!ex4}gf=Nm7qj71MMdb@QAF_8*NJ#Y1wxYt5|-HJW>8`M?C}U0B1XGByA5CS z7jo66lDsU=HIS9jBE&EmCBMR!28dp4;qVpYxr=BekRWyxhcZ{<&MRKGt1?gzy-LE@ zW8-enf{9G)ik#VSH32hZNj0faMmaU5XgP1&Q63FD zslU$7nhFN!!Dfmps}&O)%Be9DGyX&MTf9i}-BltpVt142QKCMqzV(<=tef??*hmxd zH)Y2A8>(GUQ8MJbnXggX?2~V*BE`j0Bv75t6RRG|Nar;{#PBWKZ6lk{!%tjKjR(d( zchU`{iEpL+_2JPt$lZR@RQ{lCLzX!N>8jS z=F11UsH8R2ie|LMCZ692 zqH>D4k<_gmA`CT^vK91`Dtn(&+5e<;-@d6UuYBU({d@OrKT17rWiEt{Py^|y^LMYb z(yKeerTTn*Y1nx>Ci8$@9agfZak1|lUzuZH_bJNyDHUH%uZCJlgFfAX){7QbPGPrg zKQ?phaM9g;)xF!NJ#$u(lB7}!M{*MSYjv)Ymq_*5;2PWCrnoM|+AD`U?i5U=Paz+? z{bXA&>!}=(u{4!-R_$y5n*CSdVe6M`#yjcL(tW()?pc-V{0&_iqsHt}cga+!r|0ixOXK1ByZQMDre#alA3?RWFhv>)a`5Ib zi0Ay>@OyR}K4sQOZ@+_!u4hB)ZhE^aSMJ!s_nFBPZjSQa)JzxL*d{`i@!?p#cecC6 zhZEGTy5R&nvjE9B3PVg;L88)HHK&X>Zx=8gM0qS&WlS^8yEbP#bkG(eFus!DV~b8`WbK0qy+@sA}=kxU2y8MYt?0?`vA9N zkgy21-noPA%6LH#_u7f9qaO*AH1EJX!+yKS>otUq+wZXV$0lRxSTa`U$T(UYU5?>c zvU|7Q2&m{C{bG$pGDs?F9mwJS>ek=TX z{_d&t%xQ(4wM3nET&fdwfN{Yy)=Hm#<3^AQ5A+9=CQOlQKRU)fH0Uh7XLU@f5DwRROQqCo($C*5TSQOx zE*4tSu*+)5bgfH@$x|b%8LERNLqtQ)zfor`w9ZgW#YwMp&%fQMs(6;?k5(A4G{ zC}UE~>#p?|BwkZAY4dvg#N6RjSaXpdv_Q=eG3cGY3-xLBO0bXCj7pQpSwjUft(d>+ zR(}-+^T}jjyfUrZVyGaVkSkcW0v9z6a#Gc?&E9)q5;jYHWr*O^RBnS5a*V@N?CN8LwYy{)5>D7 z%78#0>G{{Fvx{8@S(-OvaD;%9Ami{L5`5NV)vN`S>_ObhRdLn0QMsnGe5c77^P%XB ze)Peju2lQiAM^f+9Ow!xEJ|$1?aPS*lS~dXGE21wWRa*F8DmC_x|kjDnPfo|9_W&E zVVLC(NbqU3uXbifrpDEHPTe%KCUmc~vf;V3J<2*O=if+`ZC}rd1d1GG1{dq+-+%}J z8AQX>G+nO+D~S1++?`gd)pYlyK24)1R0OCShvy)E748OC39_(JSlOA4j~RlE4GEF` zwKcOhHGBR$r%#`nnLGcT>6C)$R2SRrhP8;1Tj{ZO0z%kdYxhm2$3(&i59Mp^1~9ae zVU1{FwR`_Le{pruRfrvr9Gu4Fp+V~R1_8CUP77CIYpJ;EL%QEy6bxFQbA}# z_CR~Ai-b@DUCeWB&6*9DvTX)|3XtXvoJ4-0-B?(RJD^T_-0s3IDyou!@{Yfd`lyu1 z`MXG9n*NaPXE~h`$wIVADwQsQVgFsINAMKa*(8Sd)-%7sz-H0Q5PDHZAl*d#)uKn~NEo5wqhlp;AR;qikZt09kC1GO?FYFXl zXR8XlCUoA{JV?%oc?K*P-~z?`Fsq$GYR}$V+uRMNTJzuPT-d%hp3`P&IQAwb6g6*I zg%F@eG(>N6%LtkkR37R;PbxAeR6S;<4Ja@?7Dsfm8k)o?$G@s25oucN=XL=fpv6? zfj8#yl%#jb=|Q|~n*$Lc53NhnQtK^{M>ilMlSou*Ly;(LH!vjtk;jIiF(@@)Z<9!H zfjP~)i-RT!wv;?B5HABG7f8}9Le;F9OJ=&{RKZk?b8AptX0j~T&)>saUi3iTw!zHE zOjWL0Ry~}6nc<=|P%#xE<>pLg2D3vfF*_% zQQwKCr#jcxG8k0mkWHarV(d@~f4a~hHlifFI2H7ZyQgy1tQ_~C-Pti7oLKX{8J6r9b+SBZ8B!C`D7SEm+nW?FEgG^Kt@9oWp8iG3%-w4*Dx(UpRoz#489_g z5K~ug!3bWMEOBcLL62YztJZu=+`Nq%aix7OQs{}i3v3nZpnlo!zo_7+eEM=fjV7UF z7f$jU%wdJ%MNmXv;As4sz@W?z^-?&E!J;f#Mk3NhmR@)x1%->|E;JL}_TdRc<{(EX zwJ>h1+lVXIDathwY=}K5`$*?sW0%Iw0mL^x4aQf{{z6-3v|SXrc#MY4@<3Qg3PCX7 zS-M@4M4m6RXa(dJ0;*=A(C%RtiG1}!nM z#h_Vd0ahhr-J6I8wRPSs5od>Vjvmu6S)dTRvA~SPyE<-0j*ocMWGbvJ1VE=dK9M?6 zF^rB_%QLai)llbQl33 zy2t15b}2bIIcd@om|j*GWAR*s#4)~vJ?N&>7~&JPDl0`^bbqNf6>pD_6>uGMM`Zfa zzd~E`MvKx#e%{R zk2kH-hAD~{NNrZK)F?3t3x@e zIaQO8m+Z>XAGrC!cvZ{@dkiXek=a*2SF6?hg9L6LIqQj&sj1-SB4zz|rh|=q=d34T(SS6J-9k1XV=%)NnkB@pKI?%T3bo>l^$Sy*d_Z2l0rlz-U zrO+C@LcZ(<%Vds~DyFy8B{DlEcr7djr%BotPNT`$!ZB7q<0>BKov^?M3iFT;Zv+X# zRRPG+&|{%3k%yHFA5=|`!c6U@y)+CKa2p8+jy><_U!QdfI zYvXcz4}M`W1Y#f$1{9Z>9>wLil5Zv?7+{NxAIXIJNyph&Ke&0NvvkI^h9)xF{UeT~ z&ko3zHAKcTaAW0xd8uL5oPV(kh0MmdtaLSt6`I8*~+HnA_8juO1QX70hKU} z2SSsYYq}~D%7`R|P_p^TZm)>=dPozxNS7$hB_@hQt|kXU47#5jz!@fvDi@0^>=@|* zZS^Mul_#L0^=C4E0)gRjYY#XCP7iLo;I@c{LH>5iVY6NXXb3yF5Kz&>rkF zQ%)h9L#U4Ck0tgm&k1^9{`C%2lL_!8X#*B{*{Th;cbhil7>Rq-^iuZA5=S+X?UMbo zY@@^;FcYvk-y+4984UqS@_?sN$Aiy%8?(!PgwV~BWz0-v6~Ry615}G>w3f`&jwmT# z{w5l;*f%yhdjk{M?TKU0zo8C&bB~*8xkW>cEHIqSnI@JnZrEff)U7oY`i>4rb8H`P z<;YTt_W4BbB$7H{OWSGNq)@aY<_=L>1=;Q{4LeoOFc*Hn%N+K8&h`os)GH6V|;H!%sHN)T%gIajtD&E}1 z0!1cTMymF_w4k!?S#1+t3I>}I=^FbXc-(5#M6sxyhb#gf#zU8ko_OQZ`M2O>QM=ky zt?q$P^-1CjAra+~WDHzmCB*-|e3wfMvs^+*+&2P@hz{|n+&aB*X4whb1O@IgMk|gA zDQ1a(*xuc2!v@I>NV&kf3_V?E%*&+Ol)1!YqeBRQ&qhg1N$40^1R3&}o?%bIe zCQ#`PkEBT5A#d2go(6_J-XKC8HRLyLvpFxUQc1>i2lg(73IhvENidGpdp)$CI)qR; z|C(z0O!1X7muN$tzutc1F3iqS7-vsPk4P_6{kBM1rPb zG!n1Y!eDsXmYCa_jyFs?7&(}WCn=&~nkMAlV4=eTF+I*=nPZ+SX~`U53XF&mu~3mS zNY3ifGXTANd|+T$X>{2sk+Ooo^l>v+W+zL~GFQdQFIv_l!QI7uLF!UPQ8=Dx2r!rH zDJINceP?{md}2Shn8;4ZN^)Z`f~x6>;8l8nHh+#xr@TEEvNf%@RKX|>qHsbY(2&bi z^89>-Oi9j|^+cdr#t6NMF)_xJw@`$NNi5oXR!U8|6;)Qk%J&kl*LD@)3e9LvO^^XG zh>G}$O$C>S;G)Kaq{{>To;YUGX$l&0v1=g^8iwsz7-=abL{v37$^dh70~%o)JIP2< z)#^}j1zv{3K8*8pilR@?jBuk(X!OpssR1U3;;-)RLU_S~WhC6E0CrH)L9^*>`LQOP z!z}T5J*=<-%Pnu!;XKO8od|@qqt_pf_TYkN!Mp5&!VQ*7BM!4P6z5-v4mj1O*ux8+ zrDQwa1&~|sk*$ScHDzPwDmo^3{$>nZ@O)fiYt~I=O+1vtsF?z*u1Th~2~*HRz7LZ< z2wk#<+(h>fcam9#_V92~5?n!>8kt!P#?38L{ZIl}waNtDW*+P~MyM<*_MVNQuAshf z|CN(oQY=+cUhljz#@EDAX69irluM%pO+bX%pdn)N2TB#0&@ra+Arj`++-PQ(hsZZ= zCL&=OPX-H;N^zTm(rQ^FNZnV^n+U2+aFq${f7RDdlS85!AxjSP(jB)~>unb`g>MG2 z_aciS?I4trIfo{h(K3P{HMBCRW0Zj=*g%z>Gah!&%?!EPDT=cYGAh219bl%WO#$E5 z5QQb@EkP2-R|T1ZBIl6xlW8g~>d0gf#R&Jn)aAIhJul>pzq*@h;jWr)>$jjsQ<4%d z<%-fc2KP~z(9+}0{L9SIIYx$NolcT;p~Sl+USMv@KORbFlh zO1&R0dDN3l!nA6*h+Jc{kn>Pq{upsO{4Oy`p#4!%=w`POuimDORI|{e6Kzgk0Y`*) zMQBU7xG)t1wYh{sK#zr`WK>EylzcbQE$rMo{}wtRzOzA@d8C&-pb^<_#;^vtsdZ{{ z-0ngwuOMT2iv+1lNy1PyK{~V4zTCcubIW4Gv(nLSKxy((J!Y!eLVu=mEcnx-l~l&1 zQbHHK!UwPIsXDyH1V3%i-w7_xzZQcA^VudQll!R^AZ{v4Uu~KpmnYy0wU?YMtse@} z-a}f^kJFa#3^_6u2*O_qevz{hOB|EtS!jdROCaFB&i-tLEjk}lF3s1H5Re@;u%KB(tuF(x+9SH~+O~prQVEOb( zjmo6Z>sUIdD7rTCdom;JF$eZ$*M7o_b9if)N-&c1&qtp5+GQ~UZ>~ntgLHcAo*U1p zxA78F0v+}$F7Q>(@Uo$b&xw1N(G5{-nTfaTpYT#M*-jeQ5GAP*xZH~8%pMxAZM6k1 zUfryP=DZ;B0+-q3!$@2zxeoGk*}?o-x)FRB*?<`8A`FrF4?|8W`XUUu4<)liq~`o< zLMk^H7}IJU(&Hu}iB0%DfFA-X)o7MP*w^kL;hoB~>qP+lWJasQLT`?gm#*dggkB3d z{1sesSe4ygyNUV~=UT0IJmVbeW3*RWLo$pK2I4|xDP`m2^|pC&mkcWe;3-P-TgVrQ zUPVF>v^3>Q+$|&*$e+kfSj@MJ)qF9kGitAohYB5e0MG&D?GS^dhw^9$>?&@FZK)~W zeZr}S{s!9_^{IrF$4@Ezs@D5#5WUE9k0SI9ZB%>tdRHpKt>jWsku6pdUKUmjc{>yC zCKXxK5x>J)u+h607lK4Y_RYJ*2G+|6T%VzwVuDJxfT$~G(8av?=)$eZO3pJ_DcJt- zR)z{YiZM$xePPHhc&I4*HDyj^qElv!@KuDzZH4`N_gz^a=60?CNfgL9>=9{A1b(63S31d4e8FQL$HK)OMbY3noLcUxy>m{d5qW zmsKj%R?I;tpLG!?Q_x}@QdZb*s)Vq*rvnuy@@jBz)5rdy%i5215CstZ%c%X&yO3P65M|zFIhtARCfLVu69THERrt(LqB73e8*3X?i`T>Q(q?!@Tk1-^A++^n&bXXHa`PY!H0L%gJ1Wbob z3$~lRFV-#9qFg-ttXhc~h70-|@;s7am(H}?w)7073m)zXy@ZLxj)d@Gu=YryZ z1(A68%Y#5>OcC&*7*v`=g;aV0!>IRTMdo>-oij|y;)pd|SiDxnHktsSE2X%9ldqdb zqs|I3>MSWMivCQ*g!)+UJlbeU3O#qot&t@>l;TSrtZEf62MOO%)Lf!i86ZocjXoaI zMhy48p@`T*fhb>twlxDD2wBN?4`CY#6|?SQ6iNK6`U;Pa4`q#-aT4XNrUdDr5=tBb z6|dU-um%X@iW8n_Ga@GKWRH?5EX|_CNWpYUl32PBo@d%Z157nv@`piUEZu*>^*k3M zH`pufjNMd7vH|vljfg-ECC^I~H3dk%ty(^DmWD^}l~hzoXjN74-b;(tD=lDhmri48 zvh=mpr@EbaDVt>3x!_47ku95HLRP+|5k6CT1DeBYD^21N@Tp*#@lq;69mukc8iufO zuJj3-L()I+dUUK^eTWgfa=birOC35LSc;wg89fAl!tkwq9N5kQtie2*08wA)x2v?s zET+&(TuFz#j?*-ZQa`L%4bf1cqC}#`AWWq_ecDx{mkn*!%YI)76|0p}T#qn+o-4t& zBJvngeWI3pgJFBtCiBJ+@70UWNT913GUj>)omDA2G6J&_nv%T?!<;FtP>4;4JqnY# zv>lsSxy6FLVz(7gzc9H%oer-Y)+&!vGY458a{M|om?Sx@v*^v+@*K*T*E^1QJT)9N&S3aQ%KFG_0WiUxg;uP*8?xHm_f&Z+c$rv<06<_(NC^f~Ndb+L8 zmhvs>V)1sUp1)A1tBcEZagYz6NW1AEg+{^;COaS=UxC04;W?~(Cxt=z%7rNQI4cSz zBY&nmmMuoJuxb=15@p&0Sefi--_UQnCw23o@WrSxQHQ8?QJpJ6JCCT*MH9n}ecHPb zBRCeIVR59C1e)BmxBM`392CEhZ1E}3%!VGQjZ#rUa4dAGN#SAzWk|wWXqjIno3Y8L zWRf@NjsZa_PbNqSakg-!m~!ifhmuV3Yv%*^1Ei-tJQc=FkJx#NhhPf86`>f&G)N3x zO1-oR6W^_w;dPpdSTSUK$Vh(J!a5o}@4>Ofe`qFpR|HaHGFLO|ljfcDF?#7THo-v+ z6U!Z&jD--k8pW%`86@oD10>?BjF84hQGlV`{2qd_F+shTNd#$hZ%;)!VP#YJL| zlvQcs5YyZlo1gOs)Fb%UtZ zjPkT18>@ogo9$CAsh^MxEc}CDwg&%&N5{Y%-HzPWBf)~VBrevJd$chqS-C5run9sT z$^`?;C#8F=lkc;$xEZk}fnVZ=^r%o#Jku9>IMc~KC`mU(RgEA)*r@dI4yhl(8vwUj zu*QW#vS_rBJ;r{b3bhf^UuLAVLYa~#uVmGa1cvE?3>cL~dTNF?nB3LXp$dF7b(CO%P86&w0qK6nqTj2cC5r zF;kzY+OtAXK>F%mWEewnLv{aZtvwDk7hlz{~djvkTQdYrYu!C@wMEg?X!a^Cq z)9e|+(2?kx*U~9PEdq7s`CKo zABa_m@QC&Wr$cnQmRv{eHJ2O5Tm++x4B=+w1^skqk^Ls+#}ru&o76J6wpR4oBc=%I zryySfrRp_W3Kg=z^R|kak-8(OZO;n%1m`(A@zeRcXjA)hN^MD-ny5j48DU{>mC`~= zp4ntJNXTp7H*S>-j+ts^0Y4CJYvB_d7_^U+Xbiu>W}zRO#)RZCMHEu zYOka(C4H-Bp0n>3!kfG_4MSiB>s9GEIGiWsm6$GJ!9iPGWdUPF{Co-f>N0Yb*o^Q0 z;6GAtEVH6CAW@@)up|t_k(h;iw4^`WPp_4cN9ldZjQsJurc_S=(?#W*JsPu|!Y#E9 z3UgOp(`P?>)mo6q0M`)oT~$%B*upmDa4rvXu95+7(t8U>n1Qswx)ydNUDc23OUS9_ zHN4mX$O5J9+{?3lGZZGExP{r2=fNT`+bM(^1~#UOdR6ksycGUm5q~LrM&$>NG_$FzLCdZ}ZD7?gX{eK4 zlD%L=mmFq8itZ|*17A{H3NY?SpQ$M(cETtr8%DcTT#|TV08AT477=D1H4>*C)l{Gh zPJywgNV}fEQAPq*3=ty$dRR0-OX@{75)#3>o8}Afimg9vAs}-Qg4c|eLR)4v%8>G- z+yoW<896|9{U{oUXz8nh1(c!K_S?Oo?e@6ZN_Qlu@TW~NGnMwbLSF2rhvtiueTnhK zmA1*HyLp5%i-*JnGR_F;xx_{Yn*}b{4I(IBwh5wc8P{87H>Dp!3U)rcOol0%7nKAy zQKL3Q1nouR?5ORrq-2_2-x-o-1ljvd#Cj}+BGG|9 z5_G{`kd?&?irJ4Ty3sO4QylJe=@n!Q%VkLvt|lgZuP>-UOo~WU6R4sh35d9hQH`yO zJJazpAJ*8rMOkGwF3s0 zxRFfGKrV%ph_=DR9%78k_BAz}VEbtyF{Im%pACn}0a+30wVYJ+B5tGNlaq^Pe?l;A zEoqE*=TeHfK>{jPqn0sUJEE6}8cCax zt)s$J(L>iIws^;cTkg}c_bJ%N(jO1&(AoSnIMv8M3xpteBp+2?2MtNHn!c3RfezMk z-ivfMSIZ;WMe|vq6IZ61+TwP(hZfn}WHey?$>U_)F{G;jkncX8Z=Qj%A3ZiQ_lVrQ z9>F$@1;?H}r40*4SbJd)Z;h$s=YLK1zAbro9u^tPr#^O@)Jzbp>Hq^MiE>eRJ{~9* zPe)6~OqD4 zoLul?hN6ZdZHhy1NZGOxpm%+M0)2&|7tM8mAXk2sAbpMgzHhCy_nslCNT>rewK#L; zoPG9Q`&-}oyBEABz*LHJGIxtnj#UQJ+udR}DZ(y>ikM^Od3uvMi+XI#4wYBWp3wE) zwMQr<;UCLyH#6ymGP3N=%|aU|jPMyk8X^Qw2@z}zng>KkwUP@$VRrD4;VI5$BcM>e zbvGm2VRP1U9o|iR@eZ45>~ZVy@tJ)rl>r~+zCCW*2{v=?8`iCy&>;I-9{Db%Nzj?n z+%tr)SO7sQ6LlMhj~NS>zBO2B4FujgG9fCkSA#qh+r?y68J>2!Jgo#3!dGr;D@J-J zH>i3HID_tkumq(-6O;H7&El-a%KntRMa}_6g*`*?pmM&+f6C(=_z>UdQxWF)fD>#a zG>cV^$ z)#;Zc4wG7>rn$TNYxh}Z6VG%pCuMx_GoA4Agi>2AFjm$6)is5el;Ztd9v(h(FyCHC zy_hnX*tY7ZPYogb{s}RJD-~LW0rmkC!6LCYf~!@DsG0yqYc;E{=y|C2hN{IOwko#n z5im8Q_bgj9xfF*fL6Duo0FWJWlAH1^BE!c&mR;P-OkT`jjo)TOi_l(;S$IhIdR56aC2|R&k}FM6J|+(voXGyxS6s%~R`QY=Xqk^{N~(0;lxl%=16ac` zq(iD4p)tBHB*?DY&0)EsUwr^GMj{{Jt!q@C2@kN zTTNzQfT_H|pSanWgmp+q(RZ3wghI*&8wR_TbV~T8QaI1yJ`YXk-TcE6&c=9yf zk>`YnY8Ko=&aLb~h`#7;8ty<^ZCD=(f{oZ5B4I$c)Dc?)kM^-=){H0EpOfqwN5DgP zxg^g|C>*I=g~vv?TajK`q;^=^Rl{6o4FH2|{VQv7LvNP^NNObm+|5>GxE(;tXz^IW zuFmra2b;lkD`j6tSBA4*lcBMqE@&1BQXfO{yQifezK-d20Z2`w?)p0 zD9Eo%_5l_>N?XslS+nV1%GDuZjyOPyTd)t17~@h`G08*C)quR|9F)fPj(}HH0=0@b z5&&+h#5POGN@ZTO`h}kQCee2Suo(Bccm7Cu;ogwZcLMt3Oro6$HlT=@XpsT{5iAdf zFiFa!k5fON7Y7v4bpoPg&FsJea(qE)EpMIMzaPoR&SXCAbP;ETLu6` zmk~H>`wKNd-2g>Dj0;s0+mJ`;)okYH-r(;unNE_o*v%Rnk+irpZt9z0t`YU3sMH^P$~QzjjixUrZ=)&G;5GlkNI~jy6K~FN{UqOXHm?7@sq^; z1%Q?u#zm||T$k{5+Pu)8Ak<|vGShV2TFfN(RjOJ+qcWw#Twy=RR^@9^84_qI%$>IV}p{C1h@6dqHmL1k5IMQjel+=-(C<$tzYAy2M;l-Bxf=~s+86FYMf@@c!~!_@ zNLzT=$C*z)d!qs+%ugmDD)NK-%;Sr_y$^XPar%$&F0_^qb9^4Q)!qBU&m$KDQiCU_ ze#Z~c3@jtZtg5TFBQk^)46a_HXw_ltsg;$zsX!oEvMTOaZ@7o}-VA0$vcEu6>eNMp zLl**eM6CDxUU+Hlk!L{tQ?|<`jZd4dG)Sh0uuH;&CYj@*r3J85-lw+?Yi{0GVk(Yi z*HIC>*!UDj*?@Sl{ovcqbZ#$>lGipf0YCQnr@?Km-eh%D+(@Z_pY!l)*sCyYR;lNQ z-9xK-h)6o4TS#ll-|NrUe$Xs*$}JW0;KrIFS%U1ovJ&)>mAVs(thE6LK5V8t=z)&F zJEgrT;g2NOwWkgt@@7#gE*w@pJLe5jN%-W5hL(!*GkU06)0GCzh!U`Z!=1rT-DdqW z09FP!n^h@F8Y>qFLHN`Sv1RzRVQh!rg6CH<&)^mCz60FR#z40PAj}OD7Q37^YBwGVHwmOfB}^3$X!Qm?>Eo4?R6H2MqlOy>`cZ)NXs_qZmT zLT3gW(YBRGBW{eUeDGc`qekmMA)dAx+4Vu%y2iC6J~h+MN6Y{)(Gr^$Z<=>y<>;I*uB+(a@7 zP^32g)=Ba`vt$v1QtH}{*d=NLWgE2F@TuW78b`7C%|@h1wyiDkhJi8ZDg8Blp@!T1 z@n=gL;FV$ZsaQLtzbMK$b`XuQcw z)+=a>#fVsuNXFGnf`laIn1Ss~e(97laAa67ekT3{ffK*-lQnm;7r(^os?vivNoRN# zR6i3tH14@pPX=QIIeDl!Cv!I^_Ky^m7M!P`^SDYYJ#Z;p1C*4P!k+Jw;k;I_}6Z`NN3fmy@{s3`=Ju03LwHW*&XIY zc+_A~{0~kcdJ?Noyk=Au7Se;vkz#eZJUvR(Ru1Qn#+m9%Ozqw09kt{$ATm=yo9b5B*GWR3veeaYZ-vbCgADe zkZ^XGixxcl{J&mjJY&I`Lby3p&>8=$@BVlhPCnq!qSysxM~&QRot*uk{8xKAGM|;q zXeNIZsy^JqgV~m0H6=6YMR+{ZQ7K4%2L+;Z+8JJz$-#R!2s5VY7PHKGS?$Kb^fQkt zlE^;pmAuN|XC0twP82PEW0~%K@5RAp%ePapyjmlODu(S^roq%BNaXD*}0^DAtb z2(4m`@J3OkAz755$Ss4<)cp;aO4YUVsTE0GiipZEXx*dGIr2df>lU;3Y=)n#Bvw{c zZ_K(T@Z3e&716Bq5i(nXr?p_8GU1_b@i$0@qKo_9)_Yv~6pyHbGn~Q-5Hy4W>~Y%# zL(_`aTqr1Rjz^Fz_JgbiY9N#V!Q%JMRSZ{<8V<84G!p^{LO{B7D%hms&$|7jYO>44 z7csb)hc-|K!DeHbV#NLyWlwY-XVxsHq;^JIy6~3Cr&8#IoUsL%{ai-nRNoj#_5HL0 zVhO1+<2ojr5%koDu0qbLWQ^g&HnD04yQE=P*JLn%4XtJa#J)+~m0h_xqYAQ(Q)=O< zJyp8|BC?j#YRyY5MkFK)2ep3V&eqO%cOZtN3(?wl6NR=AX{E^oGqD&5xX7+M$1*R$ zG{Q_?|LvuMC3KvN;KfjwmK$r6GqAm^bHEzpM#vSlF!?bhTjyRaJ(Ky*4E)neY9rzi zxtBES&$WDjjQ*{x4#3^?S#1AY?v(!Xk_(#F8h3tm^dJa#%6>R;3b$fJ>r;?KZ;E zJ!)St`vVU)3QFu}1R?~s!qd6`+QbEtD#;92f(z_bX~Yv>!6N8%G0~Mo-MvKL3z|Y7X$abLC$RM!3Nb%wPAcp3fg!VjF zYOb<+Z1>W~{q&`<7c?`q!tY%PGyR7ws7q4Eb=FQ{L#yIGkc8J?M*%F}P7ix<0;tCS zg3c09@}nWPn=VWS*Xe8kJS!t+$ZT!`3AYm?3R|97gV!O=8fI@zD{+^~`@u0=^WfO2 z+?LQ+0`bhBcF$U+sy1jXfH4%|WKxR0-6xAi2ELVQI9b?3Ai0=`4lD?_BjV)vj;0YZ z3tPL8-0l4U)AX3dJ8RYXuquTcrLRvq|ntekks z-;^GQ8f9HAq^z0_lI68i9C`;VAdD`Z6}me1 zOtj*3HJfZ7Q;iy5Tyk{T1cI)K&29&RF3oiVZyepdgFg|Fl@*V&DIPwwOQ3n0IdvAa z>ZNw~A3n_QLN0u@ecmcfdHB$^Pelt+jN^mme`nXJcGS?OD4Tux!{1~-FkUswOy~DF z`o!O5^RJx6!Ln_0Hn5upc!Pq%Aw*v(`IQ}8BLIf+5F`lUL5AbR3b`qG=R>E0YP-le z1!s<&AS`tg(Fk+S)pkDHlY}?Zd$f#In>yjd20@4!$O)O*Nx@Ip&$hE$uad@4pi^QP zVq-Rx1oA51>~fw?VPsr7K96-M;F0#={n)Zh9^it%i2xV75pmKWxV5IHQ32#m$un8R zMVLD4y8;BI{lrO?E(zKwQ~-Pc!5du+coy3m`Mk&GDjviChV!QM)qCc?(19RD`0_+J$`H3Rf+gF;Cz{m27jeLv*jtoZZBfg; zkTW(;EKyfY*;#aKFjRu|+P-Yhv~!UoE@nwFXPBs>TMRXz6~M!`jyDC8Bc(8C#}&h^ z8LkslCF2;0UR>uLDmzjb3=|Fh$0eHrcnDV*dtxbkKzF^|l_gGADOKJW{sC4)(RPMw z$Y=l{fn>hxkYGjBkVR(SQ^4NiCmI;YXSaWx+n7ft^4sbt#x^3=6Kv9ijIR0e3Lu72 z;MD3avn`nhTeWP#>fi$?EghJr(Y2vw%1XI9q>|}CoS82J`0$(Xd})`}3$ua3ms9cO zow3EK8%QrXmMqbMR}Ph6QRJ`RN{h1I>OAYb1WVGH$%f*}m%Ii4$J2ZwyJpG2(&)Ff zrYY8~W#s&}2(HLL%mcGP(n03I=CbdR@r1G! zt{OOkrHc;xeOl*H0{jEQkQlBTwMn2?i$3sgn;5I>qa%vd*+U=$ui%FA2qLpUo*OTu ziMYcdKRlP)MKAhr&2iprY>#>g?N*^Fi-yxfiV8x)W~EKn(Q<%uuiQ+MQg( z>m*aCvdvpElTl0z`5R#u12?@ja5zD-q)5sQan;)JuTi0y^B!4`MEa(8L*df|hEEG` zU^^y?If?By7+p9w)-#yunn9*ZN?KUg6Ut#s%6yc{igFdXW{jHh%#l-+k)W2km6+J} zs(C{Ts739jUXJ>7S(Ixx-XL7)h}N{Dr6Sz*+ihREP_Nur z5^$3VsfpC3!n^AADCY=pgEuQatq0tWuyBfbTYYZa7K)`kWXcpdFxdPCVG#GAL-F>Z9OmCgn3MLw5Q^#b zg)|0#@Z9rNB;UdR8@NVohu6wDl|cufmTmv)B4ZzRPzh7C^bI6(S+UsFZ)9BAGX)R#Nh3)}Z74%5U9P!zXPqdD>eUwaxuH z_(;;3BWpMgTG(_z5MYxa%KXHO%tl;km)(|-y-C$!M=j-*iA#t;8ik{80L$k|7 zhenZRUT0ss9Shjx)8+JJsG%c9l{(2O3G|9+zmOZnz^xsg=7N7d#GK5_zyfa!sp{AR zsCWNT^p23ssn%l1@#HQly%0Yz>^kAyjm1)1uElugpFs2?BX9qTqy6ZvjJ75tq|Sd4 zpx8u8Sc{a`WY3v^g?lFOH!hTT^(;ULv4_%K5zMkrv=v2ZWj>Np&0F4CRDAt|b_OyI zPjtGJNs9-2t@YN(jdt}w_*4B$AhZ-RRDk|?l z;2bB+L0)We+98)SZ>{U#D5&lQ#kQ9F6v9zL5oI7ZCUL zl(B;kbrOTO|2rLNgsSI&M-Jlgi!7hBGt^8tj2#tYubcATarJbb0bZP0O3wKnp< z&Bxd(+)QzdhQa|eb{mSrWI3Z|MnMeR4o=`bWnG@V znK~k@@l6HO%X6tnTKi6q*8eWGe_z)}4SDcdCf!5?TtQe`Mv17j{-%Kmuz2t;C$g#q zd=O4)YN!tXSvhydHUvNz79F=WIB!g1DP?A`yDnG0DS!7cJ#2IFwQjrDT+O+DEGOzo z=MM=-pqbU(sI?LnY)XMUHas*?19 z4nA?9y*!dKKebfINb~TKYDVXvsRNE@Z!ELO|A7i+y#j4MpD#`hU!Q_jWZ&sqUs|v; z9Nr82m75vKp#_~zqp}QWPqc~>iJ=6`|38$e^gva7M|w-7}6cD&rzm%H(+0NNJFDNV@isKZ zJMA4k`wlk?459oi;WI)$tbCuMGq2HplV2^;7t`1BCN$ul35U(DTpuXK@YJjl96nP1 zqg5UGlbltxpxOzC%;aZhhtJPXzZ5p#|1C2*S)ITdUre4%bR5=xG#PrmnkdxsFZcTZ z6bz>&#?Hmb?$eJh9{-qKG=CzZ1HSC-9iOUe#_ZMM#b1Rpv7@*3+wQl@WC3gytwrDm zna%yF-^b&)2cqvNU#6JnqM+3gW-W(yT)Iuet?ontYe^YWl@QI6=Rf!MuFt>1;X7Mi zvd^6A`&S#0D=+L_j%d1ZXDtM(Q@v{7G~*FaH`2Z1vMHDC>Q}3)7khhJj=en*fp=TE zV;eY<}pa0%P^mzH|@azO6IC=HOzJcxT%B!0X>^ ze|1Q%J0y;-K3km`+H#2EweWI*Cd@0QIkvDsCVh;!`{caRCt%9kJN<-*!GQ}I%-H)< z|MPux%=wG?-c|`um@V;G$~T0WPL!3RbwfK(tp2jx-JWPqP0LU=;AnzL^NoY)@nb}I zs3Pq{6`hnE;NMap(%6$iU?)f~dSG_u4xAf0$X)%oovk?HNL_Zwm~?t+i|K>o?F^v7 z#*?oxtxvKO#Vwht{=HzH)sWjMJw@duwO=@`+~KOoGeW=;^|gt|9MRX#8JqmziV zpV(YKu@cpfHzP-`>6N$A3C^r%rXIJv8{o8gsd7w&`|XZ}5Y1|0zIFeh8BP=k&e`G7 zVte-BcWWJWuY+4?{D@p4`O literal 0 HcmV?d00001 diff --git a/po/fr.po b/po/fr.po index 07519059..6bf53709 100644 --- a/po/fr.po +++ b/po/fr.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: Rust Design Patterns\n" -"POT-Creation-Date: 2025-05-17T14:07:35+09:00\n" -"PO-Revision-Date: 2026-08-07 12:03+0200\n" +"POT-Creation-Date: 2026-08-11T09:33:34+02:00\n" +"PO-Revision-Date: 2026-09-29 11:09+0200\n" "Last-Translator: Rémi \n" "Language-Team: French \n" "Language: fr\n" @@ -60,13 +60,13 @@ msgstr "`mem::{take(_), replace(_)}`" msgid "On-Stack Dynamic Dispatch" msgstr "Affectation dynamique sur la pile" -#: src/SUMMARY.md:14 src/SUMMARY.md:40 +#: src/SUMMARY.md:14 src/SUMMARY.md:41 msgid "Foreign function interface (FFI)" msgstr "Foreign function interface (FFI)" #: src/SUMMARY.md:15 msgid "Idiomatic Errors" -msgstr "Gestion idéale des erreurs" +msgstr "Gestion des erreurs" #: src/SUMMARY.md:16 src/idioms/ffi/accepting-strings.md:1 msgid "Accepting Strings" @@ -78,7 +78,7 @@ msgstr "Envoyer des chaînes de caractères" #: src/SUMMARY.md:18 msgid "Iterating over an Option" -msgstr "Itérer sur les Options" +msgstr "Itérer sur une Option" #: src/SUMMARY.md:19 msgid "Pass Variables to Closure" @@ -86,7 +86,7 @@ msgstr "Envoyer des variables à une fermeture" #: src/SUMMARY.md:20 msgid "Privacy For Extensibility" -msgstr "Visibilité des éléments pour l'extensibilité" +msgstr "Gérer l'extensibilité avec la visibilité des éléments" #: src/SUMMARY.md:21 src/idioms/rustdoc-init.md:1 msgid "Easy doc initialization" @@ -122,7 +122,7 @@ msgstr "Nouveau type" #: src/SUMMARY.md:30 msgid "RAII Guards" -msgstr "Garde RAII" +msgstr "RAII" #: src/SUMMARY.md:31 msgid "Strategy" @@ -161,51 +161,56 @@ msgstr "Réduire la taille des crates" msgid "Contain unsafety in small modules" msgstr "Restreindre le code non sécurisé dans des petits modules" -#: src/SUMMARY.md:41 src/patterns/ffi/export.md:1 +#: src/SUMMARY.md:40 +msgid "Avoid complex type bounds with custom traits" +msgstr "" +"Utiliser des traits personnalisés pour simplifier les restrictions de type" + +#: src/SUMMARY.md:42 src/patterns/ffi/export.md:1 msgid "Object-Based APIs" msgstr "APIs basées sur les objets" -#: src/SUMMARY.md:42 src/patterns/ffi/wrappers.md:1 +#: src/SUMMARY.md:43 src/patterns/ffi/wrappers.md:1 msgid "Type Consolidation into Wrappers" msgstr "Consolidation des types par des Wrappers" -#: src/SUMMARY.md:44 src/anti_patterns/index.md:1 +#: src/SUMMARY.md:45 src/anti_patterns/index.md:1 msgid "Anti-patterns" msgstr "Anti-patrons" -#: src/SUMMARY.md:45 src/anti_patterns/borrow_clone.md:1 +#: src/SUMMARY.md:46 src/anti_patterns/borrow_clone.md:1 msgid "Clone to satisfy the borrow checker" msgstr "Cloner pour satisfaire le vérificateur d'emprunt" -#: src/SUMMARY.md:46 +#: src/SUMMARY.md:47 msgid "`#[deny(warnings)]`" msgstr "`#[deny(warnings)]`" -#: src/SUMMARY.md:47 +#: src/SUMMARY.md:48 msgid "Deref Polymorphism" -msgstr "Utiliser deref pour simuler le polymorphisme" +msgstr "Polymorphisme avec Deref" -#: src/SUMMARY.md:49 +#: src/SUMMARY.md:50 msgid "Functional Programming" msgstr "Programmation fonctionnelle" -#: src/SUMMARY.md:50 src/functional/paradigms.md:1 +#: src/SUMMARY.md:51 src/functional/paradigms.md:1 msgid "Programming paradigms" msgstr "Paradigmes de programmation" -#: src/SUMMARY.md:51 src/functional/generics-type-classes.md:1 +#: src/SUMMARY.md:52 src/functional/generics-type-classes.md:1 msgid "Generics as Type Classes" msgstr "Les génériques sont des classes de types" -#: src/SUMMARY.md:52 +#: src/SUMMARY.md:53 msgid "Functional Optics" msgstr "Optics" -#: src/SUMMARY.md:54 +#: src/SUMMARY.md:55 msgid "Additional Resources" msgstr "Ressources additionnelles" -#: src/SUMMARY.md:55 src/additional_resources/design-principles.md:1 +#: src/SUMMARY.md:56 src/additional_resources/design-principles.md:1 msgid "Design principles" msgstr "Principes de conception" @@ -229,17 +234,26 @@ msgstr "Nouveautés" #: src/intro.md:10 msgid "" -"**2024-03-17**: You can now download the book in PDF format from [this link]" -"(https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf)." +"**2025-12-14**: New pattern added: [Use custom traits to avoid complex type " +"bounds](./patterns/structural/trait-for-bounds.md)" +msgstr "" +"**2025-12-14**: Nouveau patron ajouté: [Utiliser des traits personnalisés " +"pour simplifier les restrictions de type](./patterns/structural/trait-for-" +"bounds.md)" + +#: src/intro.md:12 +msgid "" +"**2024-03-17**: You can now download the [book in PDF format](https://rust-" +"unofficial.github.io/patterns/rust-design-patterns.pdf)." msgstr "" "**2024-03-17**: Le livre est désormais disponible en PDF via [ce lien]" "(https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf)." -#: src/intro.md:13 +#: src/intro.md:15 msgid "Design patterns" msgstr "Patrons de conception" -#: src/intro.md:15 +#: src/intro.md:17 msgid "" "In software development, we often come across problems that share " "similarities regardless of the environment they appear in. Although the " @@ -254,7 +268,7 @@ msgstr "" "reposant sur des pratiques standard applicables à un grand nombre de " "situations." -#: src/intro.md:20 +#: src/intro.md:22 msgid "" "Design patterns are a collection of reusable and tested solutions to " "recurring problems in engineering. They make our software more modular, " @@ -269,7 +283,7 @@ msgstr "" "forment un langage commun permettant une communication efficace au sein des " "équipes de développeurs." -#: src/intro.md:26 +#: src/intro.md:28 msgid "" "Keep in mind: Each pattern comes with its own set of trade-offs. It's " "crucial to focus on why you choose a particular pattern rather than just on " @@ -280,11 +294,11 @@ msgstr "" "motive le choix d'un patron plutôt que de se concentrer uniquement sur son " "implémentation.[^1]" -#: src/intro.md:30 src/patterns/index.md:14 +#: src/intro.md:32 src/patterns/index.md:14 msgid "Design patterns in Rust" msgstr "Les patrons de conception en Rust" -#: src/intro.md:32 +#: src/intro.md:34 msgid "" "Rust is not object-oriented, and the combination of all its characteristics, " "such as functional elements, a strong type system, and the borrow checker, " @@ -301,7 +315,7 @@ msgstr "" "C'est pour cela que nous avons décidé d'écrire ce livre. Nous espérons qu'il " "vous plaira ! Le livre est divisé en trois chapitres :" -#: src/intro.md:39 +#: src/intro.md:41 msgid "" "[Idioms](./idioms/index.md): guidelines to follow when coding. They are the " "social norms of the community. You should break them only if you have a good " @@ -311,7 +325,7 @@ msgstr "" "développement. Ce sont les normes sociales de la communauté. Il vaut mieux " "les respecter à moins d'avoir une bonne raison de faire autrement." -#: src/intro.md:42 +#: src/intro.md:44 msgid "" "[Design patterns](./patterns/index.md): methods to solve common problems " "when coding." @@ -319,7 +333,7 @@ msgstr "" "[Patrons de conception](./patterns/index.md): méthodes pour résoudre des " "problèmes classiques lors du développement." -#: src/intro.md:44 +#: src/intro.md:46 msgid "" "[Anti-patterns](./anti_patterns/index.md): methods to solve common problems " "when coding. However, while design patterns give us benefits, anti-patterns " @@ -330,11 +344,15 @@ msgstr "" "conception nous simplifient la tâche, les anti-patrons créent plus de " "problèmes." -#: src/intro.md:48 +#: src/intro.md:50 msgid "" -"https://web.archive.org/web/20240124025806/https://www.infoq.com/podcasts/" -"software-architecture-hard-parts/" +" ([Archive]" +"(https://web.archive.org/web/20240124025806/https://www.infoq.com/podcasts/" +"software-architecture-hard-parts/))" msgstr "" +" ([Archive]" +"(https://web.archive.org/web/20240124025806/https://www.infoq.com/podcasts/" +"software-architecture-hard-parts/))" #: src/translations.md:3 msgid "" @@ -422,12 +440,13 @@ msgstr "Le code est fait pour être lu par des humains, pas par des machines." #: src/patterns/creational/builder.md:3 src/patterns/creational/fold.md:3 #: src/patterns/structural/compose-structs.md:3 #: src/patterns/structural/small-crates.md:3 -#: src/patterns/structural/unsafe-mods.md:3 src/patterns/ffi/export.md:3 +#: src/patterns/structural/unsafe-mods.md:3 +#: src/patterns/structural/trait-for-bounds.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 "" +msgstr "Description" #: src/idioms/coercion-arguments.md:5 msgid "" @@ -435,6 +454,10 @@ msgid "" "when you are deciding which argument type to use for a function argument. In " "this way, the function will accept more input types." msgstr "" +"Utiliser la cible d'une _extrapolation de déréferencement_ (deref coercion) " +"peut rendre votre code plus flexible lorsque vous devez choisir le type d'un " +"argument à passer à une fonction. De cette façon, la fonction acceptera plus " +"de types différents." #: src/idioms/coercion-arguments.md:9 msgid "" @@ -442,6 +465,11 @@ msgid "" "always prefer using the **borrowed type** over **borrowing the owned type**. " "Such as `&str` over `&String`, `&[T]` over `&Vec`, or `&T` over `&Box`." msgstr "" +"Cela ne se limite pas aux types qu'on peut convertir en slice ou aux " +"_pointeurs élargis_ (fat pointers). En fait, vous devriez toujours " +"privilégier l'usage d'un **type emprunté** plutôt que d'**emprunter le type " +"possédé**. Par exemple, privilégier `\n" +"&str` à `&String`, `&[T]` à `&Vec` ou encore `&T` à `&Box`." #: src/idioms/coercion-arguments.md:13 msgid "" @@ -451,6 +479,12 @@ msgid "" "of indirection. We can avoid this by using `&str` instead, and letting " "`&String` coerce to a `&str` whenever the function is invoked." msgstr "" +"L'utilisation de types empruntés permet d'éviter des couches d'indirection " +"pour ces instances lorsque le type propriétaire fournit déjà une couche " +"d'indirection. Par exemple, un `String` possède une couche d'indirection " +"donc un `&String` en possédera deux. Nous pouvons éviter cela en lui " +"préférant `&str` et en laissant `&String` être extrapolé en `&str` lorsque " +"la fonction sera invoquée." #: src/idioms/coercion-arguments.md:19 src/idioms/concat-format.md:10 #: src/idioms/default.md:20 src/idioms/deref.md:9 src/idioms/dtor-finally.md:9 @@ -464,10 +498,11 @@ msgstr "" #: src/patterns/behavioural/visitor.md:13 src/patterns/creational/builder.md:7 #: src/patterns/creational/fold.md:12 #: src/patterns/structural/compose-structs.md:15 +#: src/patterns/structural/trait-for-bounds.md:11 #: 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 "" +msgstr "Exemple" #: src/idioms/coercion-arguments.md:21 msgid "" @@ -475,6 +510,10 @@ msgid "" "a function argument versus using a `&str`, but the ideas apply as well to " "using `&Vec` versus using a `&[T]` or using a `&Box` versus a `&T`." msgstr "" +"Pour cet exemple, nous illustrerons certaines différences entre " +"l'utilisation de `&String` et de `&str`en argument d'une fonction, mais " +"cette idée s'appliquera aussi bien à l'utilisation de `&Vec` par rapport " +"à `&[T]` ou à celle de `&Box` par rapport à `&T`." #: src/idioms/coercion-arguments.md:25 msgid "" @@ -482,42 +521,45 @@ msgid "" "consecutive vowels. We don't need to own the string to determine this, so we " "will take a reference." msgstr "" +"Imaginons que nous voulons déterminer si un mot contiens trois voyelles " +"consécutives. Inutile de posséder la chaîne de caractère pour cela, donc " +"nous utilisons une référence." #: src/idioms/coercion-arguments.md:29 msgid "The code might look something like this:" -msgstr "" +msgstr "Le code pourrait ressembler à quelque chose comme ça :" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'a'" -msgstr "" +msgstr "'a'" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'e'" -msgstr "" +msgstr "'e'" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'i'" -msgstr "" +msgstr "'i'" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'o'" -msgstr "" +msgstr "'o'" #: src/idioms/coercion-arguments.md:36 src/idioms/coercion-arguments.md:96 msgid "'u'" -msgstr "" +msgstr "'u'" #: src/idioms/coercion-arguments.md:49 msgid "\"Ferris\"" -msgstr "" +msgstr "\"Ferris\"" #: src/idioms/coercion-arguments.md:50 msgid "\"Curious\"" -msgstr "" +msgstr "\"Curious\"" #: src/idioms/coercion-arguments.md:51 src/idioms/coercion-arguments.md:52 msgid "\"{}: {}\"" -msgstr "" +msgstr "\"{}: {}\"" #: src/idioms/coercion-arguments.md:54 msgid "" @@ -525,6 +567,9 @@ msgid "" " // println!(\"Ferris: {}\", three_vowels(\"Ferris\"));\n" " // println!(\"Curious: {}\", three_vowels(\"Curious\"));\n" msgstr "" +"// Cela fonctionne, mais les lignes suivantes provoqueraient une erreur :\r\n" +" // println!(\"Ferris: {}\", three_vowels(\"Ferris\"));\r\n" +" // println!(\"Curious: {}\", three_vowels(\"Curious\"));\r\n" #: src/idioms/coercion-arguments.md:60 msgid "" @@ -533,14 +578,18 @@ msgid "" "because a `&str` type will not coerce to a `&String` type. We can fix this " "by simply modifying the type for our argument." msgstr "" +"Cela fonctionne parce que nous passons le type `&String` en paramètre. Si on " +"décommente les deux dernières lignes en revanche, l'exemple provoquera une " +"erreur. C'est parce que `&str` ne peut pas être extrapolé en `&String`. Nous " +"pouvons réparer cela simplement en modifiant le type de notre argument." #: src/idioms/coercion-arguments.md:65 msgid "For instance, if we change our function declaration to:" -msgstr "" +msgstr "Par exemple, si on change la déclaration de notre fonction en :" #: src/idioms/coercion-arguments.md:71 msgid "then both versions will compile and print the same output." -msgstr "" +msgstr "alors les deux versions compilent et affichent la même chose." #: src/idioms/coercion-arguments.md:78 msgid "" @@ -550,6 +599,11 @@ msgid "" "ignoring this special example, you may still find that using `&str` will " "give you more flexibility than using a `&String`." msgstr "" +"Mais attendez, ce n'est pas tout ! L'histoire ne s'arrête pas là. Vous vous " +"dites probablement \"peu importe, je n'utiliserai jamais un `&'static str` " +"en entrée de toute manière\" (c'est ce que nous avons fait en utilisant " +"\"Ferris\"). Même si on laisse de côté cet exemple spécifique, vous verrez " +"qu'utiliser `&str` vous donnera plus de flexibilité que d'utiliser `&String`." #: src/idioms/coercion-arguments.md:84 msgid "" @@ -558,28 +612,35 @@ msgid "" "vowels. We probably should make use of the function we have already defined " "and simply feed in each word from the sentence." msgstr "" +"Prenons maintenant un exemple dans lequel on nous donne une phrase et où " +"nous devons déterminer si l'un des mots de cette phrase contient trois " +"voyelles consécutives. Nous devrions probablement nous servir de la fonction " +"que nous avons déjà définie et lui fournir simplement chaque mot de la " +"phrase." #: src/idioms/coercion-arguments.md:89 msgid "An example of this could look like this:" -msgstr "" +msgstr "Un exemple de solution pourrait ressembler à ça :" #: src/idioms/coercion-arguments.md:110 msgid "\"Once upon a time, there was a friendly curious crab named Ferris\"" -msgstr "" +msgstr "\"Once upon a time, there was a friendly curious crab named Ferris\"" #: src/idioms/coercion-arguments.md:111 msgid "' '" -msgstr "" +msgstr "' '" #: src/idioms/coercion-arguments.md:113 msgid "\"{word} has three consecutive vowels!\"" -msgstr "" +msgstr "\"{word} has three consecutive vowels!\"" #: src/idioms/coercion-arguments.md:119 msgid "" "Running this example using our function declared with an argument type " "`&str` will yield" msgstr "" +"Exécuter cet exemple en utilisant notre fonction déclarée avec un argument " +"de type `&str` nous donnera" #: src/idioms/coercion-arguments.md:126 msgid "" @@ -589,6 +650,11 @@ msgid "" "which is not implicit, whereas converting from `String` to `&str` is cheap " "and implicit." msgstr "" +"Par contre, cet exemple ne s'exécutera pas si notre fonction est déclarée " +"avec un argument de type `&String`. C'est parce qu'un _string slice_ a le " +"type `&str` et pas `&String`, il faudrait donc une allocation supplémentaire " +"pour le convertir en `&String` ce qui n'est pas implicite. La conversion de " +"`String` vers `&str` en revanche est rapide et implicite." #: src/idioms/coercion-arguments.md:132 src/idioms/ctor.md:101 #: src/idioms/default.md:58 src/idioms/deref.md:76 @@ -599,19 +665,21 @@ msgstr "" #: src/patterns/behavioural/newtype.md:94 src/patterns/behavioural/RAII.md:112 #: src/patterns/behavioural/strategy.md:178 #: src/patterns/behavioural/visitor.md:108 -#: src/patterns/creational/builder.md:109 src/patterns/creational/fold.md:109 +#: src/patterns/creational/builder.md:112 src/patterns/creational/fold.md:109 #: src/patterns/structural/small-crates.md:45 #: src/patterns/structural/unsafe-mods.md:33 #: src/anti_patterns/borrow_clone.md:65 src/anti_patterns/deny-warnings.md:101 #: src/anti_patterns/deref.md:124 src/functional/generics-type-classes.md:236 msgid "See also" -msgstr "" +msgstr "Voir aussi" #: src/idioms/coercion-arguments.md:134 msgid "" "[Rust Language Reference on Type Coercions](https://doc.rust-lang.org/" "reference/type-coercions.html)" msgstr "" +"[Extrapolation de déréférencement dans la Rust Language Reference](https://" +"doc.rust-lang.org/reference/type-coercions.html)" #: src/idioms/coercion-arguments.md:135 msgid "" @@ -620,16 +688,22 @@ msgid "" "hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html) by Herman " "J. Radtke III" msgstr "" +"Pour approfondir le sujet de la gestion des `String` et `&str`, vous pouvez " +"lire [cet article de 2015](https://web.archive.org/web/20201112023149/" +"https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html) " +"par Herman J. Radtke III (_en_)" #: src/idioms/coercion-arguments.md:138 msgid "" "[Steve Klabnik's Blogpost on 'When should I use String vs &str?'](https://" "archive.ph/LBpD0)" msgstr "" +"Billet de blog de Steve Klabnik : ['When should I use String vs &str?']" +"(https://archive.ph/LBpD0)" #: src/idioms/concat-format.md:1 msgid "Concatenating strings with `format!`" -msgstr "" +msgstr "Concaténer les chaînes de caractères avec `format!`" #: src/idioms/concat-format.md:5 msgid "" @@ -638,6 +712,11 @@ msgid "" "convenient to use `format!`, especially where there is a mix of literal and " "non-literal strings." msgstr "" +"Il est possible de construire des chaînes de caractères en utilisant `push` " +"et `push_str` sur un `String` mutable ou encore avec l'opérateur `+`. " +"Cependant, il est souvent plus pratique d'utiliser la macro `format!`, " +"surtout quand on mélange des chaînes de caractère littérales et non " +"littérales." #: src/idioms/concat-format.md:14 msgid "" @@ -647,14 +726,19 @@ msgid "" " // result.push('!');\n" " // result\n" msgstr "" +"//On pourraît construire le résultat manuellement.\n" +" // let mut result = \"Hello \".to_owned();\n" +" // result.push_str(name);\n" +" //result.push('!');\n" +" //result\n" #: src/idioms/concat-format.md:20 msgid "// But using format! is better.\n" -msgstr "" +msgstr "// Mais format! est un meilleur choix.\n" #: src/idioms/concat-format.md:21 msgid "\"Hello {name}!\"" -msgstr "" +msgstr "\"Hello {name}!\"" #: src/idioms/concat-format.md:25 src/idioms/deref.md:43 #: src/idioms/dtor-finally.md:46 src/idioms/mem-replace.md:91 @@ -668,17 +752,21 @@ msgstr "" #: src/patterns/creational/builder.md:68 #: src/patterns/structural/compose-structs.md:106 #: src/patterns/structural/small-crates.md:13 -#: src/patterns/structural/unsafe-mods.md:12 src/patterns/ffi/export.md:113 -#: src/patterns/ffi/wrappers.md:64 src/anti_patterns/deny-warnings.md:16 -#: src/anti_patterns/deref.md:69 src/functional/generics-type-classes.md:209 +#: src/patterns/structural/unsafe-mods.md:12 +#: src/patterns/structural/trait-for-bounds.md:96 +#: src/patterns/ffi/export.md:113 src/patterns/ffi/wrappers.md:64 +#: src/anti_patterns/deny-warnings.md:16 src/anti_patterns/deref.md:69 +#: src/functional/generics-type-classes.md:209 msgid "Advantages" -msgstr "" +msgstr "Avantages" #: src/idioms/concat-format.md:27 msgid "" "Using `format!` is usually the most succinct and readable way to combine " "strings." msgstr "" +"Utiliser `format!` est habituellement la manière la plus succincte et " +"lisible de combiner des chaînes de caractères." #: src/idioms/concat-format.md:30 src/idioms/deref.md:50 #: src/idioms/dtor-finally.md:51 src/idioms/mem-replace.md:95 @@ -690,14 +778,15 @@ msgstr "" #: src/idioms/return-consumed-arg-on-error.md:59 #: src/patterns/behavioural/newtype.md:66 #: src/patterns/behavioural/strategy.md:107 -#: src/patterns/creational/builder.md:76 +#: src/patterns/creational/builder.md:79 #: src/patterns/structural/compose-structs.md:111 #: src/patterns/structural/small-crates.md:22 -#: src/patterns/structural/unsafe-mods.md:18 src/patterns/ffi/export.md:236 -#: src/patterns/ffi/wrappers.md:70 src/anti_patterns/deref.md:81 -#: src/functional/generics-type-classes.md:220 +#: src/patterns/structural/unsafe-mods.md:18 +#: src/patterns/structural/trait-for-bounds.md:107 +#: src/patterns/ffi/export.md:236 src/patterns/ffi/wrappers.md:70 +#: src/anti_patterns/deref.md:81 src/functional/generics-type-classes.md:220 msgid "Disadvantages" -msgstr "" +msgstr "Inconvénients" #: src/idioms/concat-format.md:32 msgid "" @@ -705,10 +794,14 @@ msgid "" "`push` operations on a mutable string is usually the most efficient " "(especially if the string has been pre-allocated to the expected size)." msgstr "" +"Ce n'est généralement pas la façon la plus efficace de combiner des chaînes " +"de caractères : une série de `push` sur une chaîne mutable est généralement " +"plus efficient (surtout si la chaîne de caractère a été pré-allouée avec la " +"taille attendue)." #: src/idioms/ctor.md:1 msgid "Constructors" -msgstr "" +msgstr "Constructeurs" #: src/idioms/ctor.md:5 msgid "" @@ -717,6 +810,10 @@ msgid "" "stable/book/ch05-03-method-syntax.html#associated-functions) `new` to create " "an object:" msgstr "" +"Rust ne fournit pas de constructeur intégré directement au langage. La " +"convention est d'utiliser une [fonction associée](https://jimskapt.github.io/" +"rust-book-fr/ch05-03-method-syntax.html#les-fonctions-associ%C3%A9es) `new` " +"pour la création d'un objet:" #: src/idioms/ctor.md:10 msgid "" @@ -729,26 +826,39 @@ msgid "" "/// assert_eq!(42, s.value());\n" "/// ```\n" msgstr "" +"/// Temps en secondes.\r\n" +"///\r\n" +"/// # Exemple\r\n" +"///\r\n" +"/// ```\r\n" +"/// let s = Second::new(42);\r\n" +"/// assert_eq!(42, s.value());\r\n" +"/// ```\r\n" #: src/idioms/ctor.md:23 msgid "" "// Constructs a new instance of [`Second`].\n" " // Note this is an associated function - no self.\n" msgstr "" +"// Crée une nouvelle instance de [`Second`].\r\n" +" // Notez que c'est une fonction associée, elle ne prend pas self en " +"paramètre.\r\n" #: src/idioms/ctor.md:29 src/idioms/ctor.md:54 src/idioms/ctor.md:85 msgid "/// Returns the value in seconds.\n" -msgstr "" +msgstr "/// Renvoie la valeur en secondes.\r\n" #: src/idioms/ctor.md:36 msgid "Default Constructors" -msgstr "" +msgstr "Constructeurs par défaut" #: src/idioms/ctor.md:38 msgid "" "Rust supports default constructors with the [`Default`](https://doc.rust-" "lang.org/stable/std/default/trait.Default.html) trait:" msgstr "" +"Rust supporte les constructeurs par défaut _via_ le trait [`Default`]" +"(https://doc.rust-lang.org/stable/std/default/trait.Default.html):" #: src/idioms/ctor.md:41 src/idioms/ctor.md:71 msgid "" @@ -761,12 +871,22 @@ msgid "" "/// assert_eq!(0, s.value());\n" "/// ```\n" msgstr "" +"/// Temps en secondes.\r\n" +"///\r\n" +"/// # Exemple\r\n" +"///\r\n" +"/// ```\r\n" +"/// let s = Second::default();\r\n" +"/// assert_eq!(0, s.value());\r\n" +"/// ```\r\n" #: src/idioms/ctor.md:67 msgid "" "`Default` can also be derived if all types of all fields implement " "`Default`, like they do with `Second`:" msgstr "" +"`Default` peut aussi être dérivé si les types de tous les champs " +"implémentent `Default`, comme c'est le cas pour`Second`:" #: src/idioms/ctor.md:92 msgid "" @@ -776,6 +896,12 @@ msgid "" "constructor to take no arguments, then it should, even if it is functionally " "identical to default." msgstr "" +"**Note:** Il est habituel et attendu qu'un type implémente à la fois " +"`Default` et un constructeur `new` vide. `new` est la convention pour les " +"constructeurs en Rust et les utilisateurs s'attendent à ce que cette " +"fonction associée existe. S'il est raisonnable d'avoir un constructeur " +"basique sans argument alors il vaut mieux l'implémenter même s'il fonctionne " +"de façon identique à `default`." #: src/idioms/ctor.md:97 msgid "" @@ -784,18 +910,27 @@ msgid "" "prominently, any of the [`*or_default` functions in the standard library]" "(https://doc.rust-lang.org/stable/std/?search=or_default)." msgstr "" +"**Astuce:** L'avantage d'implémenter ou de dériver le trait `Default` est " +"que votre type peut alors être utilisé partout où une implémentation de " +"`Default` est requise, particulièrement pour [les fonctions `*or_default` de " +"la librairie standard](https://doc.rust-lang.org/stable/std/?" +"search=or_default)." #: src/idioms/ctor.md:103 msgid "" "The [default idiom](default.md) for a more in-depth description of the " "`Default` trait." msgstr "" +"L'[idiome default](default.md) pour une description plus approfondie du " +"trait `Default`." #: src/idioms/ctor.md:106 msgid "" "The [builder pattern](../patterns/creational/builder.md) for constructing " "objects where there are multiple configurations." msgstr "" +"Le [patron de conception](../patterns/creational/builder.md) pour la " +"construction d'objets avec plusieurs configurations." #: src/idioms/ctor.md:109 msgid "" @@ -803,10 +938,13 @@ msgid "" "interoperability.html#types-eagerly-implement-common-traits-c-common-traits) " "for implementing both, `Default` and `new`." msgstr "" +"[API Guidelines/C-COMMON-TRAITS](https://rust-lang.github.io/api-guidelines/" +"interoperability.html#types-eagerly-implement-common-traits-c-common-traits) " +"pour l'implémentation à la fois de `Default` et de `new`." #: src/idioms/default.md:1 msgid "The `Default` Trait" -msgstr "" +msgstr "Le trait `Default`" #: src/idioms/default.md:5 msgid "" @@ -819,6 +957,15 @@ msgid "" "enum.Option.html#method.unwrap_or_default)). Notably, some containers " "already implement it where applicable." msgstr "" +"De nombreux types en Rust ont un [constructeur](ctor.md). Cependant c'est " +"_specifique_ à chaque type, ce qui implique que Rust ne peut pas définir une " +"catégorie \"tous ce qui a une méthode `new()`\". Le trait [`Default`]" +"(https://doc.rust-lang.org/stable/std/default/trait.Default.html) a été " +"conçu pour ça et peut être utilisé avec les conteneurs et d'autres types " +"génériques (voir par exemple [`Option::unwrap_or_default()`](https://" +"doc.rust-lang.org/stable/std/option/" +"enum.Option.html#method.unwrap_or_default)). Certains conteneurs " +"implémentent déjà cette fonctionnalité lorsque c'est possible." #: src/idioms/default.md:11 msgid "" @@ -827,6 +974,11 @@ msgid "" "`#[derive(Default)]` for structs whose fields all implement it, so the more " "types implement `Default`, the more useful it becomes." msgstr "" +"Non seulement les conteneurs contenant un seul élément comme `Cow`, `Box` ou " +"`Arc` implémentent `Default` lorsqu'il contiennent un type qui l'implémente, " +"mais on peut également utiliser `#[Derive(Default)]` sur une structure dés " +"lors que tous ses champs implémentent `Default`, ce qui signifie que plus ce " +"trait est implémenté par de nombreux types, plus il devient utile." #: src/idioms/default.md:16 msgid "" @@ -834,73 +986,87 @@ msgid "" "`default()` method does not. There can even be multiple constructors with " "different names, but there can only be one `Default` implementation per type." msgstr "" +"D'un autre côté, si un constructeur peut prendre plusieurs arguments, ce " +"n'est pas le cas de la méthode `default()`. Il peut même y avoir plusieurs " +"constructeurs avec des noms différents, mais il ne peut y avoir qu'une seule " +"implémentation de `Default` par type." #: src/idioms/default.md:24 msgid "// note that we can simply auto-derive Default here.\n" msgstr "" +"// notez qu'on peut se contenter de dériver automatiquement Default ici.\n" #: src/idioms/default.md:28 msgid "// Option defaults to None\n" -msgstr "" +msgstr "// Par défaut, une Option est initialisée comme None\n" #: src/idioms/default.md:30 msgid "// Vecs default to empty vector\n" -msgstr "" +msgstr "// un Vec est initialisé comme un vecteur vide\n" #: src/idioms/default.md:32 msgid "// Duration defaults to zero time\n" -msgstr "" +msgstr "// une Duration est initialisée à zéro\n" #: src/idioms/default.md:34 msgid "// bool defaults to false\n" -msgstr "" +msgstr "// un booléen est initialisé à false\n" #: src/idioms/default.md:39 msgid "// add setters here\n" -msgstr "" +msgstr "// ajoutez les setters ici\n" #: src/idioms/default.md:43 msgid "// construct a new instance with default values\n" -msgstr "" +msgstr "// construit une nouvelle instance avec les valeurs par défaut\n" #: src/idioms/default.md:45 msgid "// do something with conf here\n" -msgstr "" +msgstr "// on modifie conf ici\n" #: src/idioms/default.md:47 msgid "\"conf = {conf:#?}\"" -msgstr "" +msgstr "\"conf = {conf:#?}\"" #: src/idioms/default.md:49 msgid "" "// partial initialization with default values, creates the same instance\n" msgstr "" +"// une initialisation partielle avec des valeurs par défaut crée la même " +"instance\n" #: src/idioms/default.md:60 msgid "" "The [constructor](ctor.md) idiom is another way to generate instances that " "may or may not be \"default\"" msgstr "" +"L'idiome [constructeur](ctor.md) est une autre manière de générer des " +"instances qui peuvent ou non avoir des valeurs par défaut" #: src/idioms/default.md:62 msgid "" "The [`Default`](https://doc.rust-lang.org/stable/std/default/" "trait.Default.html) documentation (scroll down for the list of implementors)" msgstr "" +"La documentation du trait [`Default`](https://doc.rust-lang.org/stable/std/" +"default/trait.Default.html) (la liste des implémentations disponibles est au " +"bas de la page)" #: src/idioms/default.md:63 msgid "" "[`Option::unwrap_or_default()`](https://doc.rust-lang.org/stable/std/option/" "enum.Option.html#method.unwrap_or_default)" msgstr "" +"[`Option::unwrap_or_default()`](https://doc.rust-lang.org/stable/std/option/" +"enum.Option.html#method.unwrap_or_default)" #: src/idioms/default.md:64 msgid "[`derive(new)`](https://crates.io/crates/derive-new/)" -msgstr "" +msgstr "[`derive(new)`](https://crates.io/crates/derive-new/)" #: src/idioms/deref.md:1 msgid "Collections are smart pointers" -msgstr "" +msgstr "Les collections sont des pointeurs intelligents" #: src/idioms/deref.md:5 msgid "" @@ -908,12 +1074,16 @@ msgid "" "to treat collections like smart pointers, offering owning and borrowed views " "of data." msgstr "" +"On peut utiliser le trait [`Deref`](https://doc.rust-lang.org/std/ops/" +"trait.Deref.html) pour traiter les collections comme des pointeurs " +"intelligents, ce qui permet de visualiser les données avec ou sans " +"possession." #: src/idioms/deref.md:16 src/idioms/deref.md:23 #: src/patterns/behavioural/RAII.md:29 src/patterns/behavioural/RAII.md:41 #: src/patterns/behavioural/RAII.md:100 src/anti_patterns/deref.md:35 msgid "//..\n" -msgstr "" +msgstr "//..\n" #: src/idioms/deref.md:28 msgid "" @@ -923,10 +1093,16 @@ msgid "" "dereferencing searches. Most methods you might expect to be implemented for " "`Vec`s are instead implemented for slices." msgstr "" +"Un `Vec` est une collection de `T` avec possession, alors qu'un slice " +"(`&[T]`) est une collection de `T` empruntée. En implémentant `Deref` pour " +"`Vec`, on permet un déréférencement implicite de `&Vec` vers `&[T]` et " +"cette relation peut être utilisée pour l'auto-déréférencement. La plupart " +"des méthodes qu'on s'attend à trouver implémentées pour `Vec` sont en fait " +"implémentées pour les slices." #: src/idioms/deref.md:34 msgid "Also `String` and `&str` have a similar relation." -msgstr "" +msgstr "`String` et `&str` ont une relation similaire." #: src/idioms/deref.md:36 src/idioms/dtor-finally.md:36 #: src/idioms/mem-replace.md:63 src/idioms/on-stack-dyn-dispatch.md:32 @@ -941,7 +1117,7 @@ msgstr "" #: src/patterns/structural/compose-structs.md:100 src/patterns/ffi/export.md:16 #: src/anti_patterns/borrow_clone.md:30 msgid "Motivation" -msgstr "" +msgstr "Motivation" #: src/idioms/deref.md:38 msgid "" @@ -950,16 +1126,24 @@ msgid "" "experience. When implementing a data structure that owns its data, offering " "a borrowed view of that data allows for more flexible APIs." msgstr "" +"La propriété et l'emprunt sont des aspects essentiels du langage Rust. Les " +"structures de données doivent respecter cette sémantique pour fournir une " +"bonne expérience utilisateur. Lorsqu'on implémente une structure de données " +"qui possède ses données, offrir une vue empruntée pour ces données permet de " +"faire des APIs plus flexibles." #: src/idioms/deref.md:45 msgid "" "Most methods can be implemented only for the borrowed view, they are then " "implicitly available for the owning view." msgstr "" +"La plupart des méthodes peuvent être implémentées seulement pour la vue " +"empruntée et seront ensuite implicitement disponibles pour la vue " +"propriétaire." #: src/idioms/deref.md:48 msgid "Gives clients a choice between borrowing or taking ownership of data." -msgstr "" +msgstr "On laisse le choix d'emprunter les données ou d'en prendre possession." #: src/idioms/deref.md:52 msgid "" @@ -968,6 +1152,11 @@ msgid "" "using this pattern can get complex (see the `Borrow` and `AsRef` traits, " "etc.)." msgstr "" +"Les méthodes et les traits qui sont seulement disponible _via_ un " +"déréférencement ne sont pas pris en compte lors de la vérification des " +"limites, ce qui peut rendre complexe l'utilisation de types génériques avec " +"des structures de données lorsqu'on utilise ce pattern (voir les traits " +"`Borrow` et `AsRef`, etc.)" #: src/idioms/deref.md:56 src/idioms/dtor-finally.md:66 #: src/idioms/mem-replace.md:105 src/idioms/on-stack-dyn-dispatch.md:66 @@ -976,12 +1165,12 @@ msgstr "" #: src/patterns/behavioural/interpreter.md:105 #: src/patterns/behavioural/newtype.md:74 src/patterns/behavioural/RAII.md:84 #: src/patterns/behavioural/strategy.md:113 -#: src/patterns/behavioural/visitor.md:81 src/patterns/creational/builder.md:81 +#: src/patterns/behavioural/visitor.md:81 src/patterns/creational/builder.md:84 #: src/patterns/creational/fold.md:85 #: src/patterns/structural/compose-structs.md:117 #: src/anti_patterns/deref.md:102 msgid "Discussion" -msgstr "" +msgstr "Discussion" #: src/idioms/deref.md:58 msgid "" @@ -994,6 +1183,15 @@ msgid "" "If a collection owns its data, it is usually useful to provide a view of the " "data as borrowed so that it can be referenced multiple times." msgstr "" +"Un pointeur intelligent pointe vers un seul objet là où une collection " +"pointe vers plusieurs. Du point de vue du système de types, il y a peu de " +"différence entre les deux. Une collection possède ses données si le seul " +"moyen d'accéder à un élément est _via_ la collection et si la collection est " +"responsable de la suppression des données (même en cas de propriété " +"partagée, il peut être approprié d'avoir une vue empruntée à disposition). " +"Si une collection possède ses données, il est généralement utile de fournir " +"une vue où les données sont empruntées pour qu'elles puissent être " +"référencées plusieurs fois." #: src/idioms/deref.md:67 msgid "" @@ -1003,26 +1201,37 @@ msgid "" "`Foo` can implement `Deref>` where `Bar` is a dynamically " "sized type and `&Bar` is a borrowed view of the data in `Foo`." msgstr "" +"D'autres pointeurs intelligents (par exemple `Foo`) implémentent " +"`Deref`. Cependant, les collections sont habituellement " +"déréférencées vers un type personnalisé. `[T]` et `str` sont supportées par " +"le langage, mais dans le cas général ce n'est pas nécessaire. `Foo` peut " +"implémenter `Deref>` où `Bar` est un type avec une taille " +"dynamique et `&Bar` est une vue empruntée des données contenues dans " +"`Foo`." #: src/idioms/deref.md:73 msgid "" "Commonly, ordered collections will implement `Index` for `Range`s to provide " "slicing syntax. The target will be the borrowed view." msgstr "" +"En général, les collections ordonnées vont implémenter `Index` pour fournir " +"une syntaxe de slice avec `Range` où la cible sera la vue empruntée." #: src/idioms/deref.md:78 msgid "[Deref polymorphism anti-pattern](../anti_patterns/deref.md)." -msgstr "" +msgstr "Anti-patron : [polymorphisme avec Deref](../anti_patterns/deref.md)" #: src/idioms/deref.md:79 src/anti_patterns/deref.md:130 msgid "" "[Documentation for `Deref` trait](https://doc.rust-lang.org/std/ops/" "trait.Deref.html)." msgstr "" +"[Documentation du trait `Deref`](https://doc.rust-lang.org/std/ops/" +"trait.Deref.html)." #: src/idioms/dtor-finally.md:1 msgid "Finalisation in destructors" -msgstr "" +msgstr "Finalisation dans les destructeurs" #: src/idioms/dtor-finally.md:5 msgid "" @@ -1030,34 +1239,42 @@ msgid "" "executed no matter how a function is exited. Instead, an object's destructor " "can be used to run code that must be run before exit." msgstr "" +"Rust n'a pas d'équivalent pour les blocs `finally` (du code qui s'exécute " +"peu importe la façon dont une fonction se termine). Pour remplacer cette " +"fonctionnalité, on peut utiliser le destructeur d'un objet pour exécuter du " +"code à la sortie de la fonction." #: src/idioms/dtor-finally.md:13 msgid "// some code\n" -msgstr "" +msgstr "// du code\n" #: src/idioms/dtor-finally.md:17 msgid "// These don't need to be defined inside the function.\n" msgstr "" +"// Ce qui suit n'a pas besoin d'être défini à l'intérieur de la fonction.\n" #: src/idioms/dtor-finally.md:20 msgid "// Implement a destructor for Foo.\n" -msgstr "" +msgstr "// On implémente un destructeur pour Foo.\n" #: src/idioms/dtor-finally.md:23 msgid "\"exit\"" -msgstr "" +msgstr "\"exit\"" #: src/idioms/dtor-finally.md:27 -msgid "// The dtor of _exit will run however the function `bar` is exited.\n" +msgid "" +"// The destructor of _exit will run however the function `bar` is exited.\n" msgstr "" +"// Le destructeur de _exit s'exécutera peu importe la façon dont la fonction " +"`bar` se termine.\n" #: src/idioms/dtor-finally.md:29 msgid "// Implicit return with `?` operator.\n" -msgstr "" +msgstr "// Retour implicite avec l'opérateur `?`\n" #: src/idioms/dtor-finally.md:31 msgid "// Normal return.\n" -msgstr "" +msgstr "// Retour classique.\n" #: src/idioms/dtor-finally.md:38 msgid "" @@ -1069,12 +1286,25 @@ msgid "" "has `finally`), there is no way to schedule code to run in both the normal " "and exceptional cases. Panicking will also exit a function early." msgstr "" +"Si une fonction a plusieurs points de sortie possible, il devient compliqué " +"d'exécuter du code à la sortie de la fonction et la répétition du même code " +"à des endroits différents favorise l'apparition d'erreurs. C'est " +"particulièrement vrai lorsque le retour est implicite à cause d'une macro. " +"L'opérateur `?` est un cas classique : si le résultat est `Err`, ce résultat " +"est renvoyé et l'exécution s'arrête, alors que si le résultat est `Ok`, " +"l'exécution continue. `?` est utilisé comme un mécanisme de gestion des " +"exceptions, mais contrairement à Java (qui a le mot-clef `finally`), Rust ne " +"propose pas de solution pour prévoir l'exécution d'un même bloc de code dans " +"le cas normal et en cas d'exception. Une panique peut également provoquer " +"l'arrêt anticipé de la fonction." #: src/idioms/dtor-finally.md:48 msgid "" "Code in destructors will (nearly) always be run - copes with panics, early " "returns, etc." msgstr "" +"Le code dans un destructeur sera (presque) toujours exécuté. Il gère la " +"panique, les retours anticipés, etc." #: src/idioms/dtor-finally.md:53 msgid "" @@ -1084,6 +1314,11 @@ msgid "" "thread. Therefore, destructors cannot be relied on as finalizers where it is " "absolutely essential that finalisation happens." msgstr "" +"Il n'est pas garanti qu'un destructeur s'exécutera, notamment dans le cas " +"d'une boucle infinie ou d'un crash avant la fin d'une fonction. Les " +"destructeurs ne seront pas exécutés non plus en cas de panique dans une " +"thread déjà en état de panique. Dans les cas où la finalisation est " +"absolument nécessaire, on ne peut donc pas s'appuyer sur les destructeurs." #: src/idioms/dtor-finally.md:59 msgid "" @@ -1091,12 +1326,17 @@ msgid "" "function gives no clear indication of destructors to be run on exit. This " "can make debugging tricky." msgstr "" +"Ce pattern implique d’écrire du code difficile à trouver car en lisant une " +"fonction on n'a aucune indication claire de quels destructeurs seront " +"appelés à la fin de celle-ci. Cela peut rendre le débogage assez compliqué." #: src/idioms/dtor-finally.md:63 msgid "" "Requiring an object and `Drop` impl just for finalisation is heavy on " "boilerplate." msgstr "" +"Le besoin de créer un objet avec une implémentation de Drop juste pour gérer " +"la finalisation peut peser lourd dans un code standard." #: src/idioms/dtor-finally.md:68 msgid "" @@ -1107,6 +1347,13 @@ msgid "" "finalizer can be kept alive beyond the lifetime of the function. For similar " "reasons, the finalizer should not be moved or returned." msgstr "" +"Il y a quelques subtilités sur le stockage de l’objet qu’on utilise comme " +"finalizer. Il doit être gardé en vie jusqu’à la fin de la fonction et être " +"détruit à ce moment là. Cet objet doit toujours être une valeur ou bien un " +"pointeur à propriétaire unique (par exemple Box). Si un pointeur " +"partagé (comme Rc) est utilisé, il pourrait être gardé en vie après la fin " +"de la fonction. Pour des raisons similaires, le finalizer ne devrait jamais " +"être déplacé ou renvoyé." #: src/idioms/dtor-finally.md:75 msgid "" @@ -1117,6 +1364,12 @@ msgid "" "do not call the variable `_` with no suffix - in that case it will be " "destroyed immediately." msgstr "" +"Le finalizer doit être assigné à une variable, sinon il serait détruit " +"immédiatement et pas lorsqu’il sort de la portée. Si la variable n’est " +"utilisée que comme finalizer, son nom doit commencer par _ pour éviter que " +"le compilateur ne nous avertisse que cette variable n’est jamais utilisée. " +"Attention cependant à ne pas l’appeler simplement _ sans suffixe, car dans " +"ce cas elle serait détruite immédiatement." #: src/idioms/dtor-finally.md:81 msgid "" @@ -1126,6 +1379,12 @@ msgid "" "object in each stack frame. So, destructors get called even if the panic " "happens in a function being called." msgstr "" +"En Rust, les destructeurs sont exécutés quand un objet devient hors de " +"portée. Cela se produit lorsqu’on atteint la fin du bloc de code, lorsqu’il " +"y a un retour anticipé ou lorsque le programme panique. En cas de panique, " +"Rust déroule la pile d’exécution et exécute les destructeurs de chaque objet " +"situé dans chaque bloc mémoire de la pile. Ainsi, les destructeurs seront " +"appelés même si la panique se produit pendant l’appel d’une fonction." #: src/idioms/dtor-finally.md:87 msgid "" @@ -1135,14 +1394,22 @@ msgid "" "means that you must take extra care in your destructors not to panic, since " "it could leave resources in an unexpected state." msgstr "" +"Si un destructeur panique pendant le dépilage, il n’y a pas de bonne chose à " +"faire alors Rust stoppe la thread immédiatement sans exécuter les " +"destructeurs suivants. Cela signifie que l’exécution d’un destructeur n’est " +"pas absolument garantie. Cela signifie également qu’il faut être très " +"précautionneux en écrivant un destructeur, car s’il panique certaines " +"ressources pourraient être laissées dans un état inattendu." #: src/idioms/dtor-finally.md:95 msgid "[RAII guards](../patterns/behavioural/RAII.md)." -msgstr "" +msgstr "[RAII](../patterns/behavioural/RAII.md)." #: src/idioms/mem-replace.md:1 msgid "`mem::{take(_), replace(_)}` to keep owned values in changed enums" msgstr "" +"Garder les valeurs lors d'un changement d'enum avec `mem::{take(_), " +"replace(_)}`" #: src/idioms/mem-replace.md:5 msgid "" @@ -1150,10 +1417,14 @@ msgid "" "String, x: u8 }` and `B { name: String }`. Now we want to change `MyEnum::A` " "to a `B` if `x` is zero, while keeping `MyEnum::B` intact." msgstr "" +"Disons qu'on a une enum avec (au moins) deux variants, `A { name: String, x: " +"u8 }` et `B { name: String }`. On souhaite, en partant d'une référence " +"mutable `&mut MyEnum`, transformer un `MyEnum::A` en `B` si jamais `x` vaut " +"zéro, en gardant `MyEnum::B` intact." #: src/idioms/mem-replace.md:9 msgid "We can do this without cloning the `name`." -msgstr "" +msgstr "On peut faire cela sans cloner le champ `name`." #: src/idioms/mem-replace.md:23 msgid "" @@ -1162,16 +1433,21 @@ msgid "" " // Then, construct the new enum variant (which will\n" " // be assigned to `*e`).\n" msgstr "" +"// Cela prend notre `name` et le remplace par un String vide\n" +" // (notez que les chaînes de caractères vides ne sont pas alloués).\n" +" // puis construit le nouveau variant (qui sera assigné à `*e`).\n" #: src/idioms/mem-replace.md:34 msgid "This also works with more variants:" -msgstr "" +msgstr "Cela marche également si on a plus de variants :" #: src/idioms/mem-replace.md:49 msgid "" "// 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" msgstr "" +"// Les règles de possession ne permettent pas de prendre possession\n" +" // de `name` depuis une référence mutable, à moins de le remplacer\n" #: src/idioms/mem-replace.md:65 msgid "" @@ -1181,6 +1457,11 @@ msgid "" "look at its parts to decide what to do next. In the second phase we may " "conditionally change the value (as in the example above)." msgstr "" +"Lorsqu'on travaille avec des enums, on peut vouloir changer la valeur d'un " +"enum en place, par exemple pour la remplacer par un autre variant. C'est " +"généralement fait en deux étapes pour satisfaire le vérificateur d'emprunt. " +"D'abord, on observe la valeur existante et on décide quoi faire, ensuite on " +"peut conditionnellement changer la valeur (comme dans l'exemple précédent)." #: src/idioms/mem-replace.md:71 msgid "" @@ -1191,6 +1472,13 @@ msgid "" "Anyway, we can avoid the extra allocation by changing `e` with only a " "mutable borrow." msgstr "" +"Le vérificateur d'emprunt ne nous laissera pas sortir `name` de l'enum " +"(parce qu'il faut bien que _quelque chose_ soit là). Bien sûr, on pourrait " +"utiliser `.clone()` pour cloner `name` et mettre le clone dans notre " +"`MyEnum::B`, mais ça serait un exemple de l'anti-patron [Cloner pour " +"satisfaire le vérificateur d'emprunt](../anti_patterns/borrow_clone.md). En " +"revanche, nous pouvons éviter une allocation supplémentaire en changeant `e` " +"à partir d'une simple référence mutable." #: src/idioms/mem-replace.md:78 msgid "" @@ -1199,6 +1487,10 @@ msgid "" "empty `String`, which does not need to allocate. As a result, we get the " "original `name` _as an owned value_. We can then wrap this in another enum." msgstr "" +"`mem::take` nous permet de récupérer la valeur en la remplaçant pas la " +"valeur par défaut. Pour `String`, la valeur par défaut est une chaîne de " +"caractères vide, qui n'a donc pas besoin d'être allouée. Nous obtenons donc " +"le `name` original en tant que valeur _possédée_." #: src/idioms/mem-replace.md:83 msgid "" @@ -1206,6 +1498,9 @@ msgid "" "replace the value with. An equivalent to our `mem::take` line would be " "`mem::replace(name, String::new())`." msgstr "" +"**NOTE :** `mem::replace` est très similaire, mais il nous permet de " +"spécifier par quoi remplacer la valeur. Un équivalent de notre `mem::take` " +"utilisé plus haut serait `mem::replace(name, String::new())`." #: src/idioms/mem-replace.md:87 msgid "" @@ -1213,11 +1508,17 @@ msgid "" "value with a `None`, `Option`’s `take()` method provides a shorter and more " "idiomatic alternative." msgstr "" +"Notez cependant que si on utilise une `Option` dont on veut remplacer la " +"valeur par `None`, la fonction `take()` de `Option` est une alternative plus " +"simple et plus idiomatique." +# "Look ma" donne littéralement "Regarde m'man !". Le ton de cette phrase détonne bizarrement au milieu du reste, c'est peut-être une référence que je ne connais pas (à Indiana Jones ? je ne me souviens plus du tout de ces films). J'ai essayé d'adoucir le côté bizarre que je trouvais à cette phrase, mais je ne comprends pas trop ce que l'auteur a voulu faire ici. #: src/idioms/mem-replace.md:93 msgid "" "Look ma, no allocation! Also you may feel like Indiana Jones while doing it." msgstr "" +"Et hop, aucune allocation ! Vous risquez peut-être aussi de vous prendre " +"pour Indiana Jones en utilisant ce pattern." #: src/idioms/mem-replace.md:97 msgid "" @@ -1226,6 +1527,11 @@ msgid "" "resulting in reduced performance as opposed to what you'd do in unsafe " "languages." msgstr "" +"Cette méthode peut devenir un peu trop verbeuse. Quelques erreurs répétées " +"vous feront détester le vérificateur d'emprunt. De plus, le compilateur peut " +"ne pas réussir à bien optimiser le double stockage, ce qui peut réduire les " +"performances par rapport à ce que vous auriez fait avec un langage qui ne " +"vérifie pas la sûreté des références." #: src/idioms/mem-replace.md:101 msgid "" @@ -1233,6 +1539,9 @@ msgid "" "(./default.md). However, if the type you're working with doesn't implement " "this, you can instead use `mem::replace`." msgstr "" +"Le type que vous souhaitez prendre doit également implémenter [le trait " +"`Default`](./default.md). Cependant, si ce n'est pas le cas, vous pouvez " +"toujours utiliser `mem::replace`." #: src/idioms/mem-replace.md:107 msgid "" @@ -1241,6 +1550,11 @@ msgid "" "in other low-level languages like C you'd simply alias the pointer and fix " "things later." msgstr "" +"Cette pratique n'a d'intérêt qu'en Rust. Dans un langage avec un ramasse-" +"miette, vous prendriez la référence vers la valeur par défaut (et c'est le " +"ramasse-miettes qui garderait une trace des références), tandis que dans " +"d'autres langages bas niveaux comme C, vous feriez un simple alias vers le " +"pointeur et vous arrangeriez les choses plus tard." #: src/idioms/mem-replace.md:112 msgid "" @@ -1248,12 +1562,19 @@ msgid "" "value may only have one owner, so to take it out, we need to put something " "back in – like Indiana Jones, replacing the artifact with a bag of sand." msgstr "" +"Cependant en Rust, cela demande un peu plus de travail. Une valeur ne peut " +"avoir qu'un seul propriétaire donc pour la récupérer il faut mettre quelque " +"chose à sa place. Comme Indiana Jones, qui remplace l'artéfact par un sac de " +"sable." #: src/idioms/mem-replace.md:118 msgid "" "This gets rid of the [Clone to satisfy the borrow checker](../anti_patterns/" "borrow_clone.md) anti-pattern in a specific case." msgstr "" +"Ce pattern permet de se débarrasser de l'anti-patron [Cloner pour satisfaire " +"le vérificateur d'emprunt](../anti_patterns/borrow_clone.md) dans un cas " +"spécifique." #: src/idioms/on-stack-dyn-dispatch.md:5 msgid "" @@ -1262,21 +1583,26 @@ msgid "" "the lifetime as necessary, we can use deferred conditional initialization, " "as seen below:" msgstr "" +"Il est possible de choisir dynamiquement entre plusieurs valeurs lors de " +"l'exécution. Cependant, pour cela, il faut déclarer plusieurs variables pour " +"les lier à des objets de type différent. Pour étendre la durée de vie autant " +"que nécessaire, on peut utiliser l'initialisation conditionnelle différée " +"comme ci-dessous :" #: src/idioms/on-stack-dyn-dispatch.md:17 #: src/idioms/on-stack-dyn-dispatch.md:20 #: src/idioms/on-stack-dyn-dispatch.md:56 msgid "\"-\"" -msgstr "" +msgstr "\"-\"" #: src/idioms/on-stack-dyn-dispatch.md:18 msgid "// We need to describe the type to get dynamic dispatch.\n" -msgstr "" +msgstr "// Il faut décrire le type pour avoir une affectation dynamique.\n" #: src/idioms/on-stack-dyn-dispatch.md:25 #: src/idioms/on-stack-dyn-dispatch.md:60 msgid "// Read from `readable` here.\n" -msgstr "" +msgstr "// On peut lire depuis `readable`\n" #: src/idioms/on-stack-dyn-dispatch.md:34 msgid "" @@ -1286,12 +1612,20 @@ msgid "" "places where performance is not of the essence, thus costing compile time " "and cache usage." msgstr "" +"Rust monomorphise le code par défaut. Cela signifie qu'une copie du code " +"sera générée pour chaque type avec lequel il est utilisé et chaque copie " +"sera optimisée indépendamment. Bien que cela permette d'obtenir du code " +"rapide à l'exécution, lorsque la performance n'est pas l'enjeu principal, la " +"monomorphisation crée une grande quantité de code avec un impact sur le " +"temps de compilation et l'utilisation du cache." #: src/idioms/on-stack-dyn-dispatch.md:40 msgid "" "Luckily, Rust allows us to use dynamic dispatch, but we have to explicitly " "ask for it." msgstr "" +"Heureusement, Rust nous permet d'utiliser l'affectation dynamique, mais il " +"faut la demander explicitement." #: src/idioms/on-stack-dyn-dispatch.md:45 msgid "" @@ -1299,6 +1633,9 @@ msgid "" "initialize something we won't use later, nor do we need to monomorphize the " "whole code that follows to work with both `File` or `Stdin`." msgstr "" +"Pas besoin d'allouer quoi que ce soit sur le tas. Pas besoin non plus " +"d'initialiser quelque chose qui ne sera pas utilisé plus tard, ni de " +"monomorphiser tout le code qui suit pour travailler avec `File` ou `Stdin`." #: src/idioms/on-stack-dyn-dispatch.md:51 msgid "" @@ -1306,14 +1643,17 @@ msgid "" "initialization, which made up more moving parts than the `Box`\\-based " "version:" msgstr "" +"Avant la version 1.79.0 de Rust, pour utiliser l'initialisation différée, il " +"fallait deux assignations `let`, ce qui donnait plus de parties changeantes " +"que la version basée sur `Box` :" #: src/idioms/on-stack-dyn-dispatch.md:55 msgid "// We still need to ascribe the type for dynamic dispatch.\n" -msgstr "" +msgstr "// Il faut toujours attribuer le type pour l'allocation dynamique.\n" #: src/idioms/on-stack-dyn-dispatch.md:64 msgid "Luckily, this disadvantage is now gone. Yay!" -msgstr "" +msgstr "Heureusement pour nous, ce désavantage a désormais disparu. Youpi !" #: src/idioms/on-stack-dyn-dispatch.md:68 msgid "" @@ -1321,6 +1661,9 @@ msgid "" "temporary values within `&` or `&mut` as long as possible within the scope " "of the function." msgstr "" +"Depuis Rust 1.79.0, le compilateur étendra automatiquement la durée de vie " +"des valeurs temporaires référencées par `&` ou `&mut` aussi loin que " +"possible dans la portée de la fonction." #: src/idioms/on-stack-dyn-dispatch.md:72 msgid "" @@ -1328,6 +1671,10 @@ msgid "" "placing the contents into some `let` binding (which would have been needed " "for deferred initialization, which was the solution used before that change)." msgstr "" +"Cela signifie qu'on peut simplement utiliser une valeur derrière `&mut` ici " +"sans se préoccuper de placer le contenu dans une assignation `let` (qui " +"aurait été nécessaire pour l'initialisation différée, la solution utilisée " +"avant ce changement)." #: src/idioms/on-stack-dyn-dispatch.md:76 msgid "" @@ -1335,12 +1682,19 @@ msgid "" "compiler knows the size of each value and each borrowed value outlives all " "references borrowed from it." msgstr "" +"On a toujours une place pour chaque valeur (même si cette place est " +"temporaire), le compilateur connaît la taille de chaque valeur et chaque " +"valeur empruntée vis plus longtemps que toutes les références pointant sur " +"elle." #: src/idioms/on-stack-dyn-dispatch.md:82 msgid "" "[Finalisation in destructors](dtor-finally.md) and [RAII guards](../patterns/" "behavioural/RAII.md) can benefit from tight control over lifetimes." msgstr "" +"[Finalisation dans les destructeurs](dtor-finally.md) et [RAII](../patterns/" +"behavioural/RAII.md) peuvent bénéficier d'un contrôle plus strict sur les " +"durées de vie." #: src/idioms/on-stack-dyn-dispatch.md:85 msgid "" @@ -1349,10 +1703,14 @@ msgid "" "doc.rust-lang.org/std/option/enum.Option.html#method.as_ref) method to get " "an optional reference." msgstr "" +"Pour remplir conditionnellement une `Option<&T>` avec une référence (mutable " +"ou non), on peut initialiser une `Option` directement et utiliser sa " +"méthode [`.as_ref()`](https://doc.rust-lang.org/std/option/" +"enum.Option.html#method.as_ref) pour avoir une référence optionnelle." #: src/idioms/ffi/intro.md:1 msgid "FFI Idioms" -msgstr "" +msgstr "Idiomes FFI" #: src/idioms/ffi/intro.md:3 msgid "" @@ -1360,28 +1718,40 @@ msgid "" "idioms here that can act as pointers, and avoid traps for inexperienced " "users of `unsafe` Rust." msgstr "" +"L'écriture de Foreign Function Interface (FFI) mériterait un cours à part " +"entière. Il y a cependant quelques bonnes pratiques qui peuvent servir à " +"éviter les pièges les plus fréquents pour les utilisateurs inexpérimentés du " +"Rust non sécurisé (`unsafe`)." #: src/idioms/ffi/intro.md:7 msgid "This section contains idioms that may be useful when doing FFI." msgstr "" +"Cette section contiens des idiomes qui peuvent être utiles pour écrire des " +"FFI." #: src/idioms/ffi/intro.md:9 msgid "" "[Idiomatic Errors](./errors.md) - Error handling with integer codes and " "sentinel return values (such as `NULL` pointers)" msgstr "" +"[Gestion des erreurs](./errors.md) - Gestion des erreurs représentées par " +"des integers ou des valeurs spécifiques (comme un pointeur `NULL`)" #: src/idioms/ffi/intro.md:12 msgid "[Accepting Strings](./accepting-strings.md) with minimal unsafe code" msgstr "" +"[Recevoir des chaînes de caractères](./accepting-strings.md) avec le moins " +"de code non sécurisé possible" #: src/idioms/ffi/intro.md:14 msgid "[Passing Strings](./passing-strings.md) to FFI functions" msgstr "" +"[Envoyer des chaînes de caractères](./passing-strings.md) vers des fonctions " +"FFI" #: src/idioms/ffi/errors.md:1 msgid "Error Handling in FFI" -msgstr "" +msgstr "Gestion des erreurs dans les FFI" #: src/idioms/ffi/errors.md:5 msgid "" @@ -1389,152 +1759,187 @@ msgid "" "However, Rust's type system allows much more rich error information to be " "captured and propagated through a full type." msgstr "" +"Dans d'autres langages comme le C, les erreurs sont représentées par des " +"codes de retour. Cependant, le système de types de Rust permet de capturer " +"et de propager bien plus d'information en implémentant des types complets " +"pour les erreurs." #: src/idioms/ffi/errors.md:9 msgid "" "This best practice shows different kinds of error codes, and how to expose " "them in a usable way:" msgstr "" +"Cet idiome montre différents types de codes d'erreur et comment les exposer " +"pour pouvoir les utiliser :" #: src/idioms/ffi/errors.md:12 msgid "Flat Enums should be converted to integers and returned as codes." msgstr "" +"Les enums simples sont converties en entiers et retournées en tant que codes." #: src/idioms/ffi/errors.md:13 msgid "" "Structured Enums should be converted to an integer code with a string error " "message for detail." msgstr "" +"Les enums structurées sont converties en un code entier avec un message " +"d'erreur sous forme de chaîne de caractère pour le détail." #: src/idioms/ffi/errors.md:15 msgid "" "Custom Error Types should become \"transparent\", with a C representation." msgstr "" +"Les types d'erreur personnalisés sont \"transparents\" grâce à une " +"représentation en C." #: 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:44 #: src/patterns/ffi/wrappers.md:24 msgid "Code Example" -msgstr "" +msgstr "Exemples de code" #: src/idioms/ffi/errors.md:19 msgid "Flat Enums" -msgstr "" +msgstr "Enums simples" #: src/idioms/ffi/errors.md:23 msgid "// user attempted a write operation\n" -msgstr "" +msgstr "// Tentative d'écriture non autorisée\n" #: src/idioms/ffi/errors.md:24 msgid "// user should read the C errno() for what it was\n" -msgstr "" +msgstr "// L'utilisateur peut lire errno() pour connaître le problème\n" #: src/idioms/ffi/errors.md:25 msgid "// user should run a repair tool to recover it\n" -msgstr "" +msgstr "// L'utilisateur peut utiliser un outil de réparation du fichier\n" #: src/idioms/ffi/errors.md:35 msgid "Structured Enums" -msgstr "" +msgstr "Enums structurées" #: src/idioms/ffi/errors.md:42 msgid "// message describing the issue\n" -msgstr "" +msgstr "// message qui décrit le problème\n" #: src/idioms/ffi/errors.md:61 src/idioms/ffi/accepting-strings.md:47 #: src/idioms/ffi/accepting-strings.md:79 src/idioms/ffi/passing-strings.md:33 #: src/patterns/ffi/export.md:154 src/patterns/ffi/export.md:158 #: src/patterns/ffi/export.md:165 msgid "\"C\"" -msgstr "" +msgstr "\"C\"" #: src/idioms/ffi/errors.md:64 msgid "" "// SAFETY: we assume that the lifetime of `e` is greater than\n" " // the current stack frame.\n" msgstr "" +"// SÉCURITÉ : on suppose que la durée de vie de `e` est supérieure\n" +" // à la position actuelle dans la pile\n" #: src/idioms/ffi/errors.md:70 msgid "\"cannot write to read-only database\"" -msgstr "" +msgstr "\"impossible d'écrire dans une base de données en lecture seule\"" #: src/idioms/ffi/errors.md:73 msgid "\"I/O Error: {e}\"" -msgstr "" +msgstr "\"I/O Error: {e}\"" #: src/idioms/ffi/errors.md:76 msgid "\"File corrupted, run repair: {}\"" -msgstr "" +msgstr "\"Fichier corrompu, réparez avec {}\"" #: src/idioms/ffi/errors.md:83 msgid "" "// SAFETY: copying error_bytes to an allocated buffer with a '\\0'\n" " // byte at the end.\n" msgstr "" +"// SÉCURITÉ : on copie error_bytes vers un tampon alloué avec `\\0`\n" +" // à la fin\n" #: src/idioms/ffi/errors.md:99 msgid "Custom Error Types" -msgstr "" +msgstr "Types d'erreur personnalisés" #: src/idioms/ffi/errors.md:109 src/idioms/ffi/accepting-strings.md:48 #: src/idioms/ffi/accepting-strings.md:83 src/patterns/creational/builder.md:30 #: src/patterns/ffi/export.md:137 src/patterns/ffi/export.md:139 msgid "/* ... */" -msgstr "" +msgstr "/* ... */" #: src/idioms/ffi/errors.md:111 msgid "/* Create a second version which is exposed as a C structure */" msgstr "" +"/* Crée une deuxième version qui est exposée en tant que structure C */" #: src/idioms/ffi/errors.md:130 msgid "" "This ensures that the foreign language has clear access to error information " "while not compromising the Rust code's API at all." msgstr "" +"Cela permet de garantir que le langage extérieur a un accès clair à " +"l'information de l'erreur sans compromettre l'API du code Rust." #: src/idioms/ffi/errors.md:135 msgid "" "It's a lot of typing, and some types may not be able to be converted easily " "to C." msgstr "" +"C'est très verbeux et certains types peuvent ne pas être facilement " +"convertibles en C." #: src/idioms/ffi/accepting-strings.md:5 msgid "" "When accepting strings via FFI through pointers, there are two principles " "that should be followed:" msgstr "" +"Lorsqu'on reçoit des chaînes de caractères _via_ des pointeurs FFI, il y a " +"deux principes à respecter :" #: src/idioms/ffi/accepting-strings.md:8 msgid "Keep foreign strings \"borrowed\", rather than copying them directly." msgstr "" +"Garder les chaînes de caractères étrangères \"empruntées\" plutôt que de les " +"copier directement." #: src/idioms/ffi/accepting-strings.md:9 msgid "" "Minimize the amount of complexity and `unsafe` code involved in converting " "from a C-style string to native Rust strings." msgstr "" +"Limiter au maximum la complexité et l'insécurité du code utilisé pour " +"convertir un string C vers un string Rust." #: src/idioms/ffi/accepting-strings.md:14 msgid "" "The strings used in C have different behaviours to those used in Rust, " "namely:" msgstr "" +"Les chaînes de caractères utilisées en C ont des comportements différents de " +"celles utilisées en rust :" #: src/idioms/ffi/accepting-strings.md:16 msgid "C strings are null-terminated while Rust strings store their length" msgstr "" +"Les chaînes en C se terminent par null alors que les chaînes en Rust " +"stockent leur longueur" #: src/idioms/ffi/accepting-strings.md:17 msgid "" "C strings can contain any arbitrary non-zero byte while Rust strings must be " "UTF-8" msgstr "" +"Les chaînes en C peuvent contenir un nombre arbitraire d'octets non nuls " +"alors que les chaînes en Rust doivent être encodées en UTF-8" #: src/idioms/ffi/accepting-strings.md:19 msgid "" "C strings are accessed and manipulated using `unsafe` pointer operations " "while interactions with Rust strings go through safe methods" msgstr "" +"Les chaînes en C sont manipulées _via_ des opérations de pointeurs non " +"sécurisées alors que les interactions avec les chaînes en Rust utilisent des " +"méthodes sécurisées" #: src/idioms/ffi/accepting-strings.md:22 msgid "" @@ -1543,18 +1948,25 @@ msgid "" "complexity and `unsafe` code involved in converting between C strings and " "Rust strings." msgstr "" +"La librairie standard de Rust comprend des équivalents en C des types " +"`String` et `&str`. Ils sont nommés `CString` et `&CStr` et permettent " +"d'éviter la plupart du code complexe et non sécurisé impliqué dans la " +"conversion de chaînes de caractères du format de C au format de Rust." #: src/idioms/ffi/accepting-strings.md:26 msgid "" "The `&CStr` type also allows us to work with borrowed data, meaning passing " "strings between Rust and C is a zero-cost operation." msgstr "" +"Le type `&CStr` permet également de travailler avec des données empruntées, " +"ce qui signifie qu'on peut passer des chaînes de caractères entre Rust et C " +"sans aucun coût." #: src/idioms/ffi/accepting-strings.md:34 #: src/idioms/ffi/accepting-strings.md:77 src/idioms/ffi/passing-strings.md:31 #: src/idioms/ffi/passing-strings.md:80 src/patterns/ffi/wrappers.md:114 msgid "// other module content\n" -msgstr "" +msgstr "// autre contenu du module\n" #: src/idioms/ffi/accepting-strings.md:36 msgid "" @@ -1569,67 +1981,93 @@ msgid "" " /// - points to memory ending in a null byte\n" " /// - won't be mutated for the duration of this function call\n" msgstr "" +"/// Log un message au niveau spécifié.\n" +" ///\n" +" /// #Sécurité\n" +" ///\n" +" /// L'utilisateur de la fonction doit s'assurer que `msg`:\n" +" ///\n" +" /// - n'est pas un pointeur null\n" +" /// - pointe vers une donnée valide et initialisée\n" +" /// - pointe vers une zone mémoire qui finit par un octet vide\n" +" /// - ne sera pas modifié pendant la durée de l'appel de cette fonction\n" #: src/idioms/ffi/accepting-strings.md:50 msgid "" "// SAFETY: The caller has already guaranteed this is okay (see the\n" " // `# Safety` section of the doc-comment).\n" msgstr "" +"// SÉCURITÉ : L'utilisateur de la fonction a déjà garanti que ce code est " +"sécurisé\n" +" // (voir la section `# Sécurité` du commentaire de documentation)\n" #: src/idioms/ffi/accepting-strings.md:55 #: src/idioms/ffi/accepting-strings.md:105 msgid "\"FFI string conversion failed\"" -msgstr "" +msgstr "\"La conversion FFI a échoué\"" #: src/idioms/ffi/accepting-strings.md:67 msgid "The example is written to ensure that:" -msgstr "" +msgstr "Cet exemple est écrit pour garantir que :" #: src/idioms/ffi/accepting-strings.md:69 src/idioms/ffi/passing-strings.md:70 msgid "The `unsafe` block is as small as possible." -msgstr "" +msgstr "Le bloc non sécurisé est aussi petit que possible." #: src/idioms/ffi/accepting-strings.md:70 msgid "" "The pointer with an \"untracked\" lifetime becomes a \"tracked\" shared " "reference" msgstr "" +"Le pointeur avec une durée de vie non suivie devient une référence partagée " +"suivie" #: src/idioms/ffi/accepting-strings.md:72 msgid "Consider an alternative, where the string is actually copied:" msgstr "" +"Considérons une alternative où la chaîne de caractère est effectivement " +"copiée :" #: src/idioms/ffi/accepting-strings.md:80 msgid "" "// DO NOT USE THIS CODE.\n" " // IT IS UGLY, VERBOSE, AND CONTAINS A SUBTLE BUG.\n" msgstr "" +"// NE PAS UTILISER CE CODE.\n" +"// IL EST MOCHE, TROP VERBEUX ET CONTIENT UN BUG INSIDIEUX.\n" #: src/idioms/ffi/accepting-strings.md:85 msgid "/* SAFETY: strlen is what it is, I guess? */" -msgstr "" +msgstr "/* SÉCURITÉ : strlen est ce qu'il est je suppose ? */" #: src/idioms/ffi/accepting-strings.md:92 msgid "" "// SAFETY: copying from a foreign pointer expected to live\n" " // for the entire stack frame into owned memory\n" msgstr "" +"// SÉCURITÉ : copie depuis un pointeur externe, censé rester\n" +" // en mémoire pendant toute la durée de l'exécution\n" #: src/idioms/ffi/accepting-strings.md:116 msgid "This code is inferior to the original in two respects:" -msgstr "" +msgstr "Ce code est inférieur à l'original sous deux aspects :" #: src/idioms/ffi/accepting-strings.md:118 msgid "" "There is much more `unsafe` code, and more importantly, more invariants it " "must uphold." msgstr "" +"Il y a bien plus de code non sécurisé et, plus important encore, plus " +"d'invariants à maintenir." #: src/idioms/ffi/accepting-strings.md:120 msgid "" "Due to the extensive arithmetic required, there is a bug in this version " -"that cases Rust `undefined behaviour`." +"that causes Rust `undefined behaviour`." msgstr "" +"À cause de la grande quantité de calcul nécessaire, il y a un bug dans cette " +"version qui provoque un `comportement non défini` de Rust (`undefined " +"behaviour`)." #: src/idioms/ffi/accepting-strings.md:123 msgid "" @@ -1637,6 +2075,9 @@ msgid "" "copied, all `msg_len` bytes of it. However, the `NUL` terminator at the end " "was not." msgstr "" +"Le bug est ici une simple erreur dans l'arithmétique des pointeurs : la " +"chaîne de caractères a été copiée, avec un nombre d'octet total de " +"`msg_len`. Cependant, le terminateur `NUL` n'a pas été copié." #: src/idioms/ffi/accepting-strings.md:126 msgid "" @@ -1646,6 +2087,11 @@ msgid "" "`CString` is created at the bottom of the block, its read of the Vector will " "cause `undefined behaviour`!" msgstr "" +"Le vecteur a ensuite vu sa taille initialisée avec la longueur de la chaîne " +"caractère et non pas redimensionné, ce qui aurait pu ajouter un zéro à la " +"fin. En conséquence, le dernier octet du vecteur est de la mémoire non " +"intialisée. Quand le `CString` est créé à la fin du block, sa lecture du " +"vecteur provoquera un `comportement non défini` !" #: src/idioms/ffi/accepting-strings.md:132 msgid "" @@ -1654,36 +2100,48 @@ msgid "" "would put a weird character at the end of the string, sometimes it would " "just completely crash." msgstr "" +"Comme beaucoup de problèmes similaires, ce bug peut être difficile à " +"localiser. Parfois il provoquerait une panique parce que la chaîne de " +"caractère n'est pas au format `UTF-8`, parfois il inscrirait un caractère " +"inattendu à la fin de la chaîne, parfois il provoquerait un crash pur et " +"simple de l'application." #: src/idioms/ffi/accepting-strings.md:138 #: src/idioms/ffi/passing-strings.md:103 msgid "None?" -msgstr "" +msgstr "Aucun ?" #: src/idioms/ffi/passing-strings.md:5 msgid "" "When passing strings to FFI functions, there are four principles that should " "be followed:" msgstr "" +"Lorsqu'on envoie des chaînes de caractères à des fonctions FFI, il y a " +"quatre principes à respecter :" #: src/idioms/ffi/passing-strings.md:8 msgid "Make the lifetime of owned strings as long as possible." msgstr "" +"Réduire au maximum la durée de vie des chaînes de caractères possédées." #: src/idioms/ffi/passing-strings.md:9 msgid "Minimize `unsafe` code during the conversion." -msgstr "" +msgstr "Minimiser le code non sécurisé pendant la conversion." #: src/idioms/ffi/passing-strings.md:10 msgid "" "If the C code can modify the string data, use `Vec` instead of `CString`." msgstr "" +"Si le code C peut modifier les données de la chaîne de caractères, utiliser " +"`Vec` plutôt que `CString`." #: src/idioms/ffi/passing-strings.md:11 msgid "" "Unless the Foreign Function API requires it, the ownership of the string " "should not transfer to the callee." msgstr "" +"À moins que l'API externe ne le requière, la propriété de la chaîne de " +"caractère ne devrait pas être transférée à la fonction appelée." #: src/idioms/ffi/passing-strings.md:16 msgid "" @@ -1691,6 +2149,10 @@ msgid "" "types. However, there are different approaches one can take with strings " "that are being sent to a foreign function call from a Rust function." msgstr "" +"Rust a un support intégré pour les chaînes de caractères de style C avec les " +"types `CString` et `CStr`. Cependant, il y a plusieurs approches possibles " +"pour les chaînes de caractères à envoyer vers une fonction externe depuis " +"une fonction Rust." #: src/idioms/ffi/passing-strings.md:20 msgid "" @@ -1700,44 +2162,60 @@ msgid "" "documentation explains that \"round-tripping\" a `CString` after " "modification is UB, so additional work is necessary in that case." msgstr "" +"La meilleure pratique est simple : utiliser `CString` de sorte à minimiser " +"le code non sécurisé. Cependant, une autre notion à ne pas négliger est que " +"_l'objet doit vivre assez longtemps_, ce qui signifie que la durée de vie " +"doit être maximisée. De plus, la documentation explique qu'un aller-retour " +"de `CString` après modification provoque un `comportement non sécurisé`, " +"donc ce cas précis nécessite un peu plus de travail." #: src/idioms/ffi/passing-strings.md:42 msgid "" "// SAFETY: calling an FFI whose documentation says the pointer is\n" " // const, so no modification should occur\n" msgstr "" +"// SÉCURITÉ : appeler une FFI dont la documentation précise que le pointeur " +"est \n" +" // constant, pour qu'aucune modification n'ait lieu\n" #: src/idioms/ffi/passing-strings.md:48 msgid "// The lifetime of c_err continues until here\n" -msgstr "" +msgstr "// La durée de vie de c_err continue jusqu'ici\n" #: src/idioms/ffi/passing-strings.md:54 msgid "" "// SAFETY: calling an FFI whose documentation implies\n" " // that the input need only live as long as the call\n" msgstr "" +"// SÉCURITÉ : appeler une FFI dont la documentation précise\n" +" // que l'entrée doit seulement vivre aussi longtemps que " +"l'appel\n" #: src/idioms/ffi/passing-strings.md:68 msgid "The example is written in a way to ensure that:" -msgstr "" +msgstr "Cet exemple est écrit pour garantir que :" #: src/idioms/ffi/passing-strings.md:71 msgid "The `CString` lives long enough." -msgstr "" +msgstr "Le `CString` vit assez longtemps." #: src/idioms/ffi/passing-strings.md:72 msgid "Errors with typecasts are always propagated when possible." msgstr "" +"Les erreurs dues aux conversions entre types sont toujours propagées quand " +"c'est possible." #: src/idioms/ffi/passing-strings.md:74 msgid "" "A common mistake (so common it's in the documentation) is to not use the " "variable in the first block:" msgstr "" +"Une erreur fréquente (tellement fréquente qu'elle est dans la documentation) " +"est de ne pas utiliser la variable dans le premier bloc :" #: src/idioms/ffi/passing-strings.md:84 msgid "// SAFETY: whoops, this contains a dangling pointer!\n" -msgstr "" +msgstr "// SÉCURITÉ : ouuuups, il y a un pointeur non résolu !\n" #: src/idioms/ffi/passing-strings.md:92 msgid "" @@ -1745,6 +2223,9 @@ msgid "" "`CString` is not extended by the pointer creation, unlike if a reference " "were created." msgstr "" +"Ce code produit un pointeur non résolu, car la durée de vie du `CString` " +"n'est pas étendue par la création du pointeur, ce qui serait le cas si une " +"référence était créée." #: src/idioms/ffi/passing-strings.md:96 msgid "" @@ -1753,10 +2234,15 @@ msgid "" "particular macro to a call to `zmalloc`, meaning it is as fast as the " "operating system's ability to return zeroed memory (which is quite fast)." msgstr "" +"Un autre problème fréquent est que l'initialisation d'un vecteur d'1k de " +"zéros est \"lent\". Cependant les versions récentes de Rust ont optimisé " +"cette macro en particulier pour appeler `zmalloc`, ce qui signifie que la " +"vitesse d'exécution est égale à la capacité du système d'exploitation de " +"renvoyer une zone mémoire remplie de zéros (ce qui est plutôt rapide)." #: src/idioms/option-iter.md:1 msgid "Iterating over an `Option`" -msgstr "" +msgstr "Itérer sur une `Option`" #: src/idioms/option-iter.md:5 msgid "" @@ -1764,11 +2250,14 @@ msgid "" "element. In particular, it implements the `IntoIterator` trait, and as such " "can be used with generic code that needs such a type." msgstr "" +"`Option` peut être vu comme un conteneur qui contient zéro ou un élément. Il " +"implémente le trait `IntoIterator`, ce qui permet de l'utiliser lorsque du " +"code générique demande un type implémentant ce trait." #: src/idioms/option-iter.md:9 src/patterns/structural/small-crates.md:34 #: src/patterns/structural/unsafe-mods.md:23 msgid "Examples" -msgstr "" +msgstr "Exemples" #: src/idioms/option-iter.md:11 msgid "" @@ -1776,26 +2265,29 @@ msgid "" "[`.extend()`](https://doc.rust-lang.org/std/iter/" "trait.Extend.html#tymethod.extend):" msgstr "" +"Puisque `Option` implémente `IntoIterator`, on peut l'utiliser comme " +"argument pour [`.extend(){](https://doc.rust-lang.org/std/iter/" +"trait.Extend.html#tymethod.extend) :" #: src/idioms/option-iter.md:15 src/idioms/option-iter.md:31 msgid "\"Turing\"" -msgstr "" +msgstr "\"Turing\"" #: src/idioms/option-iter.md:16 src/idioms/option-iter.md:32 msgid "\"Curry\"" -msgstr "" +msgstr "\"Curry\"" #: src/idioms/option-iter.md:16 src/idioms/option-iter.md:32 msgid "\"Kleene\"" -msgstr "" +msgstr "\"Kleene\"" #: src/idioms/option-iter.md:16 src/idioms/option-iter.md:32 msgid "\"Markov\"" -msgstr "" +msgstr "\"Markov\"" #: src/idioms/option-iter.md:19 msgid "// equivalent to\n" -msgstr "" +msgstr "// équivalent à\n" #: src/idioms/option-iter.md:26 msgid "" @@ -1803,10 +2295,13 @@ msgid "" "pass it to [`.chain()`](https://doc.rust-lang.org/std/iter/" "trait.Iterator.html#method.chain):" msgstr "" +"Si vous avez besoin d'ajouter une `Option` à la fin d'un itérateur existant, " +"vous pouvez le passer à la méthode [`.chain()`](https://doc.rust-lang.org/" +"std/iter/trait.Iterator.html#method.chain) :" #: src/idioms/option-iter.md:35 msgid "\"{logician} is a logician\"" -msgstr "" +msgstr "\"{logician} est un logicien\"" #: src/idioms/option-iter.md:39 msgid "" @@ -1814,6 +2309,9 @@ msgid "" "[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) on the " "element instead." msgstr "" +"Notez que si `Option` vaut toujours `Some`, alors il est plus idiomatique " +"d'utiliser [`std::iter::once`](https://doc.rust-lang.org/std/iter/" +"fn.once.html) directement sur l'élément." #: src/idioms/option-iter.md:43 msgid "" @@ -1821,6 +2319,10 @@ msgid "" "over it using a `for` loop. This is equivalent to matching it with `if let " "Some(..)`, and in most cases you should prefer the latter." msgstr "" +"De plus, puisque `Option` implémente `IntoIterator`, il est possible " +"d'itérer dessus avec un boucle `for`. C'est en fait équivalent à écrire `if " +"let Some(..)`, et dans la plupart des cas vous devriez privilégier cette " +"deuxième syntaxe." #: src/idioms/option-iter.md:49 msgid "" @@ -1828,6 +2330,9 @@ msgid "" "iterator which yields exactly one element. It's a more readable alternative " "to `Some(foo).into_iter()`." msgstr "" +"[`std::iter::once`](https://doc.rust-lang.org/std/iter/fn.once.html) est un " +"itérateur qui renvoie exactement un élément. C'est une alternative plus " +"lisible à `Some(foo).into_iter()`." #: src/idioms/option-iter.md:53 msgid "" @@ -1836,22 +2341,30 @@ msgid "" "(https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map), " "specialized to mapping functions which return `Option`." msgstr "" +"[`Iterator::filter_map`](https://doc.rust-lang.org/std/iter/" +"trait.Iterator.html#method.filter_map) est une version de [`Iterator::map`]" +"(https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map) " +"spécialisée dans le mappage de fonctions qui renvoient une `Option`." #: src/idioms/option-iter.md:58 msgid "" "The [`ref_slice`](https://crates.io/crates/ref_slice) crate provides " "functions for converting an `Option` to a zero- or one-element slice." msgstr "" +"Le crate [`ref_slice`](https://crates.io/crates/ref_slice) fournit des " +"fonctions pour convertir une `Option` en slice contenant zéro ou un élément." #: src/idioms/option-iter.md:61 msgid "" "[Documentation for `Option`](https://doc.rust-lang.org/std/option/" "enum.Option.html)" msgstr "" +"[Documentation pour `Option`](https://doc.rust-lang.org/std/option/" +"enum.Option.html)" #: src/idioms/pass-var-to-closure.md:1 msgid "Pass variables to closure" -msgstr "" +msgstr "Envoyer des variables à une fermeture" #: src/idioms/pass-var-to-closure.md:5 msgid "" @@ -1860,30 +2373,36 @@ msgid "" "move just some variables to the closure, give it a copy of some data, pass " "by reference, or perform some other transformation." msgstr "" +"Par défaut, les fermetures capturent leur environnement par emprunt. On peut " +"aussi utiliser une fermeture avec `move` pour déplacer toutes les variables. " +"Cependant, on a souvent besoin de déplacer seulement certaines variables " +"vers la fermeture ou encore de lui donner une copie de certaines données, " +"une référence ou de faire un autre type de transformation." #: src/idioms/pass-var-to-closure.md:10 msgid "Use variable rebinding in a separate scope for that." msgstr "" +"Pour cela, on utilise une ré-assignation des variables dans un scope séparé." #: src/idioms/pass-var-to-closure.md:14 msgid "Use" -msgstr "" +msgstr "Utilisez" #: src/idioms/pass-var-to-closure.md:23 msgid "// `num1` is moved\n" -msgstr "" +msgstr "// `num1` est déplacée\n" #: src/idioms/pass-var-to-closure.md:24 msgid "// `num2` is cloned\n" -msgstr "" +msgstr "// `num2` est clonée\n" #: src/idioms/pass-var-to-closure.md:25 msgid "// `num3` is borrowed\n" -msgstr "" +msgstr "// `num3` est empruntée\n" #: src/idioms/pass-var-to-closure.md:32 msgid "instead of" -msgstr "" +msgstr "plutôt que" #: src/idioms/pass-var-to-closure.md:50 msgid "" @@ -1891,20 +2410,26 @@ msgid "" "purpose is more clear, and they will be dropped immediately even if they are " "not consumed by the closure." msgstr "" +"Les données copiées sont groupées avec la définition de la fermeture, leur " +"rôle est donc plus clair et elles seront libérées immédiatement même si la " +"fermeture ne les consomme pas." #: src/idioms/pass-var-to-closure.md:54 msgid "" "The closure uses the same variable names as the surrounding code, whether " "data are copied or moved." msgstr "" +"La fermeture utilise les même noms de variables que le code environnant, que " +"ces variables soient copiées ou déplacées." #: src/idioms/pass-var-to-closure.md:59 msgid "Additional indentation of the closure body." -msgstr "" +msgstr "Une indentation supplémentaire pour le corps de la fermeture." #: src/idioms/priv-extend.md:1 msgid "`#[non_exhaustive]` and private fields for extensibility" msgstr "" +"Gérer l'extensibilité avec `#[non_exhaustive]` ou avec des champs privés" #: src/idioms/priv-extend.md:5 msgid "" @@ -1912,10 +2437,13 @@ msgid "" "fields to a public struct or new variants to an enum without breaking " "backwards compatibility." msgstr "" +"Dans certains scenarios, l'auteur d'une librairie peut vouloir ajouter des " +"champs publics à une structure publique ou de nouveaux variants à une " +"énumération sans casser la retro-compatibilité." #: src/idioms/priv-extend.md:9 msgid "Rust offers two solutions to this problem:" -msgstr "" +msgstr "Rust offre deux solutions à ce problème :" #: src/idioms/priv-extend.md:11 msgid "" @@ -1924,58 +2452,72 @@ msgid "" "used, see [the docs](https://doc.rust-lang.org/reference/attributes/" "type_system.html#the-non_exhaustive-attribute)." msgstr "" +"Utiliser `#[non_exhaustive]` sur les `struct`, `enum` et variants d'`enum`. " +"Pour une liste exhaustive des endroits où `#[non_exhaustive]` peut être " +"utilisé, voir [la documentation](https://doc.rust-lang.org/reference/" +"attributes/type_system.html#the-non_exhaustive-attribute)." #: src/idioms/priv-extend.md:16 msgid "" "You may add a private field to a struct to prevent it from being directly " "instantiated or matched against (see Alternative)" msgstr "" +"Ajouter un champ privé à la structure pour interdire une instanciation " +"directe ou un filtrage par motif (voir la section Alternative)" #: src/idioms/priv-extend.md:23 msgid "// Public struct.\n" -msgstr "" +msgstr "// Structure publique.\n" #: src/idioms/priv-extend.md:41 msgid "" "// Because S is `#[non_exhaustive]`, it cannot be named here and\n" " // we must use `..` in the pattern.\n" msgstr "" +"// Comme S est `#[non_exhaustive]`, on doit utiliser `..` dans le pattern.\n" #: src/idioms/priv-extend.md:47 msgid "\"it's an A\"" -msgstr "" +msgstr "\"c'est un A\"" +# Peut-être que la différence de casse entre A, b et c était voulue dans le programme ? Ce n'est pas un détail très important je pense. #: src/idioms/priv-extend.md:48 msgid "\"it's a b\"" -msgstr "" +msgstr "\"c'est un B\"" #: src/idioms/priv-extend.md:50 msgid "// .. required because this variant is non-exhaustive as well\n" msgstr "" +"// ce variant n'est pas exhaustif non plus, donc il faut utiliser `..`\n" #: src/idioms/priv-extend.md:51 msgid "\"it's a c\"" -msgstr "" +msgstr "\"c'est un C\"" #: src/idioms/priv-extend.md:53 msgid "" "// The wildcard match is required because more variants may be\n" " // added in the future\n" msgstr "" +"// Le cas générique est obligatoire puisque d'autres variants pourraient\n" +" // être ajoutés plus tard\n" #: src/idioms/priv-extend.md:55 msgid "\"it's a new variant\"" -msgstr "" +msgstr "\"c'est un nouveau variant\"" #: src/idioms/priv-extend.md:60 msgid "Alternative: `Private fields` for structs" -msgstr "" +msgstr "Alternative : champs privés dans les structures" #: src/idioms/priv-extend.md:62 msgid "" "`#[non_exhaustive]` only works across crate boundaries. Within a crate, the " "private field method may be used." msgstr "" +"`#[non_exhaustive]` fonctionne seulement lorsqu'on sort des limites du " +"crate. Dans le crate en lui-même, on peut utiliser la technique du champ " +"privé." #: src/idioms/priv-extend.md:65 msgid "" @@ -1987,6 +2529,14 @@ msgid "" "struct's fields private forces clients to use the latter form of patterns, " "ensuring that the struct is future-proof." msgstr "" +"Ajouter un champ à une structure ne casse généralement pas la retro-" +"compatibilité. Cependant, si un client utilise un motif pour déconstruire " +"une instance de la structure, il nomme peut-être tous les champs et dans ce " +"cas en ajouter un nouveau casserait ce motif. Le client pourrait nommer " +"certains champs seulement et utiliser `..`, auquel cas l'ajout d'un nouveau " +"champ serait retro-compatible. Rendre au moins un champ de la structure " +"privé force les clients à utiliser cette syntaxe, ce qui permet de s'assurer " +"que la structure restera compatible." #: src/idioms/priv-extend.md:73 msgid "" @@ -1995,6 +2545,10 @@ msgid "" "runtime overhead and prepend `_` to the field name to avoid the unused field " "warning." msgstr "" +"L'inconvénient de cette approche est que vous devrez peut-être ajouter un " +"champ qui n'a pas d'autre utilité que celle-ci à la structure. Vous pouvez " +"utiliser le type `()` pour ne pas avoir de surcoût à l'exécution et préfixer " +"le nom du champ avec `_` pour éviter l'avertissement de champ non utilisé." #: src/idioms/priv-extend.md:81 msgid "" @@ -2002,6 +2556,9 @@ msgid "" "`S`\n" " // cannot be directly instantiated or matched against\n" msgstr "" +"// Comme `b` est privé, on ne peut pas filtrer sur `S` sans utiliser `..` et " +"`S`\n" +" // ne peut pas être directement instancié ou filtré par motif\n" #: src/idioms/priv-extend.md:89 msgid "" @@ -2012,6 +2569,13 @@ msgid "" "clients as a compiler error rather than something that may be silently " "undiscovered." msgstr "" +"Dans une structure, `#[non_exhaustive]` permet d'ajouter des champs " +"additionnels en respectant la retro-compatibilité. Cela empêche également " +"les clients d'utiliser le constructeur de la structure même dans le cas où " +"tous les champs sont publics. Cette méthode peut être utile, mais il vaut la " +"peine de se demander si on ne souhaite pas plutôt que l'ajout d'un nouveau " +"champ soit découvert par le client _via_ une erreur à la compilation plutôt " +"que de rendre cette modification silencieuse." #: src/idioms/priv-extend.md:95 msgid "" @@ -2019,6 +2583,9 @@ msgid "" "`#[non_exhaustive]` variant behaves in the same way as a `#[non_exhaustive]` " "struct." msgstr "" +"`#[non_exhaustive]` peut être appliquée sur les variants d'énumération " +"également. Un variant `#[non_exhaustive]` se comporte de la même manière " +"qu'une structure `#[non_exhaustive]`." #: src/idioms/priv-extend.md:99 msgid "" @@ -2027,6 +2594,11 @@ msgid "" "be appropriate in scenarios where you're modeling an external resource that " "may change out-of-sync with your library, but is not a general purpose tool." msgstr "" +"Utilisez ces techniques avec prudence : incrémenter la version majeure d'un " +"crate lorsqu'on ajoute des champs ou des variants est souvent une meilleure " +"option. `#[non_exhaustive]` peut être appropriée dans des scenarios où vous " +"modélisez une ressource externe qui peut changer de manière non-synchronisée " +"par rapport à votre librairie, mais ce n'est pas un outil d'usage générique." #: src/idioms/priv-extend.md:106 msgid "" @@ -2035,6 +2607,10 @@ msgid "" "used when these sorts of evolutions are required **without** incrementing " "the major version." msgstr "" +"`#[non_exhaustive]` peut rendre votre code peu ergonomique, surtout lorsque " +"le client est forcé de gérer les variants inconnus. Vous ne devriez " +"l'utiliser que lorsque des évolutions de ce types sont requise **sans** " +"incrémentation de la version majeure." #: src/idioms/priv-extend.md:110 msgid "" @@ -2046,12 +2622,23 @@ msgid "" "fact, `#[non_exhaustive]` forces clients to handle the \"Something else\" " "case; there is rarely a sensible action to take in this scenario." msgstr "" +"Quand `#[non_exhaustive]` est appliquée à une énumération, elle force les " +"clients à gérer le variant générique `_`. S'il n'y a pas d'action précise à " +"faire dans ce cas, cela peut générer du code étrange et des blocs de code " +"exécutés seulement dans des circonstances extrêmement rares. Si un client " +"décide d'utiliser `panic!()` dans ce scenario, peut-être aurait-il été " +"préférable d'exposer cette erreur à la compilation. En réalité, " +"`#[non_exhaustive]` force le client à gérer le cas \"Autre chose\" alors " +"qu'il n'y a que rarement une action appropriée à faire dans ce scenario." #: src/idioms/priv-extend.md:120 msgid "" "[RFC introducing #\\[non_exhaustive\\] attribute for enums and structs]" "(https://github.com/rust-lang/rfcs/blob/master/text/2008-non-exhaustive.md)" msgstr "" +"[RFC introduisant l'attribut #\\[non_exhaustive`] pour les énumérations et " +"les structures](https://github.com/rust-lang/rfcs/blob/master/text/2008-non-" +"exhaustive.md)" #: src/idioms/rustdoc-init.md:5 msgid "" @@ -2059,16 +2646,22 @@ msgid "" "be quicker to wrap your example with a helper function which takes the " "struct as an argument." msgstr "" +"Lorsqu'une structure demande une initialisation compliquée, pour écrire la " +"documentation, il peut être plus rapide au sein des exemples de masquer " +"cette initialisation dans une fonction qui prend la structure en argument." #: src/idioms/rustdoc-init.md:11 msgid "" "Sometimes there is a struct with multiple or complicated parameters and " "several methods. Each of these methods should have examples." msgstr "" +"Certaines structures peuvent avoir des paramètres nombreux ou compliqués et " +"plusieurs méthodes. Chacune de ces méthodes doit avoir des exemples dans la " +"documentation." #: src/idioms/rustdoc-init.md:14 msgid "For example:" -msgstr "" +msgstr "Par exemple :" #: src/idioms/rustdoc-init.md:23 msgid "" @@ -2085,15 +2678,30 @@ msgid "" " /// assert!(response.is_ok());\n" " /// ```\n" msgstr "" +"/// Envoie une requête via la connexion.\n" +" ///\n" +" /// # Exemple\n" +" /// ```no_run\n" +" /// # // Du code générique est requis pour faire fonctionner l'exemple.\n" +" /// # let stream = TcpStream::connect(\"127.0.0.1:34254\");\n" +" /// # let connection = Connection { name: \"foo\".to_owned(), stream };\n" +" /// # let request = Request::new(\"RequestId\", RequestType::Get, " +"\"payload\");\n" +" /// let response = connection.send_request(request);\n" +" /// assert!(response.is_ok());\n" +" /// ```\n" #: src/idioms/rustdoc-init.md:35 src/idioms/rustdoc-init.md:40 -#: src/idioms/rustdoc-init.md:68 +#: src/idioms/rustdoc-init.md:68 src/patterns/structural/trait-for-bounds.md:52 +#: src/patterns/structural/trait-for-bounds.md:56 +#: src/patterns/structural/trait-for-bounds.md:60 +#: src/patterns/structural/trait-for-bounds.md:90 msgid "// ...\n" -msgstr "" +msgstr "// ...\n" #: src/idioms/rustdoc-init.md:38 msgid "/// Oh no, all that boilerplate needs to be repeated here!\n" -msgstr "" +msgstr "/// Oh non, tout ce code générique doit être répété ici !\n" #: src/idioms/rustdoc-init.md:47 msgid "" @@ -2101,6 +2709,9 @@ msgid "" "`Request`, it is easier to just create a wrapping helper function which " "takes them as arguments:" msgstr "" +"Au lieu de taper tout ce code générique pour créer une `Connection` et une " +"`Request`, il est plus simple de créer une fonction auxiliaire qui prend ces " +"objets en argument :" #: src/idioms/rustdoc-init.md:58 msgid "" @@ -2114,6 +2725,15 @@ msgid "" " /// # }\n" " /// ```\n" msgstr "" +"/// Envoie une requête via la connexion.\n" +" ///\n" +" /// # Exemple\n" +" /// ```\n" +" /// # fn call_send(connection: Connection, request: Request) {\n" +" /// let response = connection.send_request(request);\n" +" /// assert!(response.is_ok());\n" +" /// # }\n" +" /// ```\n" #: src/idioms/rustdoc-init.md:73 msgid "" @@ -2121,10 +2741,14 @@ msgid "" "actually run while testing because it is inside a function which is never " "invoked." msgstr "" +"**Note** dans l'exemple ci-dessus, la ligne `assert!(response.is_ok());` ne " +"va pas s'exécuter lors des tests car elle est à l'intérieur d'une fonction " +"qui n'est jamais invoquée." #: src/idioms/rustdoc-init.md:79 msgid "This is much more concise and avoids repetitive code in examples." msgstr "" +"C'est beaucoup plus concis et évite la répétition de code dans les exemples." #: src/idioms/rustdoc-init.md:83 msgid "" @@ -2133,10 +2757,15 @@ msgid "" "this pattern is most useful when you need `no_run`. With this, you do not " "need to add `no_run`." msgstr "" +"Comme l'exemple est dans une fonction, le code ne sera pas testé. Cependant, " +"en lançant `cargo test`, on vérifiera quand même qu'il compile correctement. " +"Cette façon de faire est donc la plus utile lorsqu'on veut utiliser " +"`no_run`. L'ajout explicite de `no_run` n'est d'ailleurs plus nécessaire." #: src/idioms/rustdoc-init.md:90 msgid "If assertions are not required this pattern works well." msgstr "" +"Si les assertions ne sont pas nécessaires, ce patron fonctionne très bien." #: src/idioms/rustdoc-init.md:92 msgid "" @@ -2145,6 +2774,10 @@ msgid "" "won't see it). Then this method can be called inside of rustdoc because it " "is part of the crate's public API." msgstr "" +"Dans le cas contraire, une alternative peut être de créer une méthode " +"publique qui renvoie une instance et de l'annoter avec `#[doc(hidden)]` " +"(pour que les utilisateurs ne la voient pas). Cette méthode peut alors être " +"appelée par rustdoc car elle fait partie de l'API publique du crate." #: src/idioms/temporary-mutability.md:5 msgid "" @@ -2152,69 +2785,81 @@ msgid "" "are only inspected and never modified. The intention can be made explicit by " "redefining the mutable variable as immutable." msgstr "" +"On doit souvent préparer et traiter une donnée qui ne sera ensuite plus " +"jamais modifiée mais seulement lue. Cette intention peut être rendue " +"explicite en redéfinissant la variable concernée en variable immuable." #: src/idioms/temporary-mutability.md:9 msgid "" "It can be done either by processing data within a nested block or by " "redefining the variable." msgstr "" +"Il y a deux manières de faire : préparer les données dans un bloc imbriqué " +"ou alors redéfinir la variable après coup." #: src/idioms/temporary-mutability.md:14 msgid "Say, vector must be sorted before usage." -msgstr "" +msgstr "Imaginons un vecteur qui doit être trié avant toute utilisation." #: src/idioms/temporary-mutability.md:16 msgid "Using nested block:" -msgstr "" +msgstr "Avec un bloc imbriqué :" #: src/idioms/temporary-mutability.md:24 src/idioms/temporary-mutability.md:34 msgid "// Here `data` is immutable.\n" -msgstr "" +msgstr "// À partir d'ici, `data` est immuable.\n" #: src/idioms/temporary-mutability.md:28 msgid "Using variable rebinding:" -msgstr "" +msgstr "Avec une redéfinition de la variable :" #: src/idioms/temporary-mutability.md:40 msgid "" "Compiler ensures that you don't accidentally mutate data after some point." msgstr "" +"C'est le compilateur qui garantit que la variable ne sera pas modifiée après " +"un certain point, même accidentellement." #: src/idioms/temporary-mutability.md:44 msgid "" "Nested block requires additional indentation of block body. One more line to " "return data from block or redefine variable." msgstr "" +"Pour un bloc imbriqué, on doit rajouter une indentation au bloc de code. On " +"doit également écrire une ligne de plus pour renvoyer la donnée du bloc ou " +"pour redéfinir la variable." #: src/idioms/return-consumed-arg-on-error.md:1 msgid "Return consumed argument on error" -msgstr "" +msgstr "Renvoyer les arguments consommés en cas d'erreur" #: src/idioms/return-consumed-arg-on-error.md:5 msgid "" "If a fallible function consumes (moves) an argument, return that argument " "back inside an error." msgstr "" +"Si une fonction qui déplace un argument est faillible, on devrait renvoyer " +"cet argument au sein d'une erreur." #: src/idioms/return-consumed-arg-on-error.md:12 msgid "\"using {value} in a meaningful way\"" -msgstr "" +msgstr "\"utilisation significative de {value}\"" #: src/idioms/return-consumed-arg-on-error.md:13 msgid "// Simulate non-deterministic fallible action.\n" -msgstr "" +msgstr "// Simule une action faillible et non-déterministe.\n" #: src/idioms/return-consumed-arg-on-error.md:28 msgid "\"imagine this is very long string\"" -msgstr "" +msgstr "\"imaginons que cette chaîne de caractère est très très longue\"" #: src/idioms/return-consumed-arg-on-error.md:31 msgid "// Try to send value two times.\n" -msgstr "" +msgstr "// On essaie à deux reprises d'envoyer la valeur.\n" #: src/idioms/return-consumed-arg-on-error.md:41 msgid "\"success: {success}\"" -msgstr "" +msgstr "\"succès : {success}\"" #: src/idioms/return-consumed-arg-on-error.md:47 msgid "" @@ -2223,6 +2868,10 @@ msgid "" "consumed, you are forced to clone it on every call, which is not very " "efficient." msgstr "" +"En cas d'erreur, on pourrait vouloir essayer une autre alternative ou " +"retenter l'action si le résultat n'est pas déterministe. Mais si l'argument " +"est consommé à chaque fois, on est forcé de le cloner à chaque appel, ce qui " +"n'est pas très efficient." #: src/idioms/return-consumed-arg-on-error.md:51 msgid "" @@ -2231,14 +2880,21 @@ msgid "" "returned. You can get original vector back using `FromUtf8Error::into_bytes` " "method." msgstr "" +"La librairie standard utilise cette approche dans la méthode " +"`String::from_utf8` : lorsqu'on lui fournit un vecteur qui ne contient pas " +"une séquence UTF-8 valide, la méthode renvoie une erreur `FromUtf8Error` et " +"on peut ensuite récupérer le vecteur originel en utilisant la méthode " +"`FromUtf8Error::into_bytes`." #: src/idioms/return-consumed-arg-on-error.md:57 msgid "Better performance because of moving arguments whenever possible." msgstr "" +"On déplace les arguments dès que c'est possible, ce qui améliore les " +"performances." #: src/idioms/return-consumed-arg-on-error.md:61 msgid "Slightly more complex error types." -msgstr "" +msgstr "Les types d'erreur sont légèrement plus complexes." #: src/patterns/index.md:3 msgid "" @@ -3226,21 +3882,28 @@ msgid "" "construction." msgstr "" -#: src/patterns/creational/builder.md:78 +#: src/patterns/creational/builder.md:76 +msgid "" +"When you add new fields to the target struct, you can update the builder to " +"leave client code backwards compatible." +msgstr "" + +#: src/patterns/creational/builder.md:81 msgid "" "More complex than creating a struct object directly, or a simple constructor " "function." msgstr "" -#: src/patterns/creational/builder.md:83 +#: src/patterns/creational/builder.md:86 msgid "" "This pattern is seen more frequently in Rust (and for simpler objects) than " -"in many other languages because Rust lacks overloading. Since you can only " -"have a single method with a given name, having multiple constructors is less " -"nice in Rust than in C++, Java, or others." +"in many other languages because Rust lacks overloading and default values " +"for function parameters. Since you can only have a single method with a " +"given name, having multiple constructors is less nice in Rust than in C++, " +"Java, or others." msgstr "" -#: src/patterns/creational/builder.md:88 +#: src/patterns/creational/builder.md:91 msgid "" "This pattern is often used where the builder object is useful in its own " "right, rather than being just a builder. For example, see " @@ -3250,7 +3913,7 @@ msgid "" "`TBuilder` naming pattern is not used." msgstr "" -#: src/patterns/creational/builder.md:95 +#: src/patterns/creational/builder.md:98 msgid "" "The example takes and returns the builder by value. It is often more " "ergonomic (and more efficient) to take and return the builder as a mutable " @@ -3258,33 +3921,33 @@ msgid "" "the advantage that one can write code like" msgstr "" -#: src/patterns/creational/builder.md:107 +#: src/patterns/creational/builder.md:110 msgid "as well as the `FooBuilder::new().a().b().build()` style." msgstr "" -#: src/patterns/creational/builder.md:111 +#: src/patterns/creational/builder.md:114 msgid "" "[Description in the style guide](https://web.archive.org/web/20210104103100/" "https://doc.rust-lang.org/1.12.0/style/ownership/builders.html)" msgstr "" -#: src/patterns/creational/builder.md:112 +#: src/patterns/creational/builder.md:115 msgid "" "[derive_builder](https://crates.io/crates/derive_builder), a crate for " "automatically implementing this pattern while avoiding the boilerplate." msgstr "" -#: src/patterns/creational/builder.md:114 +#: src/patterns/creational/builder.md:117 msgid "" "[Constructor pattern](../../idioms/ctor.md) for when construction is simpler." msgstr "" -#: src/patterns/creational/builder.md:115 +#: src/patterns/creational/builder.md:118 msgid "" "[Builder pattern (wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern)" msgstr "" -#: src/patterns/creational/builder.md:116 +#: src/patterns/creational/builder.md:119 msgid "" "[Construction of complex values](https://web.archive.org/web/20210104103000/" "https://rust-lang.github.io/api-guidelines/type-safety.html#c-builder)" @@ -3706,6 +4369,92 @@ msgid "" "2018/08/22/two-kinds-of-invariants.html)" msgstr "" +#: src/patterns/structural/trait-for-bounds.md:1 +msgid "Use custom traits to avoid complex type bounds" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:5 +msgid "" +"Trait bounds can become somewhat unwieldy, especially if one of the `Fn` " +"traits[^fn-traits] is involved and there are specific requirements on the " +"output type. In such cases the introduction of a new trait may help reduce " +"verbosity, eliminate some type parameters and thus increase expressiveness. " +"Such a trait can be accompanied with a generic `impl` for all types " +"satisfying the original bound." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:13 +msgid "" +"Let's imagine some sort of monitoring or information gathering system. The " +"system retrieves values of various types from diverse sources. It may derive " +"from them some sort of status indicating issues. For example, the total " +"amount of free memory should be above a certain theshold, and the user with " +"the id `0` should always be named \"root\"." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:19 +msgid "" +"For management reasons, we probably want type erasure on the top level. " +"However, we also need to provide specific (user configurable) assesments for " +"specific types of data sources (e.g. thresholds and ranges for numerical " +"types). And since sources for these values are diverse, we may choose to " +"supply data sources as closures that return a value when called. Because we " +"are probably getting those values from the operating system, we are likely " +"confronted with operations that may fail." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:27 +msgid "" +"We thus may have settled on the following types and traits for handling " +"specific values:" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:64 +msgid "" +"With these types, we will need to repeat the trait bounds for `G` in at " +"least a few places. Readability suffers, partially due the the fact that the " +"getter returns a `Result`. Introducing a bound for \"getters\" allows a more " +"expressive bound and eliminate one of the type parameters:" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:98 +msgid "" +"Introducing a new trait can help simplify type bounds, particularly via the " +"elimination of type parameters. A good name for the new trait will also make " +"the bound more expressive. The new trait, an abstraction, also offers " +"opportunities in itself, including:" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:103 +msgid "" +"additional, specialized types implementing the new trait (e.g. representing " +"an idendity of some sort) as well as other useful traits such as `Default` " +"and" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:105 +msgid "" +"additional methods, as long as they can be implemented for all relevant " +"types." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:109 +msgid "" +"Introducing new items such as the trait means we need to find an appropriate " +"name and place for it. It also means one more item users of the original " +"functionality need to investigate[^read-docs]. Depending on presentation, it " +"may not be obvious right away that a simple closure may be used as a " +"`Getter` in the example above." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:115 +msgid "i.e. `Fn`, `FnOnce` and `FnMut`" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:117 +msgid "meaning they may need to read more documentation" +msgstr "" + #: src/patterns/ffi/intro.md:1 msgid "FFI Patterns" msgstr "" @@ -4970,7 +5719,8 @@ msgstr "" #: src/functional/generics-type-classes.md:120 msgid "" -"// private module, lest outside users invent their own protocol kinds!\n" +"// Keep the module private to prevent outside users from inventing their own " +"protocols.\n" msgstr "" #: src/functional/generics-type-classes.md:149 diff --git a/po/messages.pot b/po/messages.pot index 9076e933..74ca54e4 100644 --- a/po/messages.pot +++ b/po/messages.pot @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Rust Design Patterns\n" -"POT-Creation-Date: 2025-05-17T14:07:35+09:00\n" +"POT-Creation-Date: 2026-08-11T09:33:34+02:00\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -60,7 +60,7 @@ msgstr "" msgid "On-Stack Dynamic Dispatch" msgstr "" -#: src/SUMMARY.md:14 src/SUMMARY.md:40 +#: src/SUMMARY.md:14 src/SUMMARY.md:41 msgid "Foreign function interface (FFI)" msgstr "" @@ -160,51 +160,55 @@ msgstr "" msgid "Contain unsafety in small modules" msgstr "" -#: src/SUMMARY.md:41 src/patterns/ffi/export.md:1 +#: src/SUMMARY.md:40 +msgid "Avoid complex type bounds with custom traits" +msgstr "" + +#: src/SUMMARY.md:42 src/patterns/ffi/export.md:1 msgid "Object-Based APIs" msgstr "" -#: src/SUMMARY.md:42 src/patterns/ffi/wrappers.md:1 +#: src/SUMMARY.md:43 src/patterns/ffi/wrappers.md:1 msgid "Type Consolidation into Wrappers" msgstr "" -#: src/SUMMARY.md:44 src/anti_patterns/index.md:1 +#: src/SUMMARY.md:45 src/anti_patterns/index.md:1 msgid "Anti-patterns" msgstr "" -#: src/SUMMARY.md:45 src/anti_patterns/borrow_clone.md:1 +#: src/SUMMARY.md:46 src/anti_patterns/borrow_clone.md:1 msgid "Clone to satisfy the borrow checker" msgstr "" -#: src/SUMMARY.md:46 +#: src/SUMMARY.md:47 msgid "`#[deny(warnings)]`" msgstr "" -#: src/SUMMARY.md:47 +#: src/SUMMARY.md:48 msgid "Deref Polymorphism" msgstr "" -#: src/SUMMARY.md:49 +#: src/SUMMARY.md:50 msgid "Functional Programming" msgstr "" -#: src/SUMMARY.md:50 src/functional/paradigms.md:1 +#: src/SUMMARY.md:51 src/functional/paradigms.md:1 msgid "Programming paradigms" msgstr "" -#: src/SUMMARY.md:51 src/functional/generics-type-classes.md:1 +#: src/SUMMARY.md:52 src/functional/generics-type-classes.md:1 msgid "Generics as Type Classes" msgstr "" -#: src/SUMMARY.md:52 +#: src/SUMMARY.md:53 msgid "Functional Optics" msgstr "" -#: src/SUMMARY.md:54 +#: src/SUMMARY.md:55 msgid "Additional Resources" msgstr "" -#: src/SUMMARY.md:55 src/additional_resources/design-principles.md:1 +#: src/SUMMARY.md:56 src/additional_resources/design-principles.md:1 msgid "Design principles" msgstr "" @@ -225,15 +229,21 @@ msgstr "" #: src/intro.md:10 msgid "" -"**2024-03-17**: You can now download the book in PDF format from [this " -"link](https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf)." +"**2025-12-14**: New pattern added: [Use custom traits to avoid complex type " +"bounds](./patterns/structural/trait-for-bounds.md)" msgstr "" -#: src/intro.md:13 -msgid "Design patterns" +#: src/intro.md:12 +msgid "" +"**2024-03-17**: You can now download the [book in PDF " +"format](https://rust-unofficial.github.io/patterns/rust-design-patterns.pdf)." msgstr "" #: src/intro.md:15 +msgid "Design patterns" +msgstr "" + +#: src/intro.md:17 msgid "" "In software development, we often come across problems that share " "similarities regardless of the environment they appear in. Although the " @@ -242,7 +252,7 @@ msgid "" "generically applicable." msgstr "" -#: src/intro.md:20 +#: src/intro.md:22 msgid "" "Design patterns are a collection of reusable and tested solutions to " "recurring problems in engineering. They make our software more modular, " @@ -251,18 +261,18 @@ msgid "" "communication when problem-solving in teams." msgstr "" -#: src/intro.md:26 +#: src/intro.md:28 msgid "" "Keep in mind: Each pattern comes with its own set of trade-offs. It's " "crucial to focus on why you choose a particular pattern rather than just on " "how to implement it.[^1]" msgstr "" -#: src/intro.md:30 src/patterns/index.md:14 +#: src/intro.md:32 src/patterns/index.md:14 msgid "Design patterns in Rust" msgstr "" -#: src/intro.md:32 +#: src/intro.md:34 msgid "" "Rust is not object-oriented, and the combination of all its characteristics, " "such as functional elements, a strong type system, and the borrow checker, " @@ -272,29 +282,30 @@ msgid "" "divided in three main chapters:" msgstr "" -#: src/intro.md:39 +#: src/intro.md:41 msgid "" "[Idioms](./idioms/index.md): guidelines to follow when coding. They are the " "social norms of the community. You should break them only if you have a good " "reason for it." msgstr "" -#: src/intro.md:42 +#: src/intro.md:44 msgid "" "[Design patterns](./patterns/index.md): methods to solve common problems " "when coding." msgstr "" -#: src/intro.md:44 +#: src/intro.md:46 msgid "" "[Anti-patterns](./anti_patterns/index.md): methods to solve common problems " "when coding. However, while design patterns give us benefits, anti-patterns " "create more problems." msgstr "" -#: src/intro.md:48 +#: src/intro.md:50 msgid "" -"https://web.archive.org/web/20240124025806/https://www.infoq.com/podcasts/software-architecture-hard-parts/" +" " +"([Archive](https://web.archive.org/web/20240124025806/https://www.infoq.com/podcasts/software-architecture-hard-parts/))" msgstr "" #: src/translations.md:3 @@ -363,7 +374,8 @@ msgstr "" #: src/patterns/creational/builder.md:3 src/patterns/creational/fold.md:3 #: src/patterns/structural/compose-structs.md:3 #: src/patterns/structural/small-crates.md:3 -#: src/patterns/structural/unsafe-mods.md:3 src/patterns/ffi/export.md:3 +#: src/patterns/structural/unsafe-mods.md:3 +#: src/patterns/structural/trait-for-bounds.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 @@ -405,6 +417,7 @@ msgstr "" #: src/patterns/behavioural/visitor.md:13 src/patterns/creational/builder.md:7 #: src/patterns/creational/fold.md:12 #: src/patterns/structural/compose-structs.md:15 +#: src/patterns/structural/trait-for-bounds.md:11 #: 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" @@ -540,7 +553,7 @@ msgstr "" #: src/patterns/behavioural/newtype.md:94 src/patterns/behavioural/RAII.md:112 #: src/patterns/behavioural/strategy.md:178 #: src/patterns/behavioural/visitor.md:108 -#: src/patterns/creational/builder.md:109 src/patterns/creational/fold.md:109 +#: src/patterns/creational/builder.md:112 src/patterns/creational/fold.md:109 #: src/patterns/structural/small-crates.md:45 #: src/patterns/structural/unsafe-mods.md:33 #: src/anti_patterns/borrow_clone.md:65 src/anti_patterns/deny-warnings.md:101 @@ -609,9 +622,11 @@ msgstr "" #: src/patterns/creational/builder.md:68 #: src/patterns/structural/compose-structs.md:106 #: src/patterns/structural/small-crates.md:13 -#: src/patterns/structural/unsafe-mods.md:12 src/patterns/ffi/export.md:113 -#: src/patterns/ffi/wrappers.md:64 src/anti_patterns/deny-warnings.md:16 -#: src/anti_patterns/deref.md:69 src/functional/generics-type-classes.md:209 +#: src/patterns/structural/unsafe-mods.md:12 +#: src/patterns/structural/trait-for-bounds.md:96 +#: src/patterns/ffi/export.md:113 src/patterns/ffi/wrappers.md:64 +#: src/anti_patterns/deny-warnings.md:16 src/anti_patterns/deref.md:69 +#: src/functional/generics-type-classes.md:209 msgid "Advantages" msgstr "" @@ -631,12 +646,13 @@ msgstr "" #: src/idioms/return-consumed-arg-on-error.md:59 #: src/patterns/behavioural/newtype.md:66 #: src/patterns/behavioural/strategy.md:107 -#: src/patterns/creational/builder.md:76 +#: src/patterns/creational/builder.md:79 #: src/patterns/structural/compose-structs.md:111 #: src/patterns/structural/small-crates.md:22 -#: src/patterns/structural/unsafe-mods.md:18 src/patterns/ffi/export.md:236 -#: src/patterns/ffi/wrappers.md:70 src/anti_patterns/deref.md:81 -#: src/functional/generics-type-classes.md:220 +#: src/patterns/structural/unsafe-mods.md:18 +#: src/patterns/structural/trait-for-bounds.md:107 +#: src/patterns/ffi/export.md:236 src/patterns/ffi/wrappers.md:70 +#: src/anti_patterns/deref.md:81 src/functional/generics-type-classes.md:220 msgid "Disadvantages" msgstr "" @@ -918,7 +934,7 @@ msgstr "" #: src/patterns/behavioural/interpreter.md:105 #: src/patterns/behavioural/newtype.md:74 src/patterns/behavioural/RAII.md:84 #: src/patterns/behavioural/strategy.md:113 -#: src/patterns/behavioural/visitor.md:81 src/patterns/creational/builder.md:81 +#: src/patterns/behavioural/visitor.md:81 src/patterns/creational/builder.md:84 #: src/patterns/creational/fold.md:85 #: src/patterns/structural/compose-structs.md:117 #: src/anti_patterns/deref.md:102 @@ -990,7 +1006,8 @@ msgid "\"exit\"" msgstr "" #: src/idioms/dtor-finally.md:27 -msgid "// The dtor of _exit will run however the function `bar` is exited.\n" +msgid "" +"// The destructor of _exit will run however the function `bar` is exited.\n" msgstr "" #: src/idioms/dtor-finally.md:29 @@ -1571,7 +1588,7 @@ msgstr "" #: src/idioms/ffi/accepting-strings.md:120 msgid "" "Due to the extensive arithmetic required, there is a bug in this version " -"that cases Rust `undefined behaviour`." +"that causes Rust `undefined behaviour`." msgstr "" #: src/idioms/ffi/accepting-strings.md:123 @@ -2028,7 +2045,10 @@ msgid "" msgstr "" #: src/idioms/rustdoc-init.md:35 src/idioms/rustdoc-init.md:40 -#: src/idioms/rustdoc-init.md:68 +#: src/idioms/rustdoc-init.md:68 src/patterns/structural/trait-for-bounds.md:52 +#: src/patterns/structural/trait-for-bounds.md:56 +#: src/patterns/structural/trait-for-bounds.md:60 +#: src/patterns/structural/trait-for-bounds.md:90 msgid "// ...\n" msgstr "" @@ -3168,21 +3188,28 @@ msgid "" "construction." msgstr "" -#: src/patterns/creational/builder.md:78 +#: src/patterns/creational/builder.md:76 +msgid "" +"When you add new fields to the target struct, you can update the builder to " +"leave client code backwards compatible." +msgstr "" + +#: src/patterns/creational/builder.md:81 msgid "" "More complex than creating a struct object directly, or a simple constructor " "function." msgstr "" -#: src/patterns/creational/builder.md:83 +#: src/patterns/creational/builder.md:86 msgid "" "This pattern is seen more frequently in Rust (and for simpler objects) than " -"in many other languages because Rust lacks overloading. Since you can only " -"have a single method with a given name, having multiple constructors is less " -"nice in Rust than in C++, Java, or others." +"in many other languages because Rust lacks overloading and default values " +"for function parameters. Since you can only have a single method with a " +"given name, having multiple constructors is less nice in Rust than in C++, " +"Java, or others." msgstr "" -#: src/patterns/creational/builder.md:88 +#: src/patterns/creational/builder.md:91 msgid "" "This pattern is often used where the builder object is useful in its own " "right, rather than being just a builder. For example, see " @@ -3192,7 +3219,7 @@ msgid "" "process). In these cases, the `T` and `TBuilder` naming pattern is not used." msgstr "" -#: src/patterns/creational/builder.md:95 +#: src/patterns/creational/builder.md:98 msgid "" "The example takes and returns the builder by value. It is often more " "ergonomic (and more efficient) to take and return the builder as a mutable " @@ -3200,33 +3227,33 @@ msgid "" "the advantage that one can write code like" msgstr "" -#: src/patterns/creational/builder.md:107 +#: src/patterns/creational/builder.md:110 msgid "as well as the `FooBuilder::new().a().b().build()` style." msgstr "" -#: src/patterns/creational/builder.md:111 +#: src/patterns/creational/builder.md:114 msgid "" "[Description in the style " "guide](https://web.archive.org/web/20210104103100/https://doc.rust-lang.org/1.12.0/style/ownership/builders.html)" msgstr "" -#: src/patterns/creational/builder.md:112 +#: src/patterns/creational/builder.md:115 msgid "" "[derive_builder](https://crates.io/crates/derive_builder), a crate for " "automatically implementing this pattern while avoiding the boilerplate." msgstr "" -#: src/patterns/creational/builder.md:114 +#: src/patterns/creational/builder.md:117 msgid "" "[Constructor pattern](../../idioms/ctor.md) for when construction is simpler." msgstr "" -#: src/patterns/creational/builder.md:115 +#: src/patterns/creational/builder.md:118 msgid "" "[Builder pattern (wikipedia)](https://en.wikipedia.org/wiki/Builder_pattern)" msgstr "" -#: src/patterns/creational/builder.md:116 +#: src/patterns/creational/builder.md:119 msgid "" "[Construction of complex " "values](https://web.archive.org/web/20210104103000/https://rust-lang.github.io/api-guidelines/type-safety.html#c-builder)" @@ -3648,6 +3675,92 @@ msgid "" "code](https://www.ralfj.de/blog/2018/08/22/two-kinds-of-invariants.html)" msgstr "" +#: src/patterns/structural/trait-for-bounds.md:1 +msgid "Use custom traits to avoid complex type bounds" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:5 +msgid "" +"Trait bounds can become somewhat unwieldy, especially if one of the `Fn` " +"traits[^fn-traits] is involved and there are specific requirements on the " +"output type. In such cases the introduction of a new trait may help reduce " +"verbosity, eliminate some type parameters and thus increase expressiveness. " +"Such a trait can be accompanied with a generic `impl` for all types " +"satisfying the original bound." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:13 +msgid "" +"Let's imagine some sort of monitoring or information gathering system. The " +"system retrieves values of various types from diverse sources. It may derive " +"from them some sort of status indicating issues. For example, the total " +"amount of free memory should be above a certain theshold, and the user with " +"the id `0` should always be named \"root\"." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:19 +msgid "" +"For management reasons, we probably want type erasure on the top level. " +"However, we also need to provide specific (user configurable) assesments for " +"specific types of data sources (e.g. thresholds and ranges for numerical " +"types). And since sources for these values are diverse, we may choose to " +"supply data sources as closures that return a value when called. Because we " +"are probably getting those values from the operating system, we are likely " +"confronted with operations that may fail." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:27 +msgid "" +"We thus may have settled on the following types and traits for handling " +"specific values:" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:64 +msgid "" +"With these types, we will need to repeat the trait bounds for `G` in at " +"least a few places. Readability suffers, partially due the the fact that the " +"getter returns a `Result`. Introducing a bound for \"getters\" allows a more " +"expressive bound and eliminate one of the type parameters:" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:98 +msgid "" +"Introducing a new trait can help simplify type bounds, particularly via the " +"elimination of type parameters. A good name for the new trait will also make " +"the bound more expressive. The new trait, an abstraction, also offers " +"opportunities in itself, including:" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:103 +msgid "" +"additional, specialized types implementing the new trait (e.g. representing " +"an idendity of some sort) as well as other useful traits such as `Default` " +"and" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:105 +msgid "" +"additional methods, as long as they can be implemented for all relevant " +"types." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:109 +msgid "" +"Introducing new items such as the trait means we need to find an appropriate " +"name and place for it. It also means one more item users of the original " +"functionality need to investigate[^read-docs]. Depending on presentation, it " +"may not be obvious right away that a simple closure may be used as a " +"`Getter` in the example above." +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:115 +msgid "i.e. `Fn`, `FnOnce` and `FnMut`" +msgstr "" + +#: src/patterns/structural/trait-for-bounds.md:117 +msgid "meaning they may need to read more documentation" +msgstr "" + #: src/patterns/ffi/intro.md:1 msgid "FFI Patterns" msgstr "" @@ -4913,7 +5026,9 @@ msgid "// no authentication in bootp\n" msgstr "" #: src/functional/generics-type-classes.md:120 -msgid "// private module, lest outside users invent their own protocol kinds!\n" +msgid "" +"// Keep the module private to prevent outside users from inventing their own " +"protocols.\n" msgstr "" #: src/functional/generics-type-classes.md:149