diff --git a/po/es.po b/po/es.po index 266c75ce0a9..c6f63c59f22 100644 --- a/po/es.po +++ b/po/es.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Comprehensive Rust 🦀\n" -"POT-Creation-Date: 2023-09-11\n" +"POT-Creation-Date: 2023-12-02T17:36:47-03:00\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -12,6 +12,10 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 3.4\n" +#: src/SUMMARY.md:1 +msgid "Summary" +msgstr "" + #: src/SUMMARY.md:4 src/index.md:1 msgid "Welcome to Comprehensive Rust 🦀" msgstr "Te damos la bienvenida a Comprehensive Rust 🦀" @@ -52,8 +56,8 @@ msgstr "Ejecutar Cargo a nivel local" msgid "Day 1: Morning" msgstr "Día 1: mañana" -#: src/SUMMARY.md:19 src/SUMMARY.md:79 src/SUMMARY.md:134 src/SUMMARY.md:192 -#: src/SUMMARY.md:218 src/SUMMARY.md:268 +#: src/SUMMARY.md:19 src/SUMMARY.md:80 src/SUMMARY.md:135 src/SUMMARY.md:193 +#: src/SUMMARY.md:219 src/SUMMARY.md:269 msgid "Welcome" msgstr "Te damos la bienvenida" @@ -73,66 +77,72 @@ msgstr "Pequeño ejemplo" msgid "Why Rust?" msgstr "¿Por qué Rust?" -#: src/SUMMARY.md:24 src/why-rust/compile-time.md:1 +#: src/SUMMARY.md:24 src/why-rust/an-example-in-c.md:1 src/credits.md:32 +#, fuzzy +#| msgid "C Example" +msgid "An Example in C" +msgstr "Ejemplo en C" + +#: src/SUMMARY.md:25 src/why-rust/compile-time.md:1 msgid "Compile Time Guarantees" msgstr "Garantías en Tiempo de Compilación" -#: src/SUMMARY.md:25 src/why-rust/runtime.md:1 +#: src/SUMMARY.md:26 src/why-rust/runtime.md:1 msgid "Runtime Guarantees" msgstr "Garantías en Runtime (Tiempo de Ejecución)" -#: src/SUMMARY.md:26 src/why-rust/modern.md:1 +#: src/SUMMARY.md:27 src/why-rust/modern.md:1 msgid "Modern Features" msgstr "Funcionalidades Modernas" -#: src/SUMMARY.md:27 src/basic-syntax.md:1 +#: src/SUMMARY.md:28 src/basic-syntax.md:1 msgid "Basic Syntax" msgstr "Sintaxis básica" -#: src/SUMMARY.md:28 src/basic-syntax/scalar-types.md:1 +#: src/SUMMARY.md:29 src/basic-syntax/scalar-types.md:1 msgid "Scalar Types" msgstr "Tipos escalares" -#: src/SUMMARY.md:29 src/basic-syntax/compound-types.md:1 +#: src/SUMMARY.md:30 src/basic-syntax/compound-types.md:1 msgid "Compound Types" msgstr "Tipos compuestos" -#: src/SUMMARY.md:30 src/basic-syntax/references.md:1 +#: src/SUMMARY.md:31 src/basic-syntax/references.md:1 msgid "References" msgstr "Referencias" -#: src/SUMMARY.md:31 src/basic-syntax/references-dangling.md:1 +#: src/SUMMARY.md:32 src/basic-syntax/references-dangling.md:1 msgid "Dangling References" msgstr "Referencias colgantes" -#: src/SUMMARY.md:32 src/basic-syntax/slices.md:1 +#: src/SUMMARY.md:33 src/basic-syntax/slices.md:1 msgid "Slices" msgstr "Slices" -#: src/SUMMARY.md:33 +#: src/SUMMARY.md:34 msgid "String vs str" msgstr "String o str" -#: src/SUMMARY.md:34 src/basic-syntax/functions.md:1 +#: src/SUMMARY.md:35 src/basic-syntax/functions.md:1 msgid "Functions" msgstr "Funciones" -#: src/SUMMARY.md:35 src/basic-syntax/rustdoc.md:1 +#: src/SUMMARY.md:36 src/basic-syntax/rustdoc.md:1 msgid "Rustdoc" msgstr "Rustdoc" -#: src/SUMMARY.md:36 src/SUMMARY.md:102 src/basic-syntax/methods.md:1 +#: src/SUMMARY.md:37 src/SUMMARY.md:103 src/basic-syntax/methods.md:1 #: src/methods.md:1 msgid "Methods" msgstr "Métodos" -#: src/SUMMARY.md:37 +#: src/SUMMARY.md:38 msgid "Overloading" msgstr "Sobrecarga" -#: src/SUMMARY.md:38 src/SUMMARY.md:71 src/SUMMARY.md:105 src/SUMMARY.md:125 -#: src/SUMMARY.md:154 src/SUMMARY.md:184 src/SUMMARY.md:211 src/SUMMARY.md:232 -#: src/SUMMARY.md:260 src/SUMMARY.md:282 src/SUMMARY.md:303 +#: src/SUMMARY.md:39 src/SUMMARY.md:72 src/SUMMARY.md:106 src/SUMMARY.md:126 +#: src/SUMMARY.md:155 src/SUMMARY.md:185 src/SUMMARY.md:212 src/SUMMARY.md:233 +#: src/SUMMARY.md:261 src/SUMMARY.md:283 src/SUMMARY.md:304 #: src/exercises/android/morning.md:1 src/exercises/bare-metal/morning.md:1 #: src/exercises/bare-metal/afternoon.md:1 #: src/exercises/concurrency/morning.md:1 @@ -140,893 +150,896 @@ msgstr "Sobrecarga" msgid "Exercises" msgstr "Ejercicios" -#: src/SUMMARY.md:39 src/exercises/day-1/implicit-conversions.md:1 +#: src/SUMMARY.md:40 src/exercises/day-1/implicit-conversions.md:1 msgid "Implicit Conversions" msgstr "Conversiones Implícitas" -#: src/SUMMARY.md:40 +#: src/SUMMARY.md:41 msgid "Arrays and for Loops" msgstr "Arrays y Loops for" -#: src/SUMMARY.md:42 +#: src/SUMMARY.md:43 msgid "Day 1: Afternoon" msgstr "Día 1: Tarde" -#: src/SUMMARY.md:44 src/SUMMARY.md:295 src/control-flow.md:1 +#: src/SUMMARY.md:45 src/SUMMARY.md:296 src/control-flow.md:1 msgid "Control Flow" msgstr "Control de Flujo" -#: src/SUMMARY.md:45 src/control-flow/blocks.md:1 +#: src/SUMMARY.md:46 src/control-flow/blocks.md:1 msgid "Blocks" msgstr "Bloques" -#: src/SUMMARY.md:46 +#: src/SUMMARY.md:47 msgid "if expressions" msgstr "expresiones if" -#: src/SUMMARY.md:47 +#: src/SUMMARY.md:48 msgid "for expressions" msgstr "expresiones for" -#: src/SUMMARY.md:48 +#: src/SUMMARY.md:49 msgid "while expressions" msgstr "expresiones while" -#: src/SUMMARY.md:49 +#: src/SUMMARY.md:50 msgid "break & continue" msgstr "break y continue" -#: src/SUMMARY.md:50 +#: src/SUMMARY.md:51 msgid "loop expressions" msgstr "Expresiones loop" -#: src/SUMMARY.md:52 src/basic-syntax/variables.md:1 +#: src/SUMMARY.md:53 src/basic-syntax/variables.md:1 msgid "Variables" msgstr "Variables" -#: src/SUMMARY.md:53 src/basic-syntax/type-inference.md:1 +#: src/SUMMARY.md:54 src/basic-syntax/type-inference.md:1 msgid "Type Inference" msgstr "Inferencia de tipos" -#: src/SUMMARY.md:54 -msgid "static & const" +#: src/SUMMARY.md:55 +#, fuzzy +#| msgid "static & const" +msgid "static & const)" msgstr "static y const" -#: src/SUMMARY.md:55 src/basic-syntax/scopes-shadowing.md:1 +#: src/SUMMARY.md:56 src/basic-syntax/scopes-shadowing.md:1 msgid "Scopes and Shadowing" msgstr "Ámbitos y _Shadowing_" -#: src/SUMMARY.md:56 src/enums.md:1 +#: src/SUMMARY.md:57 src/enums.md:1 msgid "Enums" msgstr "" -#: src/SUMMARY.md:57 src/enums/variant-payloads.md:1 +#: src/SUMMARY.md:58 src/enums/variant-payloads.md:1 msgid "Variant Payloads" msgstr "Payloads Variantes" -#: src/SUMMARY.md:58 src/enums/sizes.md:1 +#: src/SUMMARY.md:59 src/enums/sizes.md:1 msgid "Enum Sizes" msgstr "Tamaños de Enum" -#: src/SUMMARY.md:60 src/control-flow/novel.md:1 +#: src/SUMMARY.md:61 src/control-flow/novel.md:1 #, fuzzy msgid "Novel Control Flow" msgstr "Control de Flujo" -#: src/SUMMARY.md:61 +#: src/SUMMARY.md:62 msgid "if let expressions" msgstr "expresiones if let" -#: src/SUMMARY.md:62 +#: src/SUMMARY.md:63 msgid "while let expressions" msgstr "expresiones while let" -#: src/SUMMARY.md:63 +#: src/SUMMARY.md:64 msgid "match expressions" msgstr "expresiones match" -#: src/SUMMARY.md:65 src/pattern-matching.md:1 +#: src/SUMMARY.md:66 src/SUMMARY.md:74 src/pattern-matching.md:1 msgid "Pattern Matching" msgstr "Correspondencia de Patrones" -#: src/SUMMARY.md:66 src/pattern-matching/destructuring-enums.md:1 +#: src/SUMMARY.md:67 src/pattern-matching/destructuring-enums.md:1 msgid "Destructuring Enums" msgstr "Desestructurando Enums" -#: src/SUMMARY.md:67 src/pattern-matching/destructuring-structs.md:1 +#: src/SUMMARY.md:68 src/pattern-matching/destructuring-structs.md:1 msgid "Destructuring Structs" msgstr "Desestructurando Structs" -#: src/SUMMARY.md:68 src/pattern-matching/destructuring-arrays.md:1 +#: src/SUMMARY.md:69 src/pattern-matching/destructuring-arrays.md:1 msgid "Destructuring Arrays" msgstr "Desestructurando Arrays" -#: src/SUMMARY.md:69 src/pattern-matching/match-guards.md:1 +#: src/SUMMARY.md:70 src/pattern-matching/match-guards.md:1 msgid "Match Guards" msgstr "Guardas de Match" -#: src/SUMMARY.md:72 src/exercises/day-1/luhn.md:1 +#: src/SUMMARY.md:73 src/exercises/day-1/luhn.md:1 #: src/exercises/day-1/solutions-afternoon.md:3 msgid "Luhn Algorithm" msgstr "Algoritmo de Luhn" -#: src/SUMMARY.md:73 -#, fuzzy -msgid "Pattern Matching (TBD)" -msgstr "Correspondencia de Patrones" - -#: src/SUMMARY.md:75 +#: src/SUMMARY.md:76 msgid "Day 2: Morning" msgstr "Día 2: Mañana" -#: src/SUMMARY.md:81 src/memory-management.md:1 +#: src/SUMMARY.md:82 src/memory-management.md:1 msgid "Memory Management" msgstr "Manejo de Memoria" -#: src/SUMMARY.md:82 +#: src/SUMMARY.md:83 msgid "Stack vs Heap" msgstr "" -#: src/SUMMARY.md:83 +#: src/SUMMARY.md:84 msgid "Stack Memory" msgstr "Memoria de la Pila (_Stack_)" -#: src/SUMMARY.md:84 src/memory-management/manual.md:1 +#: src/SUMMARY.md:85 src/memory-management/manual.md:1 msgid "Manual Memory Management" msgstr "Manejo Manual de Memoria" -#: src/SUMMARY.md:85 src/memory-management/scope-based.md:1 +#: src/SUMMARY.md:86 src/memory-management/scope-based.md:1 msgid "Scope-Based Memory Management" msgstr "Manejo de Memoria basado en Scope (ámbitos)" -#: src/SUMMARY.md:86 +#: src/SUMMARY.md:87 msgid "Garbage Collection" msgstr "Recolección de memoria residual" -#: src/SUMMARY.md:87 +#: src/SUMMARY.md:88 msgid "Rust Memory Management" msgstr "Manejo de la Memoria en Rust" -#: src/SUMMARY.md:88 src/ownership.md:1 +#: src/SUMMARY.md:89 src/ownership.md:1 msgid "Ownership" msgstr "Ownership" -#: src/SUMMARY.md:89 src/ownership/move-semantics.md:1 +#: src/SUMMARY.md:90 src/ownership/move-semantics.md:1 msgid "Move Semantics" msgstr "Semántica de movimiento" -#: src/SUMMARY.md:90 src/ownership/moved-strings-rust.md:1 +#: src/SUMMARY.md:91 src/ownership/moved-strings-rust.md:1 msgid "Moved Strings in Rust" msgstr "Cadenas movidas en Rust" -#: src/SUMMARY.md:91 +#: src/SUMMARY.md:92 msgid "Double Frees in Modern C++" msgstr "Double free en código C++ moderno" -#: src/SUMMARY.md:92 src/ownership/moves-function-calls.md:1 +#: src/SUMMARY.md:93 src/ownership/moves-function-calls.md:1 msgid "Moves in Function Calls" msgstr "Movimientos en llamadas de función" -#: src/SUMMARY.md:93 src/ownership/copy-clone.md:1 +#: src/SUMMARY.md:94 src/ownership/copy-clone.md:1 msgid "Copying and Cloning" msgstr "Copiar y clonar" -#: src/SUMMARY.md:94 src/ownership/borrowing.md:1 +#: src/SUMMARY.md:95 src/ownership/borrowing.md:1 msgid "Borrowing" msgstr "Préstamos (_Borrowing_)" -#: src/SUMMARY.md:95 src/ownership/shared-unique-borrows.md:1 +#: src/SUMMARY.md:96 src/ownership/shared-unique-borrows.md:1 msgid "Shared and Unique Borrows" msgstr "Préstamos compartidos y únicos" -#: src/SUMMARY.md:96 src/ownership/lifetimes.md:1 +#: src/SUMMARY.md:97 src/ownership/lifetimes.md:1 msgid "Lifetimes" msgstr "Tiempos de vida" -#: src/SUMMARY.md:97 src/ownership/lifetimes-function-calls.md:1 +#: src/SUMMARY.md:98 src/ownership/lifetimes-function-calls.md:1 msgid "Lifetimes in Function Calls" msgstr "Tiempos de Vida en Llamadas a Función" -#: src/SUMMARY.md:98 src/ownership/lifetimes-data-structures.md:1 +#: src/SUMMARY.md:99 src/ownership/lifetimes-data-structures.md:1 msgid "Lifetimes in Data Structures" msgstr "Tiempos de vida en estructuras de datos" -#: src/SUMMARY.md:99 src/structs.md:1 +#: src/SUMMARY.md:100 src/structs.md:1 msgid "Structs" msgstr "Structs" -#: src/SUMMARY.md:100 src/structs/tuple-structs.md:1 +#: src/SUMMARY.md:101 src/structs/tuple-structs.md:1 msgid "Tuple Structs" msgstr "Estructuras de tuplas" -#: src/SUMMARY.md:101 src/structs/field-shorthand.md:1 +#: src/SUMMARY.md:102 src/structs/field-shorthand.md:1 msgid "Field Shorthand Syntax" msgstr "Sintaxis abreviada de campos" -#: src/SUMMARY.md:103 src/methods/receiver.md:1 +#: src/SUMMARY.md:104 src/methods/receiver.md:1 msgid "Method Receiver" msgstr "Receptor de método" -#: src/SUMMARY.md:104 src/SUMMARY.md:166 src/SUMMARY.md:281 +#: src/SUMMARY.md:105 src/SUMMARY.md:167 src/SUMMARY.md:282 #: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 msgid "Example" msgstr "Ejemplo" -#: src/SUMMARY.md:106 src/exercises/day-2/book-library.md:1 +#: src/SUMMARY.md:107 src/exercises/day-2/book-library.md:1 msgid "Storing Books" msgstr "Almacenar libros" -#: src/SUMMARY.md:107 src/exercises/day-2/health-statistics.md:1 +#: src/SUMMARY.md:108 src/exercises/day-2/health-statistics.md:1 +#: src/exercises/day-2/solutions-morning.md:151 msgid "Health Statistics" msgstr "Estadísticas de salud" -#: src/SUMMARY.md:109 +#: src/SUMMARY.md:110 msgid "Day 2: Afternoon" msgstr "Día 2: tarde" -#: src/SUMMARY.md:111 src/std.md:1 +#: src/SUMMARY.md:112 src/std.md:1 msgid "Standard Library" msgstr "Biblioteca estándar" -#: src/SUMMARY.md:112 +#: src/SUMMARY.md:113 msgid "Option and Result" msgstr "Option y Result" -#: src/SUMMARY.md:113 src/std/string.md:1 +#: src/SUMMARY.md:114 src/std/string.md:1 msgid "String" msgstr "String" -#: src/SUMMARY.md:114 +#: src/SUMMARY.md:115 msgid "Vec" msgstr "Vec" -#: src/SUMMARY.md:115 +#: src/SUMMARY.md:116 msgid "HashMap" msgstr "HashMap" -#: src/SUMMARY.md:116 +#: src/SUMMARY.md:117 msgid "Box" msgstr "Box" -#: src/SUMMARY.md:117 +#: src/SUMMARY.md:118 msgid "Recursive Data Types" msgstr "Tipos de datos recursivos" -#: src/SUMMARY.md:118 src/std/box-niche.md:1 +#: src/SUMMARY.md:119 src/std/box-niche.md:1 msgid "Niche Optimization" msgstr "Optimización de la Memoria" -#: src/SUMMARY.md:119 +#: src/SUMMARY.md:120 msgid "Rc" msgstr "Rc" -#: src/SUMMARY.md:120 +#: src/SUMMARY.md:121 msgid "Cell/RefCell" msgstr "" -#: src/SUMMARY.md:121 src/modules.md:1 +#: src/SUMMARY.md:122 src/modules.md:1 msgid "Modules" msgstr "Módulos" -#: src/SUMMARY.md:122 src/modules/visibility.md:1 +#: src/SUMMARY.md:123 src/modules/visibility.md:1 msgid "Visibility" msgstr "Visibilidad" -#: src/SUMMARY.md:123 src/modules/paths.md:1 +#: src/SUMMARY.md:124 src/modules/paths.md:1 msgid "Paths" msgstr "Rutas" -#: src/SUMMARY.md:124 src/modules/filesystem.md:1 +#: src/SUMMARY.md:125 src/modules/filesystem.md:1 msgid "Filesystem Hierarchy" msgstr "Jerarquía del sistema de archivos" -#: src/SUMMARY.md:126 src/exercises/day-2/iterators-and-ownership.md:1 +#: src/SUMMARY.md:127 src/exercises/day-2/iterators-and-ownership.md:1 msgid "Iterators and Ownership" msgstr "Iteradores y Ownership (Propiedad)" -#: src/SUMMARY.md:127 src/exercises/day-2/strings-iterators.md:1 +#: src/SUMMARY.md:128 src/exercises/day-2/strings-iterators.md:1 #: src/exercises/day-2/solutions-afternoon.md:3 msgid "Strings and Iterators" msgstr "Cadenas e Iteradores" -#: src/SUMMARY.md:130 +#: src/SUMMARY.md:131 msgid "Day 3: Morning" msgstr "Día 3: Mañana" -#: src/SUMMARY.md:135 src/generics.md:1 +#: src/SUMMARY.md:136 src/generics.md:1 msgid "Generics" msgstr "Genéricos" -#: src/SUMMARY.md:136 src/generics/data-types.md:1 +#: src/SUMMARY.md:137 src/generics/data-types.md:1 msgid "Generic Data Types" msgstr "Tipos de Datos Genéricos" -#: src/SUMMARY.md:137 src/generics/methods.md:1 +#: src/SUMMARY.md:138 src/generics/methods.md:1 msgid "Generic Methods" msgstr "Métodos Genéricos" -#: src/SUMMARY.md:138 src/generics/monomorphization.md:1 +#: src/SUMMARY.md:139 src/generics/monomorphization.md:1 msgid "Monomorphization" msgstr "Monomorfización" -#: src/SUMMARY.md:139 src/traits.md:1 +#: src/SUMMARY.md:140 src/traits.md:1 msgid "Traits" msgstr "Traits" -#: src/SUMMARY.md:140 src/traits/trait-objects.md:1 +#: src/SUMMARY.md:141 src/traits/trait-objects.md:1 msgid "Trait Objects" msgstr "Objetos Trait" -#: src/SUMMARY.md:141 src/traits/deriving-traits.md:1 +#: src/SUMMARY.md:142 src/traits/deriving-traits.md:1 msgid "Deriving Traits" msgstr "Derivación de Traits" -#: src/SUMMARY.md:142 src/traits/default-methods.md:1 +#: src/SUMMARY.md:143 src/traits/default-methods.md:1 msgid "Default Methods" msgstr "Métodos por Default" -#: src/SUMMARY.md:143 src/traits/trait-bounds.md:1 +#: src/SUMMARY.md:144 src/traits/trait-bounds.md:1 msgid "Trait Bounds" msgstr "Trait Bounds" -#: src/SUMMARY.md:144 +#: src/SUMMARY.md:145 msgid "impl Trait" msgstr "impl Trait" -#: src/SUMMARY.md:145 src/traits/important-traits.md:1 +#: src/SUMMARY.md:146 src/traits/important-traits.md:1 msgid "Important Traits" msgstr "Traits Importantes" -#: src/SUMMARY.md:146 +#: src/SUMMARY.md:147 msgid "Iterator" msgstr "Iteradores" -#: src/SUMMARY.md:147 src/traits/from-iterator.md:1 +#: src/SUMMARY.md:148 src/traits/from-iterator.md:1 msgid "FromIterator" msgstr "FromIterator" -#: src/SUMMARY.md:148 +#: src/SUMMARY.md:149 msgid "From and Into" msgstr "From e Into" -#: src/SUMMARY.md:149 +#: src/SUMMARY.md:150 msgid "Read and Write" msgstr "Read y Write" -#: src/SUMMARY.md:150 +#: src/SUMMARY.md:151 msgid "Drop" msgstr "" -#: src/SUMMARY.md:151 +#: src/SUMMARY.md:152 msgid "Default" msgstr "" -#: src/SUMMARY.md:152 +#: src/SUMMARY.md:153 msgid "Operators: Add, Mul, ..." msgstr "Operadores: Add, Mul, …." -#: src/SUMMARY.md:153 +#: src/SUMMARY.md:154 msgid "Closures: Fn, FnMut, FnOnce" msgstr "" -#: src/SUMMARY.md:155 src/exercises/day-3/simple-gui.md:1 -#: src/exercises/day-3/solutions-morning.md:3 +#: src/SUMMARY.md:156 msgid "A Simple GUI Library" msgstr "Una Biblioteca GUI sencilla" -#: src/SUMMARY.md:156 src/exercises/day-3/solutions-morning.md:175 +#: src/SUMMARY.md:157 src/exercises/day-3/solutions-morning.md:142 msgid "Points and Polygons" msgstr "Puntos y Polígonos" -#: src/SUMMARY.md:158 +#: src/SUMMARY.md:159 msgid "Day 3: Afternoon" msgstr "Día 3: Tarde" -#: src/SUMMARY.md:160 src/error-handling.md:1 +#: src/SUMMARY.md:161 src/error-handling.md:1 msgid "Error Handling" msgstr "Manejo de Errores" -#: src/SUMMARY.md:161 src/error-handling/panics.md:1 +#: src/SUMMARY.md:162 src/error-handling/panics.md:1 msgid "Panics" msgstr "" -#: src/SUMMARY.md:162 +#: src/SUMMARY.md:163 msgid "Catching Stack Unwinding" msgstr "Catching Stack Unwinding" -#: src/SUMMARY.md:163 +#: src/SUMMARY.md:164 msgid "Structured Error Handling" msgstr "Manejo de Errores Estructurado" -#: src/SUMMARY.md:164 +#: src/SUMMARY.md:165 msgid "Propagating Errors with ?" msgstr "Propagación de Errores con ?" -#: src/SUMMARY.md:165 src/error-handling/converting-error-types.md:1 +#: src/SUMMARY.md:166 src/error-handling/converting-error-types.md:1 #: src/error-handling/converting-error-types-example.md:1 msgid "Converting Error Types" msgstr "Conversión de Tipos de Errores" -#: src/SUMMARY.md:167 src/error-handling/deriving-error-enums.md:1 +#: src/SUMMARY.md:168 src/error-handling/deriving-error-enums.md:1 msgid "Deriving Error Enums" msgstr "Derivación de Enums de Error" -#: src/SUMMARY.md:168 src/error-handling/dynamic-errors.md:1 +#: src/SUMMARY.md:169 src/error-handling/dynamic-errors.md:1 msgid "Dynamic Error Types" msgstr "Tipos de Errores Dinámicos" -#: src/SUMMARY.md:169 src/error-handling/error-contexts.md:1 +#: src/SUMMARY.md:170 src/error-handling/error-contexts.md:1 msgid "Adding Context to Errors" msgstr "Añadir Contexto a los Errores" -#: src/SUMMARY.md:170 src/testing.md:1 +#: src/SUMMARY.md:171 src/testing.md:1 msgid "Testing" msgstr "Probando" -#: src/SUMMARY.md:171 src/testing/unit-tests.md:1 +#: src/SUMMARY.md:172 src/testing/unit-tests.md:1 msgid "Unit Tests" msgstr "Pruebas Unitarias" -#: src/SUMMARY.md:172 src/testing/test-modules.md:1 +#: src/SUMMARY.md:173 src/testing/test-modules.md:1 msgid "Test Modules" msgstr "Módulos de Pruebas" -#: src/SUMMARY.md:173 src/testing/doc-tests.md:1 +#: src/SUMMARY.md:174 src/testing/doc-tests.md:1 msgid "Documentation Tests" msgstr "Pruebas de Documentación" -#: src/SUMMARY.md:174 src/testing/integration-tests.md:1 +#: src/SUMMARY.md:175 src/testing/integration-tests.md:1 msgid "Integration Tests" msgstr "Pruebas de Integración" -#: src/SUMMARY.md:175 src/bare-metal/useful-crates.md:1 +#: src/SUMMARY.md:176 src/bare-metal/useful-crates.md:1 msgid "Useful crates" msgstr "Crates Útiles" -#: src/SUMMARY.md:176 src/unsafe.md:1 +#: src/SUMMARY.md:177 src/unsafe.md:1 msgid "Unsafe Rust" msgstr "Unsafe Rust" -#: src/SUMMARY.md:177 src/unsafe/raw-pointers.md:1 +#: src/SUMMARY.md:178 src/unsafe/raw-pointers.md:1 msgid "Dereferencing Raw Pointers" msgstr "Dereferenciación de Punteros Sin Formato" -#: src/SUMMARY.md:178 src/unsafe/mutable-static-variables.md:1 +#: src/SUMMARY.md:179 src/unsafe/mutable-static-variables.md:1 msgid "Mutable Static Variables" msgstr "Variables Estáticas Mutables" -#: src/SUMMARY.md:179 src/unsafe/unions.md:1 +#: src/SUMMARY.md:180 src/unsafe/unions.md:1 msgid "Unions" msgstr "Uniones" -#: src/SUMMARY.md:180 src/unsafe/calling-unsafe-functions.md:1 +#: src/SUMMARY.md:181 src/unsafe/calling-unsafe-functions.md:1 msgid "Calling Unsafe Functions" msgstr "Llamar Funciones Unsafe (Inseguras)" -#: src/SUMMARY.md:181 src/unsafe/writing-unsafe-functions.md:1 +#: src/SUMMARY.md:182 src/unsafe/writing-unsafe-functions.md:1 msgid "Writing Unsafe Functions" msgstr "Escribir Funciones Unsafe (Inseguras)" -#: src/SUMMARY.md:182 +#: src/SUMMARY.md:183 msgid "Extern Functions" msgstr "Funciones Externas" -#: src/SUMMARY.md:183 src/unsafe/unsafe-traits.md:1 +#: src/SUMMARY.md:184 src/unsafe/unsafe-traits.md:1 msgid "Implementing Unsafe Traits" msgstr "Implementación de Traits Unsafe (Inseguras) " -#: src/SUMMARY.md:185 src/exercises/day-3/safe-ffi-wrapper.md:1 +#: src/SUMMARY.md:186 src/exercises/day-3/safe-ffi-wrapper.md:1 #: src/exercises/day-3/solutions-afternoon.md:3 msgid "Safe FFI Wrapper" msgstr "Envoltorio de FFI Seguro" -#: src/SUMMARY.md:188 src/SUMMARY.md:258 src/bare-metal/android.md:1 +#: src/SUMMARY.md:189 src/SUMMARY.md:259 src/bare-metal/android.md:1 msgid "Android" msgstr "" -#: src/SUMMARY.md:193 src/android/setup.md:1 +#: src/SUMMARY.md:194 src/android/setup.md:1 msgid "Setup" msgstr "Configurar" -#: src/SUMMARY.md:194 src/android/build-rules.md:1 +#: src/SUMMARY.md:195 src/android/build-rules.md:1 msgid "Build Rules" msgstr "Reglas de Compilación (Build)" -#: src/SUMMARY.md:195 +#: src/SUMMARY.md:196 msgid "Binary" msgstr "Binarios" -#: src/SUMMARY.md:196 +#: src/SUMMARY.md:197 msgid "Library" msgstr "Biblioteca" -#: src/SUMMARY.md:197 src/android/aidl.md:1 +#: src/SUMMARY.md:198 src/android/aidl.md:1 msgid "AIDL" msgstr "" -#: src/SUMMARY.md:198 +#: src/SUMMARY.md:199 msgid "Interface" msgstr "Interfaz" -#: src/SUMMARY.md:199 +#: src/SUMMARY.md:200 msgid "Implementation" msgstr "Implementación" -#: src/SUMMARY.md:200 +#: src/SUMMARY.md:201 msgid "Server" msgstr "Servidor" -#: src/SUMMARY.md:201 src/android/aidl/deploy.md:1 +#: src/SUMMARY.md:202 src/android/aidl/deploy.md:1 msgid "Deploy" msgstr "Despliegue" -#: src/SUMMARY.md:202 +#: src/SUMMARY.md:203 msgid "Client" msgstr "Cliente" -#: src/SUMMARY.md:203 src/android/aidl/changing.md:1 +#: src/SUMMARY.md:204 src/android/aidl/changing.md:1 msgid "Changing API" msgstr "Cambio de API" -#: src/SUMMARY.md:204 src/SUMMARY.md:248 src/android/logging.md:1 +#: src/SUMMARY.md:205 src/SUMMARY.md:249 src/android/logging.md:1 #: src/bare-metal/aps/logging.md:1 msgid "Logging" msgstr "Almacenamiento de registros" -#: src/SUMMARY.md:205 src/android/interoperability.md:1 +#: src/SUMMARY.md:206 src/android/interoperability.md:1 msgid "Interoperability" msgstr "Interoperabilidad" -#: src/SUMMARY.md:206 +#: src/SUMMARY.md:207 msgid "With C" msgstr "Con C" -#: src/SUMMARY.md:207 +#: src/SUMMARY.md:208 msgid "Calling C with Bindgen" msgstr "Llamar a C con Bindgen" -#: src/SUMMARY.md:208 +#: src/SUMMARY.md:209 msgid "Calling Rust from C" msgstr "Llamar a Rust desde C" -#: src/SUMMARY.md:209 src/android/interoperability/cpp.md:1 -msgid "With C++" +#: src/SUMMARY.md:210 +#, fuzzy +#| msgid "With C++" +msgid "With C++)" msgstr "Con C++" -#: src/SUMMARY.md:210 +#: src/SUMMARY.md:211 msgid "With Java" msgstr "Con Java" -#: src/SUMMARY.md:214 +#: src/SUMMARY.md:215 msgid "Bare Metal: Morning" msgstr "Bare Metal: mañana" -#: src/SUMMARY.md:219 +#: src/SUMMARY.md:220 msgid "no_std" msgstr "no_std" -#: src/SUMMARY.md:220 +#: src/SUMMARY.md:221 msgid "A Minimal Example" msgstr "Un Pequeño Ejemplo" -#: src/SUMMARY.md:221 +#: src/SUMMARY.md:222 msgid "alloc" msgstr "alloc" -#: src/SUMMARY.md:222 src/bare-metal/microcontrollers.md:1 +#: src/SUMMARY.md:223 src/bare-metal/microcontrollers.md:1 msgid "Microcontrollers" msgstr "Microcontroladores" -#: src/SUMMARY.md:223 src/bare-metal/microcontrollers/mmio.md:1 +#: src/SUMMARY.md:224 src/bare-metal/microcontrollers/mmio.md:1 msgid "Raw MMIO" msgstr "MMIO sin procesar" -#: src/SUMMARY.md:224 +#: src/SUMMARY.md:225 msgid "PACs" msgstr "PAC" -#: src/SUMMARY.md:225 +#: src/SUMMARY.md:226 msgid "HAL Crates" msgstr "Crates HAL" -#: src/SUMMARY.md:226 +#: src/SUMMARY.md:227 msgid "Board Support Crates" msgstr "Crates de Soporte de Placa" -#: src/SUMMARY.md:227 +#: src/SUMMARY.md:228 msgid "The Type State Pattern" msgstr "El Patrón de Tipo de Estado" -#: src/SUMMARY.md:228 +#: src/SUMMARY.md:229 msgid "embedded-hal" msgstr "embedded-hal" -#: src/SUMMARY.md:229 +#: src/SUMMARY.md:230 msgid "probe-rs, cargo-embed" msgstr "probe-rs, cargo-embed" -#: src/SUMMARY.md:230 src/bare-metal/microcontrollers/debugging.md:1 +#: src/SUMMARY.md:231 src/bare-metal/microcontrollers/debugging.md:1 msgid "Debugging" msgstr "Depuración" -#: src/SUMMARY.md:231 src/SUMMARY.md:251 +#: src/SUMMARY.md:232 src/SUMMARY.md:252 msgid "Other Projects" msgstr "Otros proyectos" -#: src/SUMMARY.md:233 src/exercises/bare-metal/compass.md:1 +#: src/SUMMARY.md:234 src/exercises/bare-metal/compass.md:1 #: src/exercises/bare-metal/solutions-morning.md:3 msgid "Compass" msgstr "Brújula" -#: src/SUMMARY.md:235 +#: src/SUMMARY.md:236 msgid "Bare Metal: Afternoon" msgstr "Bare Metal: tarde" -#: src/SUMMARY.md:237 +#: src/SUMMARY.md:238 msgid "Application Processors" msgstr "Procesadores de aplicaciones" -#: src/SUMMARY.md:238 src/bare-metal/aps/entry-point.md:1 +#: src/SUMMARY.md:239 src/bare-metal/aps/entry-point.md:1 msgid "Getting Ready to Rust" msgstr "Iniciación a Rust" -#: src/SUMMARY.md:239 +#: src/SUMMARY.md:240 msgid "Inline Assembly" msgstr "Ensamblador en línea" -#: src/SUMMARY.md:240 +#: src/SUMMARY.md:241 msgid "MMIO" msgstr "MMIO" -#: src/SUMMARY.md:241 +#: src/SUMMARY.md:242 msgid "Let's Write a UART Driver" msgstr "Escribir un controlador UART" -#: src/SUMMARY.md:242 +#: src/SUMMARY.md:243 msgid "More Traits" msgstr "Más traits" -#: src/SUMMARY.md:243 +#: src/SUMMARY.md:244 msgid "A Better UART Driver" msgstr "Un controlador UART mejor" -#: src/SUMMARY.md:244 src/bare-metal/aps/better-uart/bitflags.md:1 +#: src/SUMMARY.md:245 src/bare-metal/aps/better-uart/bitflags.md:1 msgid "Bitflags" msgstr "Bitflags" -#: src/SUMMARY.md:245 +#: src/SUMMARY.md:246 msgid "Multiple Registers" msgstr "Varios registros" -#: src/SUMMARY.md:246 src/bare-metal/aps/better-uart/driver.md:1 +#: src/SUMMARY.md:247 src/bare-metal/aps/better-uart/driver.md:1 msgid "Driver" msgstr "Conductor" -#: src/SUMMARY.md:247 src/SUMMARY.md:249 +#: src/SUMMARY.md:248 src/SUMMARY.md:250 msgid "Using It" msgstr "Cómo usarlo" -#: src/SUMMARY.md:250 src/bare-metal/aps/exceptions.md:1 +#: src/SUMMARY.md:251 src/bare-metal/aps/exceptions.md:1 msgid "Exceptions" msgstr "Excepciones" -#: src/SUMMARY.md:252 +#: src/SUMMARY.md:253 msgid "Useful Crates" msgstr "Crates útiles" -#: src/SUMMARY.md:253 +#: src/SUMMARY.md:254 msgid "zerocopy" msgstr "zerocopy" -#: src/SUMMARY.md:254 +#: src/SUMMARY.md:255 msgid "aarch64-paging" msgstr "aarch64-paging" -#: src/SUMMARY.md:255 +#: src/SUMMARY.md:256 msgid "buddy_system_allocator" msgstr "buddy_system_allocator" -#: src/SUMMARY.md:256 +#: src/SUMMARY.md:257 msgid "tinyvec" msgstr "tinyvec" -#: src/SUMMARY.md:257 +#: src/SUMMARY.md:258 msgid "spin" msgstr "girar" -#: src/SUMMARY.md:259 src/bare-metal/android/vmbase.md:1 +#: src/SUMMARY.md:260 src/bare-metal/android/vmbase.md:1 msgid "vmbase" msgstr "vmbase" -#: src/SUMMARY.md:261 +#: src/SUMMARY.md:262 msgid "RTC Driver" msgstr "Controlador RTC" -#: src/SUMMARY.md:264 +#: src/SUMMARY.md:265 msgid "Concurrency: Morning" msgstr "Concurrencia: mañana" -#: src/SUMMARY.md:269 src/concurrency/threads.md:1 +#: src/SUMMARY.md:270 src/concurrency/threads.md:1 msgid "Threads" msgstr "Hilos" -#: src/SUMMARY.md:270 src/concurrency/scoped-threads.md:1 +#: src/SUMMARY.md:271 src/concurrency/scoped-threads.md:1 msgid "Scoped Threads" msgstr "Hilos con ámbito" -#: src/SUMMARY.md:271 src/concurrency/channels.md:1 +#: src/SUMMARY.md:272 src/concurrency/channels.md:1 msgid "Channels" msgstr "Canales" -#: src/SUMMARY.md:272 src/concurrency/channels/unbounded.md:1 +#: src/SUMMARY.md:273 src/concurrency/channels/unbounded.md:1 msgid "Unbounded Channels" msgstr "Canales sin límites" -#: src/SUMMARY.md:273 src/concurrency/channels/bounded.md:1 +#: src/SUMMARY.md:274 src/concurrency/channels/bounded.md:1 msgid "Bounded Channels" msgstr "Canales delimitados" -#: src/SUMMARY.md:274 +#: src/SUMMARY.md:275 msgid "Send and Sync" msgstr "Send y Sync" -#: src/SUMMARY.md:274 +#: src/SUMMARY.md:276 msgid "Send" msgstr "Send" -#: src/SUMMARY.md:274 +#: src/SUMMARY.md:277 msgid "Sync" msgstr "Sync" -#: src/SUMMARY.md:277 src/concurrency/send-sync/examples.md:1 +#: src/SUMMARY.md:278 src/concurrency/send-sync/examples.md:1 msgid "Examples" msgstr "Ejemplos" -#: src/SUMMARY.md:278 src/concurrency/shared_state.md:1 +#: src/SUMMARY.md:279 src/concurrency/shared_state.md:1 msgid "Shared State" msgstr "Estado compartido" -#: src/SUMMARY.md:279 +#: src/SUMMARY.md:280 msgid "Arc" msgstr "Arc" -#: src/SUMMARY.md:280 +#: src/SUMMARY.md:281 msgid "Mutex" msgstr "Mutex" -#: src/SUMMARY.md:283 src/SUMMARY.md:304 +#: src/SUMMARY.md:284 src/SUMMARY.md:305 #: src/exercises/concurrency/dining-philosophers.md:1 #: src/exercises/concurrency/solutions-morning.md:3 msgid "Dining Philosophers" msgstr "La cena de los filósofos" -#: src/SUMMARY.md:284 src/exercises/concurrency/link-checker.md:1 +#: src/SUMMARY.md:285 src/exercises/concurrency/link-checker.md:1 msgid "Multi-threaded Link Checker" msgstr "Comprobador de enlaces multihilo" -#: src/SUMMARY.md:286 +#: src/SUMMARY.md:287 msgid "Concurrency: Afternoon" msgstr "Concurrencia: tarde" -#: src/SUMMARY.md:288 +#: src/SUMMARY.md:289 msgid "Async Basics" msgstr "Conceptos básicos de Async" -#: src/SUMMARY.md:289 +#: src/SUMMARY.md:290 msgid "async/await" msgstr "async / await" -#: src/SUMMARY.md:290 src/async/futures.md:1 +#: src/SUMMARY.md:291 src/async/futures.md:1 msgid "Futures" msgstr "Future" -#: src/SUMMARY.md:291 src/async/runtimes.md:1 +#: src/SUMMARY.md:292 src/async/runtimes.md:1 msgid "Runtimes" msgstr "Runtimes (Tiempos de Ejecución)" -#: src/SUMMARY.md:292 src/async/runtimes/tokio.md:1 +#: src/SUMMARY.md:293 src/async/runtimes/tokio.md:1 msgid "Tokio" msgstr "Tokio" -#: src/SUMMARY.md:293 src/exercises/concurrency/link-checker.md:126 +#: src/SUMMARY.md:294 src/exercises/concurrency/link-checker.md:126 #: src/async/tasks.md:1 src/exercises/concurrency/chat-app.md:143 msgid "Tasks" msgstr "Tasks" -#: src/SUMMARY.md:294 src/async/channels.md:1 +#: src/SUMMARY.md:295 src/async/channels.md:1 msgid "Async Channels" msgstr "Canales asíncronos" -#: src/SUMMARY.md:296 src/async/control-flow/join.md:1 +#: src/SUMMARY.md:297 src/async/control-flow/join.md:1 msgid "Join" msgstr "Unir" -#: src/SUMMARY.md:297 src/async/control-flow/select.md:1 +#: src/SUMMARY.md:298 src/async/control-flow/select.md:1 msgid "Select" msgstr "Seleccionar" -#: src/SUMMARY.md:298 +#: src/SUMMARY.md:299 msgid "Pitfalls" msgstr "Inconvenientes" -#: src/SUMMARY.md:299 +#: src/SUMMARY.md:300 msgid "Blocking the Executor" msgstr "Bloqueo del ejecutor" -#: src/SUMMARY.md:300 src/async/pitfalls/pin.md:1 +#: src/SUMMARY.md:301 src/async/pitfalls/pin.md:1 msgid "Pin" msgstr "Fijar" -#: src/SUMMARY.md:301 src/async/pitfalls/async-traits.md:1 +#: src/SUMMARY.md:302 src/async/pitfalls/async-traits.md:1 msgid "Async Traits" msgstr "Traits asíncronos" -#: src/SUMMARY.md:302 src/async/pitfalls/cancellation.md:1 +#: src/SUMMARY.md:303 src/async/pitfalls/cancellation.md:1 msgid "Cancellation" msgstr "Cancelación" -#: src/SUMMARY.md:305 src/exercises/concurrency/chat-app.md:1 -#: src/exercises/concurrency/solutions-afternoon.md:119 +#: src/SUMMARY.md:306 src/exercises/concurrency/chat-app.md:1 +#: src/exercises/concurrency/solutions-afternoon.md:95 msgid "Broadcast Chat Application" msgstr "Aplicación de chat de difusión" -#: src/SUMMARY.md:308 +#: src/SUMMARY.md:309 msgid "Final Words" msgstr "Conclusiones" -#: src/SUMMARY.md:312 src/thanks.md:1 +#: src/SUMMARY.md:313 src/thanks.md:1 msgid "Thanks!" msgstr "Gracias." -#: src/SUMMARY.md:313 +#: src/SUMMARY.md:314 src/glossary.md:1 +msgid "Glossary" +msgstr "" + +#: src/SUMMARY.md:315 msgid "Other Resources" msgstr "Otros recursos" -#: src/SUMMARY.md:314 src/credits.md:1 +#: src/SUMMARY.md:316 src/credits.md:1 msgid "Credits" msgstr "Créditos" -#: src/SUMMARY.md:317 src/exercises/solutions.md:1 +#: src/SUMMARY.md:319 src/SUMMARY.md:323 src/exercises/solutions.md:1 msgid "Solutions" msgstr "Soluciones" -#: src/SUMMARY.md:322 +#: src/SUMMARY.md:324 msgid "Day 1 Morning" msgstr "Día 1: mañana" -#: src/SUMMARY.md:323 +#: src/SUMMARY.md:325 msgid "Day 1 Afternoon" msgstr "Día 1: tarde" -#: src/SUMMARY.md:324 +#: src/SUMMARY.md:326 msgid "Day 2 Morning" msgstr "Día 2: mañana" -#: src/SUMMARY.md:325 +#: src/SUMMARY.md:327 msgid "Day 2 Afternoon" msgstr "Día 2: tarde" -#: src/SUMMARY.md:326 +#: src/SUMMARY.md:328 msgid "Day 3 Morning" msgstr "Día 3: mañana" -#: src/SUMMARY.md:327 +#: src/SUMMARY.md:329 msgid "Day 3 Afternoon" msgstr "Día 3: tarde" -#: src/SUMMARY.md:328 +#: src/SUMMARY.md:330 msgid "Bare Metal Rust Morning" msgstr "Rust Bare Metal: mañana" -#: src/SUMMARY.md:329 src/exercises/bare-metal/solutions-afternoon.md:1 +#: src/SUMMARY.md:331 src/exercises/bare-metal/solutions-afternoon.md:1 msgid "Bare Metal Rust Afternoon" msgstr "Rust Bare Metal: tarde" -#: src/SUMMARY.md:330 +#: src/SUMMARY.md:332 msgid "Concurrency Morning" msgstr "Concurrencia: mañana" -#: src/SUMMARY.md:331 +#: src/SUMMARY.md:333 msgid "Concurrency Afternoon" msgstr "Concurrencia: tarde" @@ -1448,22 +1461,6 @@ msgstr "" "dependencias. A continuación, podrás copiar y pegar los ejemplos en `src/" "main.rs` para experimentar con ellos:" -#: src/running-the-course/course-structure.md:57 -msgid "" -"```shell\n" -"cargo init concurrency\n" -"cd concurrency\n" -"cargo add tokio --features full\n" -"cargo run\n" -"```" -msgstr "" -"```shell\n" -"cargo init concurrency\n" -"cd concurrency\n" -"cargo add tokio --features full\n" -"cargo run\n" -"```" - #: src/running-the-course/course-structure.md:64 msgid "Format" msgstr "Formato" @@ -1524,28 +1521,43 @@ msgstr "" msgid "" "[Brazilian Portuguese](https://google.github.io/comprehensive-rust/pt-BR/) " "by [@rastringer](https://github.com/rastringer), [@hugojacob](https://github." -"com/hugojacob), [@joaovicmendes](https://github.com/joaovicmendes) and " +"com/hugojacob), [@joaovicmendes](https://github.com/joaovicmendes), and " "[@henrif75](https://github.com/henrif75)." msgstr "" #: src/running-the-course/translations.md:7 msgid "" +"[Chinese (Simplified)](https://google.github.io/comprehensive-rust/zh-CN/) " +"by [@suetfei](https://github.com/suetfei), [@wnghl](https://github.com/" +"wnghl), [@anlunx](https://github.com/anlunx), [@kongy](https://github.com/" +"kongy), [@noahdragon](https://github.com/noahdragon), [@superwhd](https://" +"github.com/superwhd), and [@SketchK](https://github.com/SketchK)." +msgstr "" + +#: src/running-the-course/translations.md:8 +msgid "" "[Korean](https://google.github.io/comprehensive-rust/ko/) by [@keispace]" -"(https://github.com/keispace), [@jiyongp](https://github.com/jiyongp) and " +"(https://github.com/keispace), [@jiyongp](https://github.com/jiyongp), and " "[@jooyunghan](https://github.com/jooyunghan)." msgstr "" #: src/running-the-course/translations.md:9 msgid "" +"[Spanish](https://google.github.io/comprehensive-rust/es/) by [@deavid]" +"(https://github.com/deavid)." +msgstr "" + +#: src/running-the-course/translations.md:11 +msgid "" "Use the language picker in the top-right corner to switch between languages." msgstr "" "Cambia el idioma con el selector situado en la esquina superior derecha." -#: src/running-the-course/translations.md:11 +#: src/running-the-course/translations.md:13 msgid "Incomplete Translations" msgstr "Traducciones Incompletas" -#: src/running-the-course/translations.md:13 +#: src/running-the-course/translations.md:15 msgid "" "There is a large number of in-progress translations. We link to the most " "recently updated translations:" @@ -1553,32 +1565,40 @@ msgstr "" "Hay muchas traducciones todavía en curso. A continuación, incluimos enlaces " "a las traducciones más actualizadas:" -#: src/running-the-course/translations.md:16 +#: src/running-the-course/translations.md:18 msgid "" "[Bengali](https://google.github.io/comprehensive-rust/bn/) by [@raselmandol]" "(https://github.com/raselmandol)." msgstr "" -#: src/running-the-course/translations.md:17 +#: src/running-the-course/translations.md:19 +msgid "" +"[Chinese (Traditional)](https://google.github.io/comprehensive-rust/zh-TW/) " +"by [@hueich](https://github.com/hueich), [@victorhsieh](https://github.com/" +"victorhsieh), [@mingyc](https://github.com/mingyc), and [@johnathan79717]" +"(https://github.com/johnathan79717)." +msgstr "" + +#: src/running-the-course/translations.md:20 msgid "" "[French](https://google.github.io/comprehensive-rust/fr/) by [@KookaS]" "(https://github.com/KookaS) and [@vcaen](https://github.com/vcaen)." msgstr "" -#: src/running-the-course/translations.md:18 +#: src/running-the-course/translations.md:21 msgid "" "[German](https://google.github.io/comprehensive-rust/de/) by [@Throvn]" "(https://github.com/Throvn) and [@ronaldfw](https://github.com/ronaldfw)." msgstr "" -#: src/running-the-course/translations.md:19 +#: src/running-the-course/translations.md:22 msgid "" "[Japanese](https://google.github.io/comprehensive-rust/ja/) by [@CoinEZ-JPN]" "(https://github.com/CoinEZ) and [@momotaro1105](https://github.com/" "momotaro1105)." msgstr "" -#: src/running-the-course/translations.md:21 +#: src/running-the-course/translations.md:24 msgid "" "If you want to help with this effort, please see [our instructions](https://" "github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md) for how to " @@ -1614,17 +1634,33 @@ msgid "**Please follow the instructions on .**" msgstr "**Sigue las instrucciones que se indican en .**" #: src/cargo.md:12 +#, fuzzy +#| msgid "" +#| "This will give you the Cargo build tool (`cargo`) and the Rust compiler " +#| "(`rustc`). You will also get `rustup`, a command line utility that you " +#| "can use to install/switch toolchains, setup cross compilation, etc." msgid "" "This will give you the Cargo build tool (`cargo`) and the Rust compiler " "(`rustc`). You will also get `rustup`, a command line utility that you can " -"use to install/switch toolchains, setup cross compilation, etc." +"use to install to different compiler versions." msgstr "" "De este modo, obtendrás la herramienta de compilación de Cargo (`cargo`) y " "el compilador de Rust (`rustc`). También obtendrás `rustup`, una utilidad de " "línea de comandos que puedes utilizar para instalar o cambiar cadenas de " "herramientas, configurar la compilación cruzada, etc." -#: src/cargo.md:16 +#: src/cargo.md:14 +msgid "" +"After installing Rust, you should configure your editor or IDE to work with " +"Rust. Most editors do this by talking to [rust-analyzer](https://rust-" +"analyzer.github.io/), which provides auto-completion and jump-to-definition " +"functionality for [VS Code](https://code.visualstudio.com/), [Emacs](https://" +"rust-analyzer.github.io/manual.html#emacs), [Vim/Neovim](https://rust-" +"analyzer.github.io/manual.html#vimneovim), and many others. There is also a " +"different IDE available called [RustRover](https://www.jetbrains.com/rust/)." +msgstr "" + +#: src/cargo.md:18 #, fuzzy msgid "" "On Debian/Ubuntu, you can also install Cargo, the Rust source and the [Rust " @@ -1637,42 +1673,6 @@ msgstr "" "`apt`. Sin embargo, solo podrás conseguir una versión de Rust obsoleta que " "podría dar lugar a comportamientos inesperados. El comando es el siguiente:" -#: src/cargo.md:18 -msgid "" -"```shell\n" -"sudo apt install cargo rust-src rustfmt\n" -"```" -msgstr "" -"```shell\n" -"sudo apt install cargo rust-src rustfmt\n" -"```" - -#: src/cargo.md:22 -#, fuzzy -msgid "" -"We suggest using [VS Code](https://code.visualstudio.com/) to edit the code " -"(but any LSP compatible editor works with rust-analyzer[3](https://rust-" -"analyzer.github.io/))." -msgstr "" -"Recomendamos usar [VS Code](https://code.visualstudio.com/) para editar el " -"código (aunque cualquier editor compatible con LSP funciona con [rust-" -"analyzer](https://rust-analyzer.github.io/))." - -#: src/cargo.md:24 -msgid "" -"Some folks also like to use the [JetBrains](https://www.jetbrains.com/" -"clion/) family of IDEs, which do their own analysis but have their own " -"tradeoffs. If you prefer them, you can install the [Rust Plugin](https://www." -"jetbrains.com/rust/). Please take note that as of January 2023 debugging " -"only works on the CLion version of the JetBrains IDEA suite." -msgstr "" -"A algunos compañeros también les gusta usar la familia [JetBrains](https://" -"www.jetbrains.com/clion/) de IDEs, que hacen sus propios análisis, pero " -"también tienen inconvenientes. Si lo prefieres, puedes instalar el [Rust " -"Plugin](https://www.jetbrains.com/rust/). Ten en cuenta que, a partir de " -"enero del 2023, la depuración solo funciona en la versión CLion del paquete " -"de JetBrains IDEA." - #: src/cargo/rust-ecosystem.md:1 msgid "The Rust Ecosystem" msgstr "El ecosistema de Rust" @@ -1723,8 +1723,8 @@ msgstr "" #: src/cargo/rust-ecosystem.md:21 src/hello-world.md:25 #: src/hello-world/small-example.md:27 src/why-rust/runtime.md:10 -#: src/why-rust/modern.md:21 src/basic-syntax/compound-types.md:30 -#: src/basic-syntax/references.md:23 +#: src/why-rust/modern.md:21 src/basic-syntax/compound-types.md:32 +#: src/basic-syntax/references.md:24 #: src/pattern-matching/destructuring-enums.md:35 #: src/ownership/double-free-modern-cpp.md:55 #: src/error-handling/try-operator.md:48 @@ -1881,19 +1881,9 @@ msgstr "" msgid "The code blocks in this course are fully interactive:" msgstr "Los bloques de código de este curso son totalmente interactivos:" -#: src/cargo/code-samples.md:13 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"Edit me!\");\n" -"}\n" -"```" +#: src/cargo/code-samples.md:15 src/cargo/running-locally.md:45 +msgid "\"Edit me!\"" msgstr "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"Edit me!\");\n" -"}\n" -"```" #: src/cargo/code-samples.md:19 msgid "You can use " @@ -1949,22 +1939,6 @@ msgstr "" "funcionen. En el momento en que se redactó este documento, los números de " "las últimas versiones estables de Rust eran los siguientes:" -#: src/cargo/running-locally.md:8 -msgid "" -"```shell\n" -"% rustc --version\n" -"rustc 1.69.0 (84c898d65 2023-04-16)\n" -"% cargo --version\n" -"cargo 1.69.0 (6e9a83356 2023-04-12)\n" -"```" -msgstr "" -"```shell\n" -"% rustc --version\n" -"rustc 1.69.0 (84c898d65 2023-04-16)\n" -"% cargo --version\n" -"cargo 1.69.0 (6e9a83356 2023-04-12)\n" -"```" - #: src/cargo/running-locally.md:15 msgid "" "You can use any later version too since Rust maintains backwards " @@ -1991,44 +1965,12 @@ msgid "" msgstr "" "Usa `cargo new exercise` para crear un directorio `exercise/` para tu código:" -#: src/cargo/running-locally.md:24 -msgid "" -"```shell\n" -"$ cargo new exercise\n" -" Created binary (application) `exercise` package\n" -"```" -msgstr "" -"```shell\n" -"$ cargo new exercise\n" -" Created binary (application) `exercise` package\n" -"```" - #: src/cargo/running-locally.md:29 msgid "" "Navigate into `exercise/` and use `cargo run` to build and run your binary:" msgstr "" "Ve a `exercise/` y usa `cargo run` para compilar y ejecutar tu binario:" -#: src/cargo/running-locally.md:31 -msgid "" -"```shell\n" -"$ cd exercise\n" -"$ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" -" Running `target/debug/exercise`\n" -"Hello, world!\n" -"```" -msgstr "" -"```shell\n" -"$ cd exercise\n" -"$ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" -" Running `target/debug/exercise`\n" -"Hola Mundo!\n" -"```" - #: src/cargo/running-locally.md:40 msgid "" "Replace the boiler-plate code in `src/main.rs` with your own code. For " @@ -2038,42 +1980,10 @@ msgstr "" "ejemplo, si usamos el ejemplo de la página anterior, podemos hacer que `src/" "main.rs` tenga el siguiente aspecto:" -#: src/cargo/running-locally.md:43 -msgid "" -"```rust\n" -"fn main() {\n" -" println!(\"Edit me!\");\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"fn main() {\n" -" println!(\"Edit me!\");\n" -"}\n" -"```" - #: src/cargo/running-locally.md:49 msgid "Use `cargo run` to build and run your updated binary:" msgstr "Usa `cargo run` para hacer build y ejecutar tu binario actualizado:" -#: src/cargo/running-locally.md:51 -msgid "" -"```shell\n" -"$ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" -" Running `target/debug/exercise`\n" -"Edit me!\n" -"```" -msgstr "" -"```shell\n" -"$ cargo run\n" -" Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" -" Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" -" Running `target/debug/ejercicio`\n" -"Modifícame!\n" -"```" - #: src/cargo/running-locally.md:59 msgid "" "Use `cargo check` to quickly check your project for errors, use `cargo " @@ -2311,19 +2221,9 @@ msgid "" "program:" msgstr "Vamos a hablar del programa Rust más simple, un clásico Hola Mundo:" -#: src/hello-world.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"Hello 🌍!\");\n" -"}\n" -"```" +#: src/hello-world.md:8 +msgid "\"Hello 🌍!\"" msgstr "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"Hola 🌍!\");\n" -"}\n" -"```" #: src/hello-world.md:12 msgid "What you see:" @@ -2411,39 +2311,33 @@ msgstr "" msgid "Here is a small example program in Rust:" msgstr "A continuación, se muestra un pequeño programa de ejemplo de Rust:" -#: src/hello-world/small-example.md:5 -msgid "" -"```rust,editable\n" -"fn main() { // Program entry point\n" -" let mut x: i32 = 6; // Mutable variable binding\n" -" print!(\"{x}\"); // Macro for printing, like printf\n" -" while x != 1 { // No parenthesis around expression\n" -" if x % 2 == 0 { // Math like in other languages\n" -" x = x / 2;\n" -" } else {\n" -" x = 3 * x + 1;\n" -" }\n" -" print!(\" -> {x}\");\n" -" }\n" -" println!();\n" -"}\n" -"```" +#: src/hello-world/small-example.md:6 +msgid "// Program entry point\n" +msgstr "" + +#: src/hello-world/small-example.md:7 +msgid "// Mutable variable binding\n" +msgstr "" + +#: src/hello-world/small-example.md:8 src/traits/impl-trait.md:15 +msgid "\"{x}\"" +msgstr "" + +#: src/hello-world/small-example.md:8 +msgid "// Macro for printing, like printf\n" +msgstr "" + +#: src/hello-world/small-example.md:9 +msgid "// No parenthesis around expression\n" +msgstr "" + +#: src/hello-world/small-example.md:10 +msgid "// Math like in other languages\n" +msgstr "" + +#: src/hello-world/small-example.md:15 +msgid "\" -> {x}\"" msgstr "" -"```rust,editable\n" -"fn main() { // Punto de entrada del programa\n" -" let mut x: i32 = 6; // Variable mutable vinculante\n" -" print!(\"{x}\"); // Macro para printing, como printf\n" -" while x != 1 { // Sin paréntesis alrededor de las expresiones\n" -" if x % 2 == 0 { // Operaciones matemáticas como en otros lenguajes\n" -" x = x / 2;\n" -" } else {\n" -" x = 3 * x + 1;\n" -" }\n" -" print!(\" -> {x}\");\n" -" }\n" -" println!();\n" -"}\n" -"```" #: src/hello-world/small-example.md:23 msgid "" @@ -2554,41 +2448,223 @@ msgstr "" "rápido y predecible como en C y C++ (sin recolector de memoria residual), " "así como acceso a hardware de bajo nivel (si lo necesitas)." -#: src/why-rust/compile-time.md:3 -msgid "Static memory management at compile time:" -msgstr "Gestión estática de la memoria en tiempo de compilación:" +#: src/why-rust/an-example-in-c.md:4 +msgid "Let's consider the following \"minimum wrong example\" program in C:" +msgstr "" -#: src/why-rust/compile-time.md:5 -msgid "No uninitialized variables." -msgstr "No hay variables no inicializadas." +#: src/why-rust/an-example-in-c.md:7 +#: src/android/interoperability/with-c/bindgen.md:22 +msgid "" +msgstr "" -#: src/why-rust/compile-time.md:6 -msgid "No memory leaks (_mostly_, see notes)." -msgstr "No hay pérdidas de memoria (_casi siempre_, consulta las notas)." +#: src/why-rust/an-example-in-c.md:8 +msgid "" +msgstr "" -#: src/why-rust/compile-time.md:7 -msgid "No double-frees." -msgstr "No hay errores double free." +#: src/why-rust/an-example-in-c.md:9 +msgid "" +msgstr "" -#: src/why-rust/compile-time.md:8 -msgid "No use-after-free." -msgstr "No hay errores use-after-free." +#: src/why-rust/an-example-in-c.md:19 +msgid "\"Too few arguments!\\n\"" +msgstr "" -#: src/why-rust/compile-time.md:9 -msgid "No `NULL` pointers." -msgstr "No hay punteros `NULL`." +#: src/why-rust/an-example-in-c.md:29 +msgid "\"malloc failed!\\n\"" +msgstr "" -#: src/why-rust/compile-time.md:10 -msgid "No forgotten locked mutexes." -msgstr "No se olvidan las exclusiones mutuas bloqueadas." +#: src/why-rust/an-example-in-c.md:32 +msgid "\"rb\"" +msgstr "" -#: src/why-rust/compile-time.md:11 -msgid "No data races between threads." -msgstr "No hay condiciones de carrera de datos entre hilos." +#: src/why-rust/an-example-in-c.md:35 +msgid "\"%s\"" +msgstr "" -#: src/why-rust/compile-time.md:12 -msgid "No iterator invalidation." -msgstr "No se invalidan los iteradores." +#: src/why-rust/an-example-in-c.md:37 +msgid "\"fread failed!\\n\"" +msgstr "" + +#: src/why-rust/an-example-in-c.md:40 +msgid "\"Too many arguments!\\n\"" +msgstr "" + +#: src/why-rust/an-example-in-c.md:48 +msgid "How many bugs do you spot?" +msgstr "" + +#: src/why-rust/an-example-in-c.md:52 +msgid "" +"Despite just 29 lines of code, this C example contains serious bugs in at " +"least 11:" +msgstr "" + +#: src/why-rust/an-example-in-c.md:54 +msgid "Assignment `=` instead of equality comparison `==` (line 28)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:55 +msgid "Excess argument to `printf` (line 23)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:56 +msgid "File descriptor leak (after line 26)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:57 +msgid "Forgotten braces in multi-line `if` (line 22)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:58 +msgid "Forgotten `break` in a `switch` statement (line 32)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:59 +msgid "" +"Forgotten NUL-termination of the `buf` string, leading to a buffer overflow " +"(line 29)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:60 +msgid "Memory leak by not freeing the `malloc`\\-allocated buffer (line 21)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:61 +msgid "Out-of-bounds access (line 17)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:62 +msgid "Unchecked cases in the `switch` statement (line 11)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:63 +msgid "Unchecked return values of `stat` and `fopen` (lines 18 and 26)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:65 +msgid "" +"_Shouldn't these bugs be obvious even for a C compiler?_ \n" +"No, surprisingly this code compiles warning-free at the default warning " +"level, even in the latest GCC version (13.2 as of writing)." +msgstr "" + +#: src/why-rust/an-example-in-c.md:68 +msgid "" +"_Isn't this a highly unrealistic example?_ \n" +"Absolutely not, these kind of bugs have lead to serious security " +"vulnerabilities in the past. Some examples:" +msgstr "" + +#: src/why-rust/an-example-in-c.md:71 +msgid "" +"Assignment `=` instead of equality comparison `==`: [The Linux Backdoor " +"Attempt of 2003](https://freedom-to-tinker.com/2013/10/09/the-linux-backdoor-" +"attempt-of-2003)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:72 +msgid "" +"Forgotten braces in multi-line `if`: [The Apple goto fail vulnerability]" +"(https://dwheeler.com/essays/apple-goto-fail.html)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:73 +msgid "" +"Forgotten `break` in a `switch` statement: [The break that broke sudo]" +"(https://nakedsecurity.sophos.com/2012/05/21/anatomy-of-a-security-hole-the-" +"break-that-broke-sudo)" +msgstr "" + +#: src/why-rust/an-example-in-c.md:75 +msgid "" +"_How is Rust any better here?_ \n" +"Safe Rust makes all of these bugs impossible:" +msgstr "" + +#: src/why-rust/an-example-in-c.md:78 +msgid "Assignments inside an `if` clause are not supported." +msgstr "" + +#: src/why-rust/an-example-in-c.md:79 +msgid "Format strings are checked at compile-time." +msgstr "" + +#: src/why-rust/an-example-in-c.md:80 +msgid "Resources are freed at the end of scope via the `Drop` trait." +msgstr "" + +#: src/why-rust/an-example-in-c.md:81 +msgid "All `if` clauses require braces." +msgstr "" + +#: src/why-rust/an-example-in-c.md:82 +msgid "" +"`match` (as the Rust equivalent to `switch`) does not fall-through, hence " +"you can't accidentally forget a `break`." +msgstr "" + +#: src/why-rust/an-example-in-c.md:83 +msgid "Buffer slices carry their size and don't rely on a NUL terminator." +msgstr "" + +#: src/why-rust/an-example-in-c.md:84 +msgid "" +"Heap-allocated memory is freed via the `Drop` trait when the corresponding " +"`Box` leaves the scope." +msgstr "" + +#: src/why-rust/an-example-in-c.md:85 +msgid "" +"Out-of-bounds accesses cause a panic or can be checked via the `get` method " +"of a slice." +msgstr "" + +#: src/why-rust/an-example-in-c.md:86 +msgid "`match` mandates that all cases are handled." +msgstr "" + +#: src/why-rust/an-example-in-c.md:87 +msgid "" +"Fallible Rust functions return `Result` values that need to be unwrapped and " +"thereby checked for success. Additionally, the compiler emits a warning if " +"you miss to check the return value of a function marked with `#[must_use]`." +msgstr "" + +#: src/why-rust/compile-time.md:3 +msgid "Static memory management at compile time:" +msgstr "Gestión estática de la memoria en tiempo de compilación:" + +#: src/why-rust/compile-time.md:5 +msgid "No uninitialized variables." +msgstr "No hay variables no inicializadas." + +#: src/why-rust/compile-time.md:6 +msgid "No memory leaks (_mostly_, see notes)." +msgstr "No hay pérdidas de memoria (_casi siempre_, consulta las notas)." + +#: src/why-rust/compile-time.md:7 +msgid "No double-frees." +msgstr "No hay errores double free." + +#: src/why-rust/compile-time.md:8 +msgid "No use-after-free." +msgstr "No hay errores use-after-free." + +#: src/why-rust/compile-time.md:9 +msgid "No `NULL` pointers." +msgstr "No hay punteros `NULL`." + +#: src/why-rust/compile-time.md:10 +msgid "No forgotten locked mutexes." +msgstr "No se olvidan las exclusiones mutuas bloqueadas." + +#: src/why-rust/compile-time.md:11 +msgid "No data races between threads." +msgstr "No hay condiciones de carrera de datos entre hilos." + +#: src/why-rust/compile-time.md:12 +msgid "No iterator invalidation." +msgstr "No se invalidan los iteradores." #: src/why-rust/compile-time.md:16 msgid "" @@ -2971,31 +3047,11 @@ msgstr "" "inhabilitados: `r\"\\n\" == \"\\\\n\"`. Puedes insertar comillas dobles con " "la misma cantidad de `#` a cada lado de ellas:" -#: src/basic-syntax/scalar-types.md:27 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(r#\"link\"#);\n" -" println!(\"link\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/scalar-types.md:34 +#: src/basic-syntax/scalar-types.md:35 msgid "Byte strings allow you to create a `&[u8]` value directly:" msgstr "Las cadenas de bytes te permiten crear un valor `&[u8]` directamente:" -#: src/basic-syntax/scalar-types.md:36 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"{:?}\", b\"abc\");\n" -" println!(\"{:?}\", &[97, 98, 99]);\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/scalar-types.md:43 +#: src/basic-syntax/scalar-types.md:45 msgid "" "All underscores in numbers can be left out, they are for legibility only. So " "`1_000` can be written as `1000` (or `10_00`), and `123_i64` can be written " @@ -3033,37 +3089,15 @@ msgstr "" msgid "Array assignment and access:" msgstr "Asignación y acceso a arrays:" -#: src/basic-syntax/compound-types.md:10 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut a: [i8; 10] = [42; 10];\n" -" a[5] = 0;\n" -" println!(\"a: {:?}\", a);\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/compound-types.md:18 +#: src/basic-syntax/compound-types.md:19 msgid "Tuple assignment and access:" msgstr "Asignación y acceso a tuplas:" -#: src/basic-syntax/compound-types.md:20 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let t: (i8, bool) = (7, true);\n" -" println!(\"1st index: {}\", t.0);\n" -" println!(\"2nd index: {}\", t.1);\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/compound-types.md:32 +#: src/basic-syntax/compound-types.md:34 msgid "Arrays:" msgstr "Arrays:" -#: src/basic-syntax/compound-types.md:34 +#: src/basic-syntax/compound-types.md:36 msgid "" "A value of the array type `[T; N]` holds `N` (a compile-time constant) " "elements of the same type `T`. Note that the length of the array is _part of " @@ -3075,11 +3109,11 @@ msgstr "" "array es *parte de su tipo*, lo que significa que `[u8; 3]` y `[u8; 4]` se " "consideran dos tipos diferentes." -#: src/basic-syntax/compound-types.md:38 +#: src/basic-syntax/compound-types.md:40 msgid "We can use literals to assign values to arrays." msgstr "Podemos usar literales para asignar valores a arrays." -#: src/basic-syntax/compound-types.md:40 +#: src/basic-syntax/compound-types.md:42 msgid "" "In the main function, the print statement asks for the debug implementation " "with the `?` format parameter: `{}` gives the default output, `{:?}` gives " @@ -3092,7 +3126,7 @@ msgstr "" "haber usado `{a}` y `{a:?}` sin especificar el valor después de la cadena de " "formato." -#: src/basic-syntax/compound-types.md:45 +#: src/basic-syntax/compound-types.md:47 msgid "" "Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be " "easier to read." @@ -3100,19 +3134,19 @@ msgstr "" "Si se añade `#`, por ejemplo `{a:#?}`, se da formato al texto para facilitar " "la lectura." -#: src/basic-syntax/compound-types.md:47 +#: src/basic-syntax/compound-types.md:49 msgid "Tuples:" msgstr "Tuplas:" -#: src/basic-syntax/compound-types.md:49 +#: src/basic-syntax/compound-types.md:51 msgid "Like arrays, tuples have a fixed length." msgstr "Al igual que los arrays, las tuplas tienen una longitud fija." -#: src/basic-syntax/compound-types.md:51 +#: src/basic-syntax/compound-types.md:53 msgid "Tuples group together values of different types into a compound type." msgstr "Las tuplas agrupan valores de diferentes tipos en un tipo compuesto." -#: src/basic-syntax/compound-types.md:53 +#: src/basic-syntax/compound-types.md:55 msgid "" "Fields of a tuple can be accessed by the period and the index of the value, " "e.g. `t.0`, `t.1`." @@ -3120,7 +3154,7 @@ msgstr "" "Se puede acceder a los campos de una tupla por el punto y el índice del " "valor, por ejemplo, `t.0`, `t.1`." -#: src/basic-syntax/compound-types.md:55 +#: src/basic-syntax/compound-types.md:57 msgid "" "The empty tuple `()` is also known as the \"unit type\". It is both a type, " "and the only valid value of that type - that is to say both the type and its " @@ -3133,7 +3167,7 @@ msgstr "" "función o expresión no tiene valor de retorno, como veremos en una " "diapositiva posterior." -#: src/basic-syntax/compound-types.md:59 +#: src/basic-syntax/compound-types.md:61 msgid "" "You can think of it as `void` that can be familiar to you from other " "programming languages." @@ -3145,23 +3179,11 @@ msgstr "" msgid "Like C++, Rust has references:" msgstr "Al igual que C++, Rust tiene referencias:" -#: src/basic-syntax/references.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x: i32 = 10;\n" -" let ref_x: &mut i32 = &mut x;\n" -" *ref_x = 20;\n" -" println!(\"x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/references.md:14 +#: src/basic-syntax/references.md:15 msgid "Some notes:" msgstr "Algunas notas:" -#: src/basic-syntax/references.md:16 +#: src/basic-syntax/references.md:17 msgid "" "We must dereference `ref_x` when assigning to it, similar to C and C++ " "pointers." @@ -3169,7 +3191,7 @@ msgstr "" "Debemos desreferenciar `ref_x` al asignarle un valor, de forma similar a los " "punteros de C y C++." -#: src/basic-syntax/references.md:17 +#: src/basic-syntax/references.md:18 msgid "" "Rust will auto-dereference in some cases, in particular when invoking " "methods (try `ref_x.count_ones()`)." @@ -3177,7 +3199,7 @@ msgstr "" "Rust realizará una desreferencia automática en algunos casos, en especial al " "invocar métodos (prueba `ref_x.count_ones()`)." -#: src/basic-syntax/references.md:19 +#: src/basic-syntax/references.md:20 msgid "" "References that are declared as `mut` can be bound to different values over " "their lifetime." @@ -3185,7 +3207,7 @@ msgstr "" "Las referencias que se declaran como `mut` se pueden vincular a distintos " "valores durante su tiempo de vida." -#: src/basic-syntax/references.md:25 +#: src/basic-syntax/references.md:26 msgid "" "Be sure to note the difference between `let mut ref_x: &i32` and `let ref_x: " "&mut i32`. The first one represents a mutable reference which can be bound " @@ -3201,26 +3223,12 @@ msgstr "" msgid "Rust will statically forbid dangling references:" msgstr "Rust prohibirá estáticamente las referencias colgantes:" -#: src/basic-syntax/references-dangling.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let ref_x: &i32;\n" -" {\n" -" let x: i32 = 10;\n" -" ref_x = &x;\n" -" }\n" -" println!(\"ref_x: {ref_x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/references-dangling.md:16 +#: src/basic-syntax/references-dangling.md:17 msgid "A reference is said to \"borrow\" the value it refers to." msgstr "" "Se dice que una referencia \"toma prestado\" el valor al que hace referencia." -#: src/basic-syntax/references-dangling.md:17 +#: src/basic-syntax/references-dangling.md:18 msgid "" "Rust is tracking the lifetimes of all references to ensure they live long " "enough." @@ -3228,7 +3236,7 @@ msgstr "" "Rust hace un seguimiento del tiempo de vida de todas las referencias para " "asegurarse de que duran lo suficiente." -#: src/basic-syntax/references-dangling.md:19 +#: src/basic-syntax/references-dangling.md:20 msgid "We will talk more about borrowing when we get to ownership." msgstr "" "Más adelante hablaremos de los préstamos cuando lleguemos a la parte de " @@ -3238,30 +3246,16 @@ msgstr "" msgid "A slice gives you a view into a larger collection:" msgstr "Un _slice_ ofrece una visión de una colección más amplia:" -#: src/basic-syntax/slices.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" -" println!(\"a: {a:?}\");\n" -"\n" -" let s: &[i32] = &a[2..4];\n" -"\n" -" println!(\"s: {s:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/slices.md:16 +#: src/basic-syntax/slices.md:17 msgid "Slices borrow data from the sliced type." msgstr "Los slices toman prestados datos del tipo slice." -#: src/basic-syntax/slices.md:17 +#: src/basic-syntax/slices.md:18 msgid "Question: What happens if you modify `a[3]` right before printing `s`?" msgstr "" "Pregunta: ¿Qué ocurre si se modifica `a[3]` justo antes de imprimir `s`?" -#: src/basic-syntax/slices.md:21 +#: src/basic-syntax/slices.md:22 msgid "" "We create a slice by borrowing `a` and specifying the starting and ending " "indexes in brackets." @@ -3269,7 +3263,7 @@ msgstr "" "Creamos un slice tomando prestado `a` y especificando entre paréntesis los " "índices de inicio y de fin." -#: src/basic-syntax/slices.md:23 +#: src/basic-syntax/slices.md:24 msgid "" "If the slice starts at index 0, Rust’s range syntax allows us to drop the " "starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are " @@ -3279,7 +3273,7 @@ msgstr "" "permite eliminar el índice inicial, lo que significa que `&a[0..a.len()]` y " "`&a[..a.len()]` son idénticos." -#: src/basic-syntax/slices.md:25 +#: src/basic-syntax/slices.md:26 msgid "" "The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are " "identical." @@ -3287,13 +3281,13 @@ msgstr "" "Lo mismo ocurre con el último índice, por lo que `&a[2..a.len()]` y " "`&a[2..]` son idénticos." -#: src/basic-syntax/slices.md:27 +#: src/basic-syntax/slices.md:28 msgid "" "To easily create a slice of the full array, we can therefore use `&a[..]`." msgstr "" "Para crear fácilmente un slice del array completo, podemos usar `&a[..]`." -#: src/basic-syntax/slices.md:29 +#: src/basic-syntax/slices.md:30 msgid "" "`s` is a reference to a slice of `i32`s. Notice that the type of `s` " "(`&[i32]`) no longer mentions the array length. This allows us to perform " @@ -3303,7 +3297,7 @@ msgstr "" "(`&[i32]`) ya no menciona la longitud del array. Esto nos permite realizar " "cálculos en slices de diferentes tamaños." -#: src/basic-syntax/slices.md:31 +#: src/basic-syntax/slices.md:32 msgid "" "Slices always borrow from another object. In this example, `a` has to remain " "'alive' (in scope) for at least as long as our slice. " @@ -3312,7 +3306,7 @@ msgstr "" "tiene que permanecer \"con vida\" (en el ámbito) al menos durante el tiempo " "que dure el slice. " -#: src/basic-syntax/slices.md:33 +#: src/basic-syntax/slices.md:34 msgid "" "The question about modifying `a[3]` can spark an interesting discussion, but " "the answer is that for memory safety reasons you cannot do it through `a` at " @@ -3336,22 +3330,29 @@ msgstr "`String` o `str`" msgid "We can now understand the two string types in Rust:" msgstr "Ahora podemos entender los dos tipos de cadenas de Rust:" -#: src/basic-syntax/string-slices.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1: &str = \"World\";\n" -" println!(\"s1: {s1}\");\n" -"\n" -" let mut s2: String = String::from(\"Hello \");\n" -" println!(\"s2: {s2}\");\n" -" s2.push_str(s1);\n" -" println!(\"s2: {s2}\");\n" -" \n" -" let s3: &str = &s2[6..];\n" -" println!(\"s3: {s3}\");\n" -"}\n" -"```" +#: src/basic-syntax/string-slices.md:7 src/traits/read-write.md:36 +#: src/testing/test-modules.md:12 +msgid "\"World\"" +msgstr "" + +#: src/basic-syntax/string-slices.md:8 +msgid "\"s1: {s1}\"" +msgstr "" + +#: src/basic-syntax/string-slices.md:10 src/memory-management/scope-based.md:16 +#: src/memory-management/garbage-collection.md:15 +#, fuzzy +#| msgid "Hello World!" +msgid "\"Hello \"" +msgstr "¡Hola, mundo!" + +#: src/basic-syntax/string-slices.md:11 src/basic-syntax/string-slices.md:13 +#: src/ownership/move-semantics.md:9 +msgid "\"s2: {s2}\"" +msgstr "" + +#: src/basic-syntax/string-slices.md:16 +msgid "\"s3: {s3}\"" msgstr "" #: src/basic-syntax/string-slices.md:20 @@ -3434,38 +3435,7 @@ msgstr "" "Una versión de Rust de la famosa pregunta de la entrevista de [FizzBuzz]" "(https://es.wikipedia.org/wiki/Fizz_buzz):" -#: src/basic-syntax/functions.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" print_fizzbuzz_to(20);\n" -"}\n" -"\n" -"fn is_divisible(n: u32, divisor: u32) -> bool {\n" -" if divisor == 0 {\n" -" return false;\n" -" }\n" -" n % divisor == 0\n" -"}\n" -"\n" -"fn fizzbuzz(n: u32) -> String {\n" -" let fizz = if is_divisible(n, 3) { \"fizz\" } else { \"\" };\n" -" let buzz = if is_divisible(n, 5) { \"buzz\" } else { \"\" };\n" -" if fizz.is_empty() && buzz.is_empty() {\n" -" return format!(\"{n}\");\n" -" }\n" -" format!(\"{fizz}{buzz}\")\n" -"}\n" -"\n" -"fn print_fizzbuzz_to(n: u32) {\n" -" for i in 1..=n {\n" -" println!(\"{}\", fizzbuzz(i));\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/functions.md:35 +#: src/basic-syntax/functions.md:36 msgid "" "We refer in `main` to a function written below. Neither forward declarations " "nor headers are necessary. " @@ -3473,7 +3443,7 @@ msgstr "" "En `main` hacemos referencia a una función escrita más abajo. No se " "necesitan declaraciones de redirección ni encabezados. " -#: src/basic-syntax/functions.md:36 +#: src/basic-syntax/functions.md:37 msgid "" "Declaration parameters are followed by a type (the reverse of some " "programming languages), then a return type." @@ -3482,7 +3452,7 @@ msgstr "" "algunos lenguajes de programación) y, a continuación, de un tipo de " "resultado devuelto." -#: src/basic-syntax/functions.md:37 +#: src/basic-syntax/functions.md:38 msgid "" "The last expression in a function body (or any block) becomes the return " "value. Simply omit the `;` at the end of the expression." @@ -3491,7 +3461,7 @@ msgstr "" "convierte en el valor devuelto. Basta con omitir el carácter `;` al final de " "la expresión." -#: src/basic-syntax/functions.md:38 +#: src/basic-syntax/functions.md:39 msgid "" "Some functions have no return value, and return the 'unit type', `()`. The " "compiler will infer this if the `-> ()` return type is omitted." @@ -3499,7 +3469,7 @@ msgstr "" "Algunas funciones no devuelven ningún valor, devuelven el \"tipo unitario\", " "`()`. El compilador deducirá esto si se omite el tipo de retorno `-> ()`." -#: src/basic-syntax/functions.md:39 +#: src/basic-syntax/functions.md:40 msgid "" "The range expression in the `for` loop in `print_fizzbuzz_to()` contains " "`=n`, which causes it to include the upper bound." @@ -3514,29 +3484,40 @@ msgstr "" "Todos los elementos del lenguaje de Rust se pueden documentar con la " "sintaxis especial `///`." -#: src/basic-syntax/rustdoc.md:5 +#: src/basic-syntax/rustdoc.md:6 msgid "" -"```rust,editable\n" "/// Determine whether the first argument is divisible by the second " "argument.\n" "///\n" "/// If the second argument is zero, the result is false.\n" -"fn is_divisible_by(lhs: u32, rhs: u32) -> bool {\n" -" if rhs == 0 {\n" -" return false; // Corner case, early return\n" -" }\n" -" lhs % rhs == 0 // The last expression in a block is the return " -"value\n" -"}\n" -"```" +"///\n" +"/// # Example\n" +"/// ```\n" +"/// assert!(is_divisible_by(42, 2));\n" +"/// ```\n" +msgstr "" + +#: src/basic-syntax/rustdoc.md:16 +msgid "// Corner case, early return\n" +msgstr "" + +#: src/basic-syntax/rustdoc.md:18 +msgid "// The last expression in a block is the return value\n" msgstr "" -#: src/basic-syntax/rustdoc.md:17 +#: src/basic-syntax/rustdoc.md:22 +#, fuzzy +#| msgid "" +#| "The contents are treated as Markdown. All published Rust library crates " +#| "are automatically documented at [`docs.rs`](https://docs.rs) using the " +#| "[rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. " +#| "It is idiomatic to document all public items in an API using this pattern." msgid "" "The contents are treated as Markdown. All published Rust library crates are " "automatically documented at [`docs.rs`](https://docs.rs) using the [rustdoc]" "(https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It is " -"idiomatic to document all public items in an API using this pattern." +"idiomatic to document all public items in an API using this pattern. Code " +"snippets can document usage and will be used as unit tests." msgstr "" "El contenido se trata como Markdown. Todos los crates de la biblioteca de " "Rust publicados se documentan automáticamente\n" @@ -3545,7 +3526,7 @@ msgstr "" "propio\n" "documentar todos los elementos públicos de una API usando este patrón." -#: src/basic-syntax/rustdoc.md:24 +#: src/basic-syntax/rustdoc.md:30 msgid "" "Show students the generated docs for the `rand` crate at [`docs.rs/rand`]" "(https://docs.rs/rand)." @@ -3553,7 +3534,7 @@ msgstr "" "Muestra a los alumnos los documentos generados para el crate `rand` en " "[`docs.rs/rand`](https://docs.rs/rand)." -#: src/basic-syntax/rustdoc.md:27 +#: src/basic-syntax/rustdoc.md:33 msgid "" "This course does not include rustdoc on slides, just to save space, but in " "real code they should be present." @@ -3561,7 +3542,7 @@ msgstr "" "Este curso no incluye diapositivas sobre rustdoc para ahorrar espacio, pero " "deben aparecer en el código real." -#: src/basic-syntax/rustdoc.md:30 +#: src/basic-syntax/rustdoc.md:36 msgid "" "Inner doc comments are discussed later (in the page on modules) and need not " "be addressed here." @@ -3569,7 +3550,7 @@ msgstr "" "Los comentarios internos de los documentos se tratarán más adelante (en la " "página de módulos), no es necesario tratarlos aquí." -#: src/basic-syntax/rustdoc.md:33 +#: src/basic-syntax/rustdoc.md:39 msgid "" "Rustdoc comments can contain code snippets that we can run and test using " "`cargo test`. We will discuss these tests in the [Testing section](../" @@ -3587,31 +3568,12 @@ msgstr "" "Los métodos son funciones asociadas a un tipo. El argumento `self` de un " "método es una instancia del tipo al que está asociada:" -#: src/basic-syntax/methods.md:6 -msgid "" -"```rust,editable\n" -"struct Rectangle {\n" -" width: u32,\n" -" height: u32,\n" -"}\n" -"\n" -"impl Rectangle {\n" -" fn area(&self) -> u32 {\n" -" self.width * self.height\n" -" }\n" -"\n" -" fn inc_width(&mut self, delta: u32) {\n" -" self.width += delta;\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let mut rect = Rectangle { width: 10, height: 5 };\n" -" println!(\"old area: {}\", rect.area());\n" -" rect.inc_width(5);\n" -" println!(\"new area: {}\", rect.area());\n" -"}\n" -"```" +#: src/basic-syntax/methods.md:24 +msgid "\"old area: {}\"" +msgstr "" + +#: src/basic-syntax/methods.md:26 +msgid "\"new area: {}\"" msgstr "" #: src/basic-syntax/methods.md:30 @@ -3627,20 +3589,6 @@ msgid "Add a static method called `Rectangle::new` and call this from `main`:" msgstr "" "Añade un método estático denominado `Rectangle::new` y llámalo desde `main`:" -#: src/basic-syntax/methods.md:36 -msgid "" -"```rust,editable,compile_fail\n" -"fn new(width: u32, height: u32) -> Rectangle {\n" -" Rectangle { width, height }\n" -"}\n" -"```" -msgstr "" -"```rust,editable,compile_fail\n" -"fn new(width: u32, height: u32) -> Rectangle {\n" -" Rectangle { width, height }\n" -"}\n" -"```" - #: src/basic-syntax/methods.md:42 msgid "" "While _technically_, Rust does not have custom constructors, static methods " @@ -3698,18 +3646,22 @@ msgstr "A veces, se utilizan macros como alternativa." msgid "However, function parameters can be generic:" msgstr "Sin embargo, los parámetros de función pueden ser genéricos:" -#: src/basic-syntax/functions-interlude.md:14 -msgid "" -"```rust,editable\n" -"fn pick_one(a: T, b: T) -> T {\n" -" if std::process::id() % 2 == 0 { a } else { b }\n" -"}\n" -"\n" -"fn main() {\n" -" println!(\"coin toss: {}\", pick_one(\"heads\", \"tails\"));\n" -" println!(\"cash prize: {}\", pick_one(500, 1000));\n" -"}\n" -"```" +#: src/basic-syntax/functions-interlude.md:20 +msgid "\"coin toss: {}\"" +msgstr "" + +#: src/basic-syntax/functions-interlude.md:20 +#, fuzzy +#| msgid "Threads" +msgid "\"heads\"" +msgstr "Hilos" + +#: src/basic-syntax/functions-interlude.md:20 +msgid "\"tails\"" +msgstr "" + +#: src/basic-syntax/functions-interlude.md:21 +msgid "\"cash prize: {}\"" msgstr "" #: src/basic-syntax/functions-interlude.md:27 @@ -3785,23 +3737,7 @@ msgstr "" "implicit_conversion)). Puedes ver un ejemplo de esto en el siguiente " "programa:" -#: src/exercises/day-1/implicit-conversions.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"fn multiply(x: i16, y: i16) -> i16 {\n" -" x * y\n" -"}\n" -"\n" -"fn main() {\n" -" let x: i8 = 15;\n" -" let y: i16 = 1000;\n" -"\n" -" println!(\"{x} * {y} = {}\", multiply(x, y));\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/implicit-conversions.md:19 +#: src/exercises/day-1/implicit-conversions.md:20 msgid "" "The Rust integer types all implement the [`From`](https://doc.rust-lang." "org/std/convert/trait.From.html) and [`Into`](https://doc.rust-lang.org/" @@ -3818,7 +3754,7 @@ msgstr "" "`into()`. Un tipo expresa que se puede convertir en otro tipo implementando " "estos traits." -#: src/exercises/day-1/implicit-conversions.md:25 +#: src/exercises/day-1/implicit-conversions.md:26 msgid "" "The standard library has an implementation of `From for i16`, which " "means that we can convert a variable `x` of type `i8` to an `i16` by " @@ -3832,7 +3768,7 @@ msgstr "" "`From for i16` crea automáticamente una implementación de `Into for " "i8`." -#: src/exercises/day-1/implicit-conversions.md:30 +#: src/exercises/day-1/implicit-conversions.md:31 msgid "" "The same applies for your own `From` implementations for your own types, so " "it is sufficient to only implement `From` to get a respective `Into` " @@ -3842,16 +3778,16 @@ msgstr "" "lo que basta con implementar `From` para obtener la respectiva " "implementación `Into` de forma automática." -#: src/exercises/day-1/implicit-conversions.md:33 +#: src/exercises/day-1/implicit-conversions.md:34 msgid "Execute the above program and look at the compiler error." msgstr "Ejecuta el programa anterior y observa el error del compilador." -#: src/exercises/day-1/implicit-conversions.md:35 +#: src/exercises/day-1/implicit-conversions.md:36 msgid "Update the code above to use `into()` to do the conversion." msgstr "" "Actualiza el código anterior para usar `into()` y realizar la conversión." -#: src/exercises/day-1/implicit-conversions.md:37 +#: src/exercises/day-1/implicit-conversions.md:38 msgid "" "Change the types of `x` and `y` to other things (such as `f32`, `bool`, " "`i128`) to see which types you can convert to which other types. Try " @@ -3874,13 +3810,6 @@ msgstr "Arrays y bucles`for`" msgid "We saw that an array can be declared like this:" msgstr "Hemos visto que un array se puede declarar de la siguiente manera:" -#: src/exercises/day-1/for-loops.md:5 -msgid "" -"```rust\n" -"let array = [10, 20, 30];\n" -"```" -msgstr "" - #: src/exercises/day-1/for-loops.md:9 msgid "" "You can print such an array by asking for its debug representation with `{:?}" @@ -3889,17 +3818,7 @@ msgstr "" "Puedes imprimir dicho array solicitando su representación de depuración con " "`{:?}`:" -#: src/exercises/day-1/for-loops.md:11 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let array = [10, 20, 30];\n" -" println!(\"array: {array:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/for-loops.md:18 +#: src/exercises/day-1/for-loops.md:19 msgid "" "Rust lets you iterate over things like arrays and ranges using the `for` " "keyword:" @@ -3907,27 +3826,23 @@ msgstr "" "Rust te permite iterar sobre elementos como arrays y rangos usando la " "palabra clave `for`:" -#: src/exercises/day-1/for-loops.md:21 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let array = [10, 20, 30];\n" -" print!(\"Iterating over array:\");\n" -" for n in &array {\n" -" print!(\" {n}\");\n" -" }\n" -" println!();\n" -"\n" -" print!(\"Iterating over range:\");\n" -" for i in 0..3 {\n" -" print!(\" {}\", array[i]);\n" -" }\n" -" println!();\n" -"}\n" -"```" +#: src/exercises/day-1/for-loops.md:25 +msgid "\"Iterating over array:\"" +msgstr "" + +#: src/exercises/day-1/for-loops.md:27 +msgid "\" {n}\"" +msgstr "" + +#: src/exercises/day-1/for-loops.md:31 +msgid "\"Iterating over range:\"" msgstr "" -#: src/exercises/day-1/for-loops.md:38 +#: src/exercises/day-1/for-loops.md:33 +msgid "\" {}\"" +msgstr "" + +#: src/exercises/day-1/for-loops.md:39 msgid "" "Use the above to write a function `pretty_print` which pretty-print a matrix " "and a function `transpose` which will transpose a matrix (turn rows into " @@ -3937,20 +3852,11 @@ msgstr "" "para dar formato al texto de la matriz y una función `transpose` que " "transponga una matriz (convertir filas en columnas):" -#: src/exercises/day-1/for-loops.md:41 -msgid "" -"```bob\n" -" ⎛⎡1 2 3⎤⎞ ⎡1 4 7⎤\n" -"\"transpose\"⎜⎢4 5 6⎥⎟ \"==\"⎢2 5 8⎥\n" -" ⎝⎣7 8 9⎦⎠ ⎣3 6 9⎦\n" -"```" -msgstr "" - -#: src/exercises/day-1/for-loops.md:47 +#: src/exercises/day-1/for-loops.md:49 msgid "Hard-code both functions to operate on 3 × 3 matrices." msgstr "Codifica ambas funciones para que operen con matrices de 3 × 3." -#: src/exercises/day-1/for-loops.md:49 +#: src/exercises/day-1/for-loops.md:51 msgid "" "Copy the code below to and implement the " "functions:" @@ -3958,42 +3864,45 @@ msgstr "" "Copia el siguiente fragmento de código en e " "implementa las funciones:" -#: src/exercises/day-1/for-loops.md:52 -msgid "" +#: src/exercises/day-1/for-loops.md:55 src/exercises/day-1/luhn.md:26 +#: src/exercises/day-2/health-statistics.md:14 +#: src/exercises/day-2/strings-iterators.md:13 +#: src/exercises/day-3/simple-gui.md:20 +#: src/exercises/day-3/points-polygons.md:8 +#: src/exercises/day-3/safe-ffi-wrapper.md:49 +#, fuzzy +#| msgid "" +#| "```rust,should_panic\n" +#| "// TODO: remove this when you're done with your implementation.\n" +#| "#![allow(unused_variables, dead_code)]\n" +#| "```" +msgid "// TODO: remove this when you're done with your implementation.\n" +msgstr "" "```rust,should_panic\n" -"// TODO: remove this when you're done with your implementation.\n" +"// TODO: borra esto cuando termines de implementarlo.\n" "#![allow(unused_variables, dead_code)]\n" -"\n" -"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" -" unimplemented!()\n" -"}\n" -"\n" -"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" -" unimplemented!()\n" -"}\n" -"\n" -"fn main() {\n" -" let matrix = [\n" -" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" -" [201, 202, 203],\n" -" [301, 302, 303],\n" -" ];\n" -"\n" -" println!(\"matrix:\");\n" -" pretty_print(&matrix);\n" -"\n" -" let transposed = transpose(matrix);\n" -" println!(\"transposed:\");\n" -" pretty_print(&transposed);\n" -"}\n" "```" + +#: src/exercises/day-1/for-loops.md:68 +#: src/exercises/day-1/solutions-morning.md:44 +msgid "// <-- the comment makes rustfmt add a newline\n" +msgstr "" + +#: src/exercises/day-1/for-loops.md:73 +#: src/exercises/day-1/solutions-morning.md:49 +msgid "\"matrix:\"" +msgstr "" + +#: src/exercises/day-1/for-loops.md:77 +#: src/exercises/day-1/solutions-morning.md:53 +msgid "\"transposed:\"" msgstr "" -#: src/exercises/day-1/for-loops.md:80 +#: src/exercises/day-1/for-loops.md:82 msgid "Bonus Question" msgstr "Pregunta Extra" -#: src/exercises/day-1/for-loops.md:82 +#: src/exercises/day-1/for-loops.md:84 msgid "" "Could you use `&[i32]` slices instead of hard-coded 3 × 3 matrices for your " "argument and return types? Something like `&[&[i32]]` for a two-dimensional " @@ -4004,7 +3913,7 @@ msgstr "" "ejemplo, `&[&[i32]]` para un slice de slices de dos dimensiones. ¿Por qué? " "¿Por qué no?" -#: src/exercises/day-1/for-loops.md:87 +#: src/exercises/day-1/for-loops.md:89 msgid "" "See the [`ndarray` crate](https://docs.rs/ndarray/) for a production quality " "implementation." @@ -4012,7 +3921,7 @@ msgstr "" "Consulta el [crate `ndarray`](https://docs.rs/ndarray/) para obtener una " "implementación con calidad de producción." -#: src/exercises/day-1/for-loops.md:92 +#: src/exercises/day-1/for-loops.md:94 msgid "" "The solution and the answer to the bonus section are available in the " "[Solution](solutions-morning.md#arrays-and-for-loops) section." @@ -4020,7 +3929,7 @@ msgstr "" "La solución y la respuesta a la pregunta extra están disponibles en la " "sección [soluciones](solutions-morning.md#arrays-and-for-loops)." -#: src/exercises/day-1/for-loops.md:95 +#: src/exercises/day-1/for-loops.md:97 msgid "" "The use of the reference `&array` within `for n in &array` is a subtle " "preview of issues of ownership that will come later in the afternoon." @@ -4029,11 +3938,11 @@ msgstr "" "previa sutil de los problemas de propiedad que se tratarán más tarde por la " "tarde." -#: src/exercises/day-1/for-loops.md:98 +#: src/exercises/day-1/for-loops.md:100 msgid "Without the `&`..." msgstr "Sin el `&`..." -#: src/exercises/day-1/for-loops.md:99 +#: src/exercises/day-1/for-loops.md:101 msgid "" "The loop would have been one that consumes the array. This is a change " "[introduced in the 2021 Edition](https://doc.rust-lang.org/edition-guide/" @@ -4043,7 +3952,7 @@ msgstr "" "[introducido en la edición de 2021](https://doc.rust-lang.org/edition-guide/" "rust-2021/IntoIterator-for-arrays.html)." -#: src/exercises/day-1/for-loops.md:102 +#: src/exercises/day-1/for-loops.md:104 msgid "" "An implicit array copy would have occurred. Since `i32` is a copy type, " "then `[i32; 3]` is also a copy type." @@ -4071,29 +3980,7 @@ msgstr "" "En Rust, un bloque contiene una secuencia de expresiones. Cada bloque tiene " "un tipo y un valor, que son los de la última expresión del bloque:" -#: src/control-flow/blocks.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let x = {\n" -" let y = 10;\n" -" println!(\"y: {y}\");\n" -" let z = {\n" -" let w = {\n" -" 3 + 4\n" -" };\n" -" println!(\"w: {w}\");\n" -" y * w\n" -" };\n" -" println!(\"z: {z}\");\n" -" z - y\n" -" };\n" -" println!(\"x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/blocks.md:26 +#: src/control-flow/blocks.md:27 msgid "" "If the last expression ends with `;`, then the resulting value and type is " "`()`." @@ -4101,7 +3988,7 @@ msgstr "" "Si la última expresión termina con `;`, el tipo y el valor resultante será " "`()`." -#: src/control-flow/blocks.md:28 +#: src/control-flow/blocks.md:29 msgid "" "The same rule is used for functions: the value of the function body is the " "return value:" @@ -4109,26 +3996,13 @@ msgstr "" "Se utiliza la misma regla para las funciones: el valor del cuerpo de la " "función es el valor devuelto:" -#: src/control-flow/blocks.md:31 -msgid "" -"```rust,editable\n" -"fn double(x: i32) -> i32 {\n" -" x + x\n" -"}\n" -"\n" -"fn main() {\n" -" println!(\"doubled: {}\", double(7));\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/blocks.md:43 src/enums.md:34 src/enums/sizes.md:28 +#: src/control-flow/blocks.md:45 src/enums.md:34 src/enums/sizes.md:28 #: src/pattern-matching.md:25 src/pattern-matching/match-guards.md:22 #: src/structs.md:31 src/methods.md:30 src/methods/example.md:46 msgid "Key Points:" msgstr "Puntos Clave:" -#: src/control-flow/blocks.md:44 +#: src/control-flow/blocks.md:46 msgid "" "The point of this slide is to show that blocks have a type and value in " "Rust. " @@ -4136,7 +4010,7 @@ msgstr "" "El objetivo de esta diapositiva es mostrar que los bloques tienen un tipo y " "un valor en Rust. " -#: src/control-flow/blocks.md:45 +#: src/control-flow/blocks.md:47 msgid "" "You can show how the value of the block changes by changing the last line in " "the block. For instance, adding/removing a semicolon or using a `return`." @@ -4157,20 +4031,6 @@ msgstr "" "expressions/if-expr.html#if-expressions) de la misma forma que en otros " "lenguajes:" -#: src/control-flow/if-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" if x % 2 == 0 {\n" -" x = x / 2;\n" -" } else {\n" -" x = 3 * x + 1;\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/control-flow/if-expressions.md:18 msgid "" "In addition, you can use `if` as an expression. The last expression of each " @@ -4179,20 +4039,6 @@ msgstr "" "Además, puedes utilizar `if` como expresión. La última expresión de cada " "bloque se convierte en el valor de la expresión `if`:" -#: src/control-flow/if-expressions.md:22 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -"}\n" -"```" -msgstr "" - #: src/control-flow/if-expressions.md:35 msgid "" "Because `if` is an expression and must have a particular type, both of its " @@ -4219,37 +4065,20 @@ msgstr "" "md). Llamará automáticamente a `into_iter()` en la expresión y después " "iterará sobre ella:" -#: src/control-flow/for-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -"\n" -" for x in v {\n" -" println!(\"x: {x}\");\n" -" }\n" -" \n" -" for i in (0..10).step_by(2) {\n" -" println!(\"i: {i}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/for-expressions.md:21 +#: src/control-flow/for-expressions.md:22 msgid "You can use `break` and `continue` here as usual." msgstr "Aquí puedes usar `break` y `continue` como de costumbre." -#: src/control-flow/for-expressions.md:25 +#: src/control-flow/for-expressions.md:26 msgid "Index iteration is not a special syntax in Rust for just that case." msgstr "" "La iteración de índices no es una sintaxis especial en Rust para ese caso." -#: src/control-flow/for-expressions.md:26 +#: src/control-flow/for-expressions.md:27 msgid "`(0..10)` is a range that implements an `Iterator` trait. " msgstr "`(0..10)` es un rango que implementa un `Iterator` trait." -#: src/control-flow/for-expressions.md:27 +#: src/control-flow/for-expressions.md:28 msgid "" "`step_by` is a method that returns another `Iterator` that skips every other " "element. " @@ -4257,7 +4086,7 @@ msgstr "" "`step_by` es un método que devuelve otro `Iterator` que salta cada otro " "elemento." -#: src/control-flow/for-expressions.md:28 +#: src/control-flow/for-expressions.md:29 msgid "" "Modify the elements in the vector and explain the compiler errors. Change " "vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." @@ -4277,23 +4106,6 @@ msgstr "" "La [palabra clave `while`](https://doc.rust-lang.org/reference/expressions/" "loop-expr.html#predicate-loops) es muy similar a otros lenguajes:" -#: src/control-flow/while-expressions.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" while x != 1 {\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -" }\n" -" println!(\"Final x: {x}\");\n" -"}\n" -"```" -msgstr "" - #: src/control-flow/break-continue.md:1 msgid "`break` and `continue`" msgstr "`break` y `continue`" @@ -4323,28 +4135,7 @@ msgstr "" "De forma opcional, tanto `continue` como `break` pueden utilizar un " "argumento de etiqueta para interrumpir los bucles anidados:" -#: src/control-flow/break-continue.md:10 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();\n" -" 'outer: while let Some(x) = iter.next() {\n" -" println!(\"x: {x}\");\n" -" let mut i = 0;\n" -" while i < x {\n" -" println!(\"x: {x}, i: {i}\");\n" -" i += 1;\n" -" if i == 3 {\n" -" break 'outer;\n" -" }\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/break-continue.md:28 +#: src/control-flow/break-continue.md:29 msgid "" "In this case we break the outer loop after 3 iterations of the inner loop." msgstr "" @@ -4367,31 +4158,11 @@ msgstr "" msgid "Here you must either `break` or `return` to stop the loop:" msgstr "Para detener el bucle, debes usar `break` o `return`:" -#: src/control-flow/loop-expressions.md:8 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" loop {\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -" if x == 1 {\n" -" break;\n" -" }\n" -" }\n" -" println!(\"Final x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/loop-expressions.md:27 +#: src/control-flow/loop-expressions.md:28 msgid "Break the `loop` with a value (e.g. `break 8`) and print it out." msgstr "Interrumpe `loop` con un valor (por ejemplo, `break 8`) e imprímelo." -#: src/control-flow/loop-expressions.md:28 +#: src/control-flow/loop-expressions.md:29 msgid "" "Note that `loop` is the only looping construct which returns a non-trivial " "value. This is because it's guaranteed to be entered at least once (unlike " @@ -4409,19 +4180,7 @@ msgstr "" "Rust ofrece seguridad de tipos mediante tipado estático. De forma " "predeterminada, los enlaces a variables son inmutables:" -#: src/basic-syntax/variables.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let x: i32 = 10;\n" -" println!(\"x: {x}\");\n" -" // x = 20;\n" -" // println!(\"x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/variables.md:17 +#: src/basic-syntax/variables.md:18 msgid "" "Due to type inference the `i32` is optional. We will gradually show the " "types less and less as the course progresses." @@ -4433,29 +4192,7 @@ msgstr "" msgid "Rust will look at how the variable is _used_ to determine the type:" msgstr "Rust consultará cómo se _usa_ la variable para determinar el tipo:" -#: src/basic-syntax/type-inference.md:5 -msgid "" -"```rust,editable\n" -"fn takes_u32(x: u32) {\n" -" println!(\"u32: {x}\");\n" -"}\n" -"\n" -"fn takes_i8(y: i8) {\n" -" println!(\"i8: {y}\");\n" -"}\n" -"\n" -"fn main() {\n" -" let x = 10;\n" -" let y = 20;\n" -"\n" -" takes_u32(x);\n" -" takes_i8(y);\n" -" // takes_u32(y);\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/type-inference.md:26 +#: src/basic-syntax/type-inference.md:27 msgid "" "This slide demonstrates how the Rust compiler infers types based on " "constraints given by variable declarations and usages." @@ -4463,7 +4200,7 @@ msgstr "" "Esta diapositiva muestra cómo el compilador de Rust infiere tipos basándose " "en restricciones proporcionadas por declaraciones y usos de variables." -#: src/basic-syntax/type-inference.md:28 +#: src/basic-syntax/type-inference.md:29 msgid "" "It is very important to emphasize that variables declared like this are not " "of some sort of dynamic \"any type\" that can hold any data. The machine " @@ -4477,7 +4214,7 @@ msgstr "" "de un tipo. El compilador hace el trabajo por nosotros y nos ayuda a " "escribir código más conciso." -#: src/basic-syntax/type-inference.md:32 +#: src/basic-syntax/type-inference.md:33 msgid "" "The following code tells the compiler to copy into a certain generic " "container without the code ever explicitly specifying the contained type, " @@ -4487,22 +4224,7 @@ msgstr "" "determinado contenedor genérico sin que el código especifique explícitamente " "el tipo contenido utilizando `_` como marcador de posición:" -#: src/basic-syntax/type-inference.md:34 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut v = Vec::new();\n" -" v.push((10, false));\n" -" v.push((20, true));\n" -" println!(\"v: {v:?}\");\n" -"\n" -" let vv = v.iter().collect::>();\n" -" println!(\"vv: {vv:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/type-inference.md:46 +#: src/basic-syntax/type-inference.md:48 msgid "" "[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator." "html#method.collect) relies on [`FromIterator`](https://doc.rust-lang.org/" @@ -4542,29 +4264,7 @@ msgstr "" "Las variables constantes se evalúan en tiempo de compilación y sus valores " "se insertan dondequiera que se utilicen:" -#: src/basic-syntax/static-and-const.md:11 -msgid "" -"```rust,editable\n" -"const DIGEST_SIZE: usize = 3;\n" -"const ZERO: Option = Some(42);\n" -"\n" -"fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {\n" -" let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];\n" -" for (idx, &b) in text.as_bytes().iter().enumerate() {\n" -" digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE]." -"wrapping_add(b);\n" -" }\n" -" digest\n" -"}\n" -"\n" -"fn main() {\n" -" let digest = compute_digest(\"Hello\");\n" -" println!(\"Digest: {digest:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/basic-syntax/static-and-const.md:29 +#: src/basic-syntax/static-and-const.md:30 #, fuzzy msgid "" "According to the [Rust RFC Book](https://rust-lang.github.io/rfcs/0246-const-" @@ -4573,7 +4273,7 @@ msgstr "" "Según el libro [Rust RFC Book](https://rust-lang.github.io/rfcs/0246-const-" "vs-static.html), se insertan cuando se utilizan." -#: src/basic-syntax/static-and-const.md:31 +#: src/basic-syntax/static-and-const.md:32 msgid "" "Only functions marked `const` can be called at compile time to generate " "`const` values. `const` functions can however be called at runtime." @@ -4582,11 +4282,11 @@ msgstr "" "compilación para generar valores `const`. Sin embargo, las funciones `const` " "se pueden llamar en _runtime_." -#: src/basic-syntax/static-and-const.md:33 +#: src/basic-syntax/static-and-const.md:34 msgid "`static`" msgstr "`static`" -#: src/basic-syntax/static-and-const.md:35 +#: src/basic-syntax/static-and-const.md:36 msgid "" "Static variables will live during the whole execution of the program, and " "therefore will not move:" @@ -4594,18 +4294,17 @@ msgstr "" "Las variables estáticas vivirán durante toda la ejecución del programa y, " "por lo tanto, no se moverán:" -#: src/basic-syntax/static-and-const.md:37 -msgid "" -"```rust,editable\n" -"static BANNER: &str = \"Welcome to RustOS 3.14\";\n" -"\n" -"fn main() {\n" -" println!(\"{BANNER}\");\n" -"}\n" -"```" +#: src/basic-syntax/static-and-const.md:39 +#, fuzzy +#| msgid "Welcome to Day 1" +msgid "\"Welcome to RustOS 3.14\"" +msgstr "Te damos la bienvenida al Día 1" + +#: src/basic-syntax/static-and-const.md:42 +msgid "\"{BANNER}\"" msgstr "" -#: src/basic-syntax/static-and-const.md:45 +#: src/basic-syntax/static-and-const.md:46 msgid "" "As noted in the [Rust RFC Book](https://rust-lang.github.io/rfcs/0246-const-" "vs-static.html), these are not inlined upon use and have an actual " @@ -4621,7 +4320,7 @@ msgstr "" "Cuando un valor de ámbito global no tiene ningún motivo para necesitar " "identidad de objeto, se suele preferir `const`." -#: src/basic-syntax/static-and-const.md:49 +#: src/basic-syntax/static-and-const.md:50 msgid "" "Because `static` variables are accessible from any thread, they must be " "`Sync`. Interior mutability is possible through a [`Mutex`](https://doc.rust-" @@ -4636,13 +4335,13 @@ msgstr "" "código `unsafe`. Veremos la [mutación de datos estáticos](../unsafe/mutable-" "static-variables.md) en el capítulo sobre Rust inseguro." -#: src/basic-syntax/static-and-const.md:57 +#: src/basic-syntax/static-and-const.md:58 msgid "Mention that `const` behaves semantically similar to C++'s `constexpr`." msgstr "" "Menciona que `const` se comporta semánticamente de forma similar a " "`constexpr` de C++." -#: src/basic-syntax/static-and-const.md:58 +#: src/basic-syntax/static-and-const.md:59 msgid "" "`static`, on the other hand, is much more similar to a `const` or mutable " "global variable in C++." @@ -4650,7 +4349,7 @@ msgstr "" "Por su parte, `static` se parece mucho más a `const` o a una variable global " "mutable de C++." -#: src/basic-syntax/static-and-const.md:59 +#: src/basic-syntax/static-and-const.md:60 msgid "" "`static` provides object identity: an address in memory and state as " "required by types with interior mutability such as `Mutex`." @@ -4659,7 +4358,7 @@ msgstr "" "en el estado que requieren los tipos con mutabilidad interior, como " "`Mutex`." -#: src/basic-syntax/static-and-const.md:60 +#: src/basic-syntax/static-and-const.md:61 msgid "" "It isn't super common that one would need a runtime evaluated constant, but " "it is helpful and safer than using a static." @@ -4667,69 +4366,69 @@ msgstr "" "No es muy habitual que se necesite una constante evaluada en _runtime_, pero " "es útil y más seguro que usar una estática." -#: src/basic-syntax/static-and-const.md:61 +#: src/basic-syntax/static-and-const.md:62 msgid "`thread_local` data can be created with the macro `std::thread_local`." msgstr "" "Datos del `thread_local` se pueden crear con la macro `std::thread_local`." -#: src/basic-syntax/static-and-const.md:63 +#: src/basic-syntax/static-and-const.md:64 msgid "Properties table:" msgstr "Tabla de Propiedades:" -#: src/basic-syntax/static-and-const.md:65 +#: src/basic-syntax/static-and-const.md:66 msgid "Property" msgstr "Propiedad" -#: src/basic-syntax/static-and-const.md:65 +#: src/basic-syntax/static-and-const.md:66 msgid "Static" msgstr "Estático" -#: src/basic-syntax/static-and-const.md:65 +#: src/basic-syntax/static-and-const.md:66 msgid "Constant" msgstr "Constante" -#: src/basic-syntax/static-and-const.md:67 +#: src/basic-syntax/static-and-const.md:68 msgid "Has an address in memory" msgstr "Tiene una dirección en la memoria" -#: src/basic-syntax/static-and-const.md:67 #: src/basic-syntax/static-and-const.md:68 -#: src/basic-syntax/static-and-const.md:70 +#: src/basic-syntax/static-and-const.md:69 #: src/basic-syntax/static-and-const.md:71 +#: src/basic-syntax/static-and-const.md:72 msgid "Yes" msgstr "Sí" -#: src/basic-syntax/static-and-const.md:67 +#: src/basic-syntax/static-and-const.md:68 msgid "No (inlined)" msgstr "No (insertado)" -#: src/basic-syntax/static-and-const.md:68 +#: src/basic-syntax/static-and-const.md:69 msgid "Lives for the entire duration of the program" msgstr "Vive durante toda la ejecución del programa" -#: src/basic-syntax/static-and-const.md:68 #: src/basic-syntax/static-and-const.md:69 -#: src/basic-syntax/static-and-const.md:71 +#: src/basic-syntax/static-and-const.md:70 +#: src/basic-syntax/static-and-const.md:72 msgid "No" msgstr "No" -#: src/basic-syntax/static-and-const.md:69 +#: src/basic-syntax/static-and-const.md:70 msgid "Can be mutable" msgstr "Puede ser mutable" -#: src/basic-syntax/static-and-const.md:69 +#: src/basic-syntax/static-and-const.md:70 msgid "Yes (unsafe)" msgstr "Sí (inseguro)" -#: src/basic-syntax/static-and-const.md:70 +#: src/basic-syntax/static-and-const.md:71 msgid "Evaluated at compile time" msgstr "Evaluado en tiempo de compilación" -#: src/basic-syntax/static-and-const.md:70 +#: src/basic-syntax/static-and-const.md:71 msgid "Yes (initialised at compile time)" msgstr "Sí (inicializado en tiempo de compilación)" -#: src/basic-syntax/static-and-const.md:71 +#: src/basic-syntax/static-and-const.md:72 msgid "Inlined wherever it is used" msgstr "Insertado dondequiera que se utilice" @@ -4741,24 +4440,25 @@ msgstr "" "Puedes sombrear variables, tanto las de ámbitos externos como las del propio " "ámbito:" -#: src/basic-syntax/scopes-shadowing.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let a = 10;\n" -" println!(\"before: {a}\");\n" -"\n" -" {\n" -" let a = \"hello\";\n" -" println!(\"inner scope: {a}\");\n" -"\n" -" let a = true;\n" -" println!(\"shadowed in inner scope: {a}\");\n" -" }\n" -"\n" -" println!(\"after: {a}\");\n" -"}\n" -"```" +#: src/basic-syntax/scopes-shadowing.md:9 +msgid "\"before: {a}\"" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:12 src/traits/from-into.md:7 +#: src/traits/from-into.md:19 +msgid "\"hello\"" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:13 +msgid "\"inner scope: {a}\"" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:16 +msgid "\"shadowed in inner scope: {a}\"" +msgstr "" + +#: src/basic-syntax/scopes-shadowing.md:19 +msgid "\"after: {a}\"" msgstr "" #: src/basic-syntax/scopes-shadowing.md:25 @@ -4794,18 +4494,6 @@ msgstr "" "reutilizar ubicaciones de memoria cuando sombrea una variable inmutable en " "un ámbito, incluso si el tipo no cambia." -#: src/basic-syntax/scopes-shadowing.md:30 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let a = 1;\n" -" let b = &a;\n" -" let a = a + 1;\n" -" println!(\"{a} {b}\");\n" -"}\n" -"```" -msgstr "" - #: src/enums.md:3 msgid "" "The `enum` keyword allows the creation of a type which has a few different " @@ -4813,59 +4501,17 @@ msgid "" msgstr "" "La palabra clave `enum` permite crear un tipo que tiene diferentes variantes:" -#: src/enums.md:6 -msgid "" -"```rust,editable\n" -"fn generate_random_number() -> i32 {\n" -" // Implementation based on https://xkcd.com/221/\n" -" 4 // Chosen by fair dice roll. Guaranteed to be random.\n" -"}\n" -"\n" -"#[derive(Debug)]\n" -"enum CoinFlip {\n" -" Heads,\n" -" Tails,\n" -"}\n" -"\n" -"fn flip_coin() -> CoinFlip {\n" -" let random_number = generate_random_number();\n" -" if random_number % 2 == 0 {\n" -" return CoinFlip::Heads;\n" -" } else {\n" -" return CoinFlip::Tails;\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" println!(\"You got: {:?}\", flip_coin());\n" -"}\n" -"```" +#: src/enums.md:8 +msgid "// Implementation based on https://xkcd.com/221/\n" +msgstr "" + +#: src/enums.md:9 +msgid "// Chosen by fair dice roll. Guaranteed to be random.\n" +msgstr "" + +#: src/enums.md:28 +msgid "\"You got: {:?}\"" msgstr "" -"```rust,editable\n" -"fn generate_random_number() -> i32 {\n" -" // Implementation based on https://xkcd.com/221/\n" -" 4 // Chosen by fair dice roll. Guaranteed to be random.\n" -"}\n" -"\n" -"#[derive(Debug)]\n" -"enum CoinFlip {\n" -" Heads,\n" -" Tails,\n" -"}\n" -"\n" -"fn flip_coin() -> CoinFlip {\n" -" let random_number = generate_random_number();\n" -" if random_number % 2 == 0 {\n" -" return CoinFlip::Heads;\n" -" } else {\n" -" return CoinFlip::Tails;\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" println!(\"You got: {:?}\", flip_coin());\n" -"}\n" -"```" #: src/enums.md:36 msgid "Enumerations allow you to collect a set of values under one type" @@ -4918,34 +4564,34 @@ msgstr "" "contienen datos. Después, puedes usar la instrucción `match` para extraer " "los datos de cada variante:" -#: src/enums/variant-payloads.md:6 -msgid "" -"```rust,editable\n" -"enum WebEvent {\n" -" PageLoad, // Variant without payload\n" -" KeyPress(char), // Tuple struct variant\n" -" Click { x: i64, y: i64 }, // Full struct variant\n" -"}\n" -"\n" -"#[rustfmt::skip]\n" -"fn inspect(event: WebEvent) {\n" -" match event {\n" -" WebEvent::PageLoad => println!(\"page loaded\"),\n" -" WebEvent::KeyPress(c) => println!(\"pressed '{c}'\"),\n" -" WebEvent::Click { x, y } => println!(\"clicked at x={x}, y={y}\"),\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let load = WebEvent::PageLoad;\n" -" let press = WebEvent::KeyPress('x');\n" -" let click = WebEvent::Click { x: 20, y: 80 };\n" -"\n" -" inspect(load);\n" -" inspect(press);\n" -" inspect(click);\n" -"}\n" -"```" +#: src/enums/variant-payloads.md:8 +#, fuzzy +#| msgid "Variant Payloads" +msgid "// Variant without payload\n" +msgstr "Payloads Variantes" + +#: src/enums/variant-payloads.md:9 +msgid "// Tuple struct variant\n" +msgstr "" + +#: src/enums/variant-payloads.md:10 +msgid "// Full struct variant\n" +msgstr "" + +#: src/enums/variant-payloads.md:16 +msgid "\"page loaded\"" +msgstr "" + +#: src/enums/variant-payloads.md:17 +msgid "\"pressed '{c}'\"" +msgstr "" + +#: src/enums/variant-payloads.md:18 +msgid "\"clicked at x={x}, y={y}\"" +msgstr "" + +#: src/enums/variant-payloads.md:24 src/pattern-matching.md:10 +msgid "'x'" msgstr "" #: src/enums/variant-payloads.md:35 @@ -5029,27 +4675,11 @@ msgstr "" "Las enumeraciones de Rust son densamente empaquetadas, ya que tienen en " "cuenta las restricciones debidas a la alineación:" -#: src/enums/sizes.md:5 -msgid "" -"```rust,editable\n" -"use std::any::type_name;\n" -"use std::mem::{align_of, size_of};\n" -"\n" -"fn dbg_size() {\n" -" println!(\"{}: size {} bytes, align: {} bytes\",\n" -" type_name::(), size_of::(), align_of::());\n" -"}\n" -"\n" -"enum Foo {\n" -" A,\n" -" B,\n" -"}\n" -"\n" -"fn main() {\n" -" dbg_size::();\n" -"}\n" -"```" -msgstr "" +#: src/enums/sizes.md:10 +#, fuzzy +#| msgid "`dbg_size!(bool)`: size 1 bytes, align: 1 bytes," +msgid "\"{}: size {} bytes, align: {} bytes\"" +msgstr "`dbg_size!(bool)`: tamaño de 1 byte, alineación de 1 byte," #: src/enums/sizes.md:24 msgid "" @@ -5074,25 +4704,7 @@ msgstr "" "Puedes controlar el discriminante si es necesario (por ejemplo, para " "asegurar la compatibilidad con C):" -#: src/enums/sizes.md:34 -msgid "" -"```rust,editable\n" -"#[repr(u32)]\n" -"enum Bar {\n" -" A, // 0\n" -" B = 10000,\n" -" C, // 10001\n" -"}\n" -"\n" -"fn main() {\n" -" println!(\"A: {}\", Bar::A as u32);\n" -" println!(\"B: {}\", Bar::B as u32);\n" -" println!(\"C: {}\", Bar::C as u32);\n" -"}\n" -"```" -msgstr "" - -#: src/enums/sizes.md:49 +#: src/enums/sizes.md:50 msgid "" "Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2 " "bytes." @@ -5100,15 +4712,15 @@ msgstr "" "Sin `repr`, el tipo discriminante ocupa 2 bytes, debido a que 10001 se cabe " "en 2 bytes." -#: src/enums/sizes.md:53 +#: src/enums/sizes.md:54 msgid "Try out other types such as" msgstr "Prueba otros tipos, como" -#: src/enums/sizes.md:55 +#: src/enums/sizes.md:56 msgid "`dbg_size!(bool)`: size 1 bytes, align: 1 bytes," msgstr "`dbg_size!(bool)`: tamaño de 1 byte, alineación de 1 byte," -#: src/enums/sizes.md:56 +#: src/enums/sizes.md:57 msgid "" "`dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche optimization, " "see below)," @@ -5116,13 +4728,13 @@ msgstr "" "`dbg_size!(Option)`: tamaño de 1 byte, alineación de 1 byte " "(optimización de nichos, consulta más abajo)," -#: src/enums/sizes.md:57 +#: src/enums/sizes.md:58 msgid "`dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit machine)," msgstr "" "`dbg_size!(&i32)`: tamaño de 8 bytes, alineación de 8 bytes (en una máquina " "de 64 bits)," -#: src/enums/sizes.md:58 +#: src/enums/sizes.md:59 msgid "" "`dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer " "optimization, see below)." @@ -5130,7 +4742,17 @@ msgstr "" "`dbg_size!(Option<&i32>)`: tamaño de 8 bytes, alineación de 8 bytes " "(optimización del puntero nulo, consulta más abajo)." -#: src/enums/sizes.md:60 +#: src/enums/sizes.md:61 src/memory-management/stack.md:32 +msgid "More to Explore" +msgstr "" + +#: src/enums/sizes.md:63 +msgid "" +"Rust has several optimizations it can employ to make enums take up less " +"space." +msgstr "" + +#: src/enums/sizes.md:65 msgid "" "Niche optimization: Rust will merge unused bit patterns for the enum " "discriminant." @@ -5138,7 +4760,7 @@ msgstr "" "Optimización de nichos: Rust combina los patrones de bits no utilizados para " "el discriminante de enumeración." -#: src/enums/sizes.md:63 +#: src/enums/sizes.md:68 msgid "" "Null pointer optimization: For [some types](https://doc.rust-lang.org/std/" "option/#representation), Rust guarantees that `size_of::()` equals " @@ -5148,7 +4770,7 @@ msgstr "" "std/option/#representation), Rust asegura que `size_of::()` es igual a " "`size_of:: >()`." -#: src/enums/sizes.md:67 +#: src/enums/sizes.md:72 msgid "" "Example code if you want to show how the bitwise representation _may_ look " "like in practice. It's important to note that the compiler provides no " @@ -5159,46 +4781,7 @@ msgstr "" "el compilador no ofrece garantías con respecto a esta representación, por lo " "tanto es totalmente inseguro. " -#: src/enums/sizes.md:70 -msgid "" -"```rust,editable\n" -"use std::mem::transmute;\n" -"\n" -"macro_rules! dbg_bits {\n" -" ($e:expr, $bit_type:ty) => {\n" -" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, " -"$bit_type>($e));\n" -" };\n" -"}\n" -"\n" -"fn main() {\n" -" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" -" // representation of types.\n" -" unsafe {\n" -" println!(\"Bitwise representation of bool\");\n" -" dbg_bits!(false, u8);\n" -" dbg_bits!(true, u8);\n" -"\n" -" println!(\"Bitwise representation of Option\");\n" -" dbg_bits!(None::, u8);\n" -" dbg_bits!(Some(false), u8);\n" -" dbg_bits!(Some(true), u8);\n" -"\n" -" println!(\"Bitwise representation of Option>\");\n" -" dbg_bits!(Some(Some(false)), u8);\n" -" dbg_bits!(Some(Some(true)), u8);\n" -" dbg_bits!(Some(None::), u8);\n" -" dbg_bits!(None::>, u8);\n" -"\n" -" println!(\"Bitwise representation of Option<&i32>\");\n" -" dbg_bits!(None::<&i32>, usize);\n" -" dbg_bits!(Some(&0i32), usize);\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/enums/sizes.md:105 +#: src/enums/sizes.md:109 msgid "" "More complex example if you want to discuss what happens when we chain more " "than 256 `Option`s together." @@ -5206,60 +4789,7 @@ msgstr "" "Ejemplo más complejo si quieres hablar de lo que pasa cuando encadenamos más " "de 256 `Option`." -#: src/enums/sizes.md:107 -msgid "" -"```rust,editable\n" -"#![recursion_limit = \"1000\"]\n" -"\n" -"use std::mem::transmute;\n" -"\n" -"macro_rules! dbg_bits {\n" -" ($e:expr, $bit_type:ty) => {\n" -" println!(\"- {}: {:#x}\", stringify!($e), transmute::<_, " -"$bit_type>($e));\n" -" };\n" -"}\n" -"\n" -"// Macro to wrap a value in 2^n Some() where n is the number of \"@\" " -"signs.\n" -"// Increasing the recursion limit is required to evaluate this macro.\n" -"macro_rules! many_options {\n" -" ($value:expr) => { Some($value) };\n" -" ($value:expr, @) => {\n" -" Some(Some($value))\n" -" };\n" -" ($value:expr, @ $($more:tt)+) => {\n" -" many_options!(many_options!($value, $($more)+), $($more)+)\n" -" };\n" -"}\n" -"\n" -"fn main() {\n" -" // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise\n" -" // representation of types.\n" -" unsafe {\n" -" assert_eq!(many_options!(false), Some(false));\n" -" assert_eq!(many_options!(false, @), Some(Some(false)));\n" -" assert_eq!(many_options!(false, @@), " -"Some(Some(Some(Some(false)))));\n" -"\n" -" println!(\"Bitwise representation of a chain of 128 Option's.\");\n" -" dbg_bits!(many_options!(false, @@@@@@@), u8);\n" -" dbg_bits!(many_options!(true, @@@@@@@), u8);\n" -"\n" -" println!(\"Bitwise representation of a chain of 256 Option's.\");\n" -" dbg_bits!(many_options!(false, @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(true, @@@@@@@@), u16);\n" -"\n" -" println!(\"Bitwise representation of a chain of 257 Option's.\");\n" -" dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);\n" -" dbg_bits!(many_options!(None::, @@@@@@@@), u16);\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/novel.md:3 +#: src/control-flow/novel.md:3 msgid "" "Rust has a few control flow constructs which differ from other languages. " "They are used for pattern matching:" @@ -5289,22 +4819,16 @@ msgstr "" "expr.html#if-let-expressions) te permite ejecutar código diferente en " "función de si un valor coincide con un patrón:" -#: src/control-flow/if-let-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let arg = std::env::args().next();\n" -" if let Some(value) = arg {\n" -" println!(\"Program name: {value}\");\n" -" } else {\n" -" println!(\"Missing name?\");\n" -" }\n" -"}\n" -"```" +#: src/control-flow/if-let-expressions.md:11 +msgid "\"Program name: {value}\"" +msgstr "" + +#: src/control-flow/if-let-expressions.md:13 +msgid "\"Missing name?\"" msgstr "" #: src/control-flow/if-let-expressions.md:18 -#: src/control-flow/while-let-expressions.md:21 +#: src/control-flow/while-let-expressions.md:22 #: src/control-flow/match-expressions.md:23 msgid "" "See [pattern matching](../pattern-matching.md) for more details on patterns " @@ -5347,24 +4871,6 @@ msgstr "" "necesario para anular el flujo de control normal (con `panic`/`return`/" "`break`/`continue`)::" -#: src/control-flow/if-let-expressions.md:28 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"{:?}\", second_word_to_upper(\"foo bar\"));\n" -"}\n" -" \n" -"fn second_word_to_upper(s: &str) -> Option {\n" -" let mut it = s.split(' ');\n" -" let (Some(_), Some(item)) = (it.next(), it.next()) else {\n" -" return None;\n" -" };\n" -" Some(item.to_uppercase())\n" -"}\n" -"\n" -"```" -msgstr "" - #: src/control-flow/while-let-expressions.md:1 msgid "`while let` loops" msgstr "Bucles `while let`" @@ -5379,21 +4885,7 @@ msgstr "" "lang.org/reference/expressions/loop-expr.html#predicate-pattern-loops) que " "prueba repetidamente un valor con respecto a un patrón:" -#: src/control-flow/while-let-expressions.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();\n" -"\n" -" while let Some(x) = iter.next() {\n" -" println!(\"x: {x}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/while-let-expressions.md:17 +#: src/control-flow/while-let-expressions.md:18 msgid "" "Here the iterator returned by `v.into_iter()` will return a `Option` on " "every call to `next()`. It returns `Some(x)` until it is done, after which " @@ -5405,7 +4897,7 @@ msgstr "" "continuación, devuelve `None`. `while let` nos permite seguir iterando a " "través de todos los elementos." -#: src/control-flow/while-let-expressions.md:26 +#: src/control-flow/while-let-expressions.md:27 msgid "" "Point out that the `while let` loop will keep going as long as the value " "matches the pattern." @@ -5413,7 +4905,7 @@ msgstr "" "Señala que el bucle `while let` seguirá funcionando siempre que el valor " "coincida con el patrón." -#: src/control-flow/while-let-expressions.md:27 +#: src/control-flow/while-let-expressions.md:28 msgid "" "You could rewrite the `while let` loop as an infinite loop with an if " "statement that breaks when there is no value to unwrap for `iter.next()`. " @@ -5435,20 +4927,46 @@ msgstr "" "o varios patrones. En ese sentido, funciona como una serie de expresiones " "`if let`:" -#: src/control-flow/match-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" match std::env::args().next().as_deref() {\n" -" Some(\"cat\") => println!(\"Will do cat things\"),\n" -" Some(\"ls\") => println!(\"Will ls some files\"),\n" -" Some(\"mv\") => println!(\"Let's move some files\"),\n" -" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" -" None => println!(\"Hmm, no program name?\"),\n" -" _ => println!(\"Unknown program name!\"),\n" -" }\n" -"}\n" -"```" +#: src/control-flow/match-expressions.md:10 +msgid "\"cat\"" +msgstr "" + +#: src/control-flow/match-expressions.md:10 +#, fuzzy +#| msgid "We will look at two things:" +msgid "\"Will do cat things\"" +msgstr "Veremos todas estas cosas:" + +#: src/control-flow/match-expressions.md:11 +msgid "\"ls\"" +msgstr "" + +#: src/control-flow/match-expressions.md:11 +msgid "\"Will ls some files\"" +msgstr "" + +#: src/control-flow/match-expressions.md:12 +msgid "\"mv\"" +msgstr "" + +#: src/control-flow/match-expressions.md:12 +msgid "\"Let's move some files\"" +msgstr "" + +#: src/control-flow/match-expressions.md:13 +msgid "\"rm\"" +msgstr "" + +#: src/control-flow/match-expressions.md:13 +msgid "\"Uh, dangerous!\"" +msgstr "" + +#: src/control-flow/match-expressions.md:14 +msgid "\"Hmm, no program name?\"" +msgstr "" + +#: src/control-flow/match-expressions.md:15 +msgid "\"Unknown program name!\"" msgstr "" #: src/control-flow/match-expressions.md:20 @@ -5492,8 +5010,12 @@ msgstr "" "con `&str` dentro de `Option`." #: src/pattern-matching.md:3 +#, fuzzy +#| msgid "" +#| "The `match` keyword let you match a value against one or more _patterns_. " +#| "The comparisons are done from top to bottom and the first match wins." msgid "" -"The `match` keyword let you match a value against one or more _patterns_. " +"The `match` keyword lets you match a value against one or more _patterns_. " "The comparisons are done from top to bottom and the first match wins." msgstr "" "La palabra clave `match` te permite comparar un valor con uno o varios " @@ -5506,20 +5028,48 @@ msgstr "" "Los patrones pueden ser valores simples, del mismo modo que `switch` en C y " "C++:" -#: src/pattern-matching.md:8 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let input = 'x';\n" -"\n" -" match input {\n" -" 'q' => println!(\"Quitting\"),\n" -" 'a' | 's' | 'w' | 'd' => println!(\"Moving around\"),\n" -" '0'..='9' => println!(\"Number input\"),\n" -" _ => println!(\"Something else\"),\n" -" }\n" -"}\n" -"```" +#: src/pattern-matching.md:13 +msgid "'q'" +msgstr "" + +#: src/pattern-matching.md:13 +msgid "\"Quitting\"" +msgstr "" + +#: src/pattern-matching.md:14 +msgid "'a'" +msgstr "" + +#: src/pattern-matching.md:14 +msgid "'s'" +msgstr "" + +#: src/pattern-matching.md:14 +msgid "'w'" +msgstr "" + +#: src/pattern-matching.md:14 +msgid "'d'" +msgstr "" + +#: src/pattern-matching.md:14 +msgid "\"Moving around\"" +msgstr "" + +#: src/pattern-matching.md:15 +msgid "'0'" +msgstr "" + +#: src/pattern-matching.md:15 +msgid "'9'" +msgstr "" + +#: src/pattern-matching.md:15 +msgid "\"Number input\"" +msgstr "" + +#: src/pattern-matching.md:16 +msgid "\"Something else\"" msgstr "" #: src/pattern-matching.md:21 @@ -5579,30 +5129,16 @@ msgstr "" "valores. Así es como se inspecciona la estructura de tus tipos. Empecemos " "con un tipo `enum` sencillo:" -#: src/pattern-matching/destructuring-enums.md:6 -msgid "" -"```rust,editable\n" -"enum Result {\n" -" Ok(i32),\n" -" Err(String),\n" -"}\n" -"\n" -"fn divide_in_two(n: i32) -> Result {\n" -" if n % 2 == 0 {\n" -" Result::Ok(n / 2)\n" -" } else {\n" -" Result::Err(format!(\"cannot divide {n} into two equal parts\"))\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let n = 100;\n" -" match divide_in_two(n) {\n" -" Result::Ok(half) => println!(\"{n} divided in two is {half}\"),\n" -" Result::Err(msg) => println!(\"sorry, an error happened: {msg}\"),\n" -" }\n" -"}\n" -"```" +#: src/pattern-matching/destructuring-enums.md:16 +msgid "\"cannot divide {n} into two equal parts\"" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:23 +msgid "\"{n} divided in two is {half}\"" +msgstr "" + +#: src/pattern-matching/destructuring-enums.md:24 +msgid "\"sorry, an error happened: {msg}\"" msgstr "" #: src/pattern-matching/destructuring-enums.md:29 @@ -5638,25 +5174,16 @@ msgstr "" msgid "You can also destructure `structs`:" msgstr "También puedes desestructurar `structs`:" -#: src/pattern-matching/destructuring-structs.md:5 -msgid "" -"```rust,editable\n" -"struct Foo {\n" -" x: (u32, u32),\n" -" y: u32,\n" -"}\n" -"\n" -"#[rustfmt::skip]\n" -"fn main() {\n" -" let foo = Foo { x: (1, 2), y: 3 };\n" -" match foo {\n" -" Foo { x: (1, b), y } => println!(\"x.0 = 1, b = {b}, y = {y}\"),\n" -" Foo { y: 2, x: i } => println!(\"y = 2, x = {i:?}\"),\n" -" Foo { y, .. } => println!(\"y = {y}, other fields were " -"ignored\"),\n" -" }\n" -"}\n" -"```" +#: src/pattern-matching/destructuring-structs.md:15 +msgid "\"x.0 = 1, b = {b}, y = {y}\"" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md:16 +msgid "\"y = 2, x = {i:?}\"" +msgstr "" + +#: src/pattern-matching/destructuring-structs.md:17 +msgid "\"y = {y}, other fields were ignored\"" msgstr "" #: src/pattern-matching/destructuring-structs.md:23 @@ -5687,20 +5214,23 @@ msgstr "" "Puedes desestructurar arrays, tuplas y slices haciendo coincidir sus " "elementos:" -#: src/pattern-matching/destructuring-arrays.md:5 -msgid "" -"```rust,editable\n" -"#[rustfmt::skip]\n" -"fn main() {\n" -" let triple = [0, -2, 3];\n" -" println!(\"Tell me about {triple:?}\");\n" -" match triple {\n" -" [0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" -" [1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" -" _ => println!(\"All elements were ignored\"),\n" -" }\n" -"}\n" -"```" +#: src/pattern-matching/destructuring-arrays.md:9 +msgid "\"Tell me about {triple:?}\"" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:11 +#: src/pattern-matching/destructuring-arrays.md:34 +msgid "\"First is 0, y = {y}, and z = {z}\"" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:12 +#: src/pattern-matching/destructuring-arrays.md:35 +msgid "\"First is 1 and the rest were ignored\"" +msgstr "" + +#: src/pattern-matching/destructuring-arrays.md:13 +#: src/pattern-matching/destructuring-arrays.md:36 +msgid "\"All elements were ignored\"" msgstr "" #: src/pattern-matching/destructuring-arrays.md:21 @@ -5711,24 +5241,8 @@ msgstr "" "La desestructuración de slices de longitud desconocida también funciona con " "patrones de longitud fija." -#: src/pattern-matching/destructuring-arrays.md:24 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" inspect(&[0, -2, 3]);\n" -" inspect(&[0, -2, 3, 4]);\n" -"}\n" -"\n" -"#[rustfmt::skip]\n" -"fn inspect(slice: &[i32]) {\n" -" println!(\"Tell me about {slice:?}\");\n" -" match slice {\n" -" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n" -" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n" -" _ => println!(\"All elements were ignored\"),\n" -" }\n" -"}\n" -"```" +#: src/pattern-matching/destructuring-arrays.md:32 +msgid "\"Tell me about {slice:?}\"" msgstr "" #: src/pattern-matching/destructuring-arrays.md:41 @@ -5761,21 +5275,26 @@ msgstr "" "trata de una expresión booleana arbitraria que se ejecutará si el patrón " "coincide:" -#: src/pattern-matching/match-guards.md:6 -msgid "" -"```rust,editable\n" -"#[rustfmt::skip]\n" -"fn main() {\n" -" let pair = (2, -2);\n" -" println!(\"Tell me about {pair:?}\");\n" -" match pair {\n" -" (x, y) if x == y => println!(\"These are twins\"),\n" -" (x, y) if x + y == 0 => println!(\"Antimatter, kaboom!\"),\n" -" (x, _) if x % 2 == 1 => println!(\"The first one is odd\"),\n" -" _ => println!(\"No correlation...\"),\n" -" }\n" -"}\n" -"```" +#: src/pattern-matching/match-guards.md:10 +msgid "\"Tell me about {pair:?}\"" +msgstr "" + +#: src/pattern-matching/match-guards.md:12 +#, fuzzy +#| msgid "There are no exceptions." +msgid "\"These are twins\"" +msgstr "No hay excepciones." + +#: src/pattern-matching/match-guards.md:13 +msgid "\"Antimatter, kaboom!\"" +msgstr "" + +#: src/pattern-matching/match-guards.md:14 +msgid "\"The first one is odd\"" +msgstr "" + +#: src/pattern-matching/match-guards.md:15 +msgid "\"No correlation...\"" msgstr "" #: src/pattern-matching/match-guards.md:23 @@ -5899,57 +5418,154 @@ msgstr "" "`for` e enteros. Luego, vuelve a la solución e intenta implementarla con " "iteradores." -#: src/exercises/day-1/luhn.md:25 +#: src/exercises/day-1/luhn.md:35 +#: src/exercises/day-2/iterators-and-ownership.md:75 +#: src/exercises/day-2/iterators-and-ownership.md:91 +#: src/traits/trait-bounds.md:22 src/traits/impl-trait.md:14 +#: src/exercises/day-3/simple-gui.md:148 src/exercises/day-3/simple-gui.md:149 +#: src/exercises/day-3/simple-gui.md:150 src/testing/test-modules.md:21 +#: src/exercises/day-1/solutions-afternoon.md:49 +msgid "\"foo\"" +msgstr "" + +#: src/exercises/day-1/luhn.md:36 src/exercises/day-1/solutions-afternoon.md:50 +msgid "\"foo 0 0\"" +msgstr "" + +#: src/exercises/day-1/luhn.md:41 src/testing/unit-tests.md:15 +#: src/exercises/day-1/solutions-afternoon.md:55 +#: src/exercises/day-3/solutions-morning.md:90 +#: src/exercises/day-3/solutions-morning.md:92 +#: src/exercises/day-3/solutions-morning.md:96 +#: src/exercises/day-3/solutions-morning.md:110 +#: src/exercises/day-3/solutions-morning.md:114 +msgid "\"\"" +msgstr "" + +#: src/exercises/day-1/luhn.md:42 src/exercises/day-1/solutions-afternoon.md:56 +msgid "\" \"" +msgstr "" + +#: src/exercises/day-1/luhn.md:43 src/exercises/day-1/solutions-afternoon.md:57 +msgid "\" \"" +msgstr "" + +#: src/exercises/day-1/luhn.md:44 src/exercises/day-1/solutions-afternoon.md:58 +msgid "\" \"" +msgstr "" + +#: src/exercises/day-1/luhn.md:49 src/exercises/day-1/solutions-afternoon.md:63 +msgid "\"0\"" +msgstr "" + +#: src/exercises/day-1/luhn.md:54 src/exercises/day-1/solutions-afternoon.md:68 +msgid "\" 0 0 \"" +msgstr "" + +#: src/exercises/day-1/luhn.md:59 src/exercises/day-1/solutions-afternoon.md:73 +msgid "\"4263 9826 4026 9299\"" +msgstr "" + +#: src/exercises/day-1/luhn.md:60 src/exercises/day-1/solutions-afternoon.md:74 +msgid "\"4539 3195 0343 6467\"" +msgstr "" + +#: src/exercises/day-1/luhn.md:61 src/exercises/day-1/solutions-afternoon.md:75 +msgid "\"7992 7398 713\"" +msgstr "" + +#: src/exercises/day-1/luhn.md:66 src/exercises/day-1/solutions-afternoon.md:80 +msgid "\"4223 9826 4026 9299\"" +msgstr "" + +#: src/exercises/day-1/luhn.md:67 src/exercises/day-1/solutions-afternoon.md:81 +msgid "\"4539 3195 0343 6476\"" +msgstr "" + +#: src/exercises/day-1/luhn.md:68 src/exercises/day-1/solutions-afternoon.md:82 +msgid "\"8273 1232 7352 0569\"" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:1 +msgid "Exercise: Expression Evaluation" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:3 +msgid "Let's write a simple recursive evaluator for arithmetic expressions. " +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:6 +#: src/exercises/day-1/solutions-afternoon.md:89 +msgid "/// An operation to perform on two subexpressions.\n" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:14 +#: src/exercises/day-1/solutions-afternoon.md:97 +msgid "/// An expression, in tree form.\n" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:18 +#: src/exercises/day-1/solutions-afternoon.md:101 +msgid "/// An operation on two subexpressions.\n" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:25 +#: src/exercises/day-1/solutions-afternoon.md:108 +msgid "/// A literal value\n" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:28 +#: src/exercises/day-1/solutions-afternoon.md:111 +msgid "/// The result of evaluating an expression.\n" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:32 +#: src/exercises/day-1/solutions-afternoon.md:115 +msgid "/// Evaluation was successful, with the given result.\n" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:34 +#: src/exercises/day-1/solutions-afternoon.md:117 +msgid "/// Evaluation failed, with the given error message.\n" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:36 +#: src/exercises/day-1/solutions-afternoon.md:119 +msgid "// Allow `Ok` and `Err` as shorthands for `Res::Ok` and `Res::Err`.\n" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:95 +#: src/exercises/day-1/solutions-afternoon.md:140 +#: src/exercises/day-1/solutions-afternoon.md:202 +msgid "\"division by zero\"" +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:100 msgid "" -"```rust\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]\n" -"\n" -"pub fn luhn(cc_number: &str) -> bool {\n" -" unimplemented!()\n" -"}\n" -"\n" -"#[test]\n" -"fn test_non_digit_cc_number() {\n" -" assert!(!luhn(\"foo\"));\n" -" assert!(!luhn(\"foo 0 0\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_empty_cc_number() {\n" -" assert!(!luhn(\"\"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_single_digit_cc_number() {\n" -" assert!(!luhn(\"0\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_two_digit_cc_number() {\n" -" assert!(luhn(\" 0 0 \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_valid_cc_number() {\n" -" assert!(luhn(\"4263 9826 4026 9299\"));\n" -" assert!(luhn(\"4539 3195 0343 6467\"));\n" -" assert!(luhn(\"7992 7398 713\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_invalid_cc_number() {\n" -" assert!(!luhn(\"4223 9826 4026 9299\"));\n" -" assert!(!luhn(\"4539 3195 0343 6476\"));\n" -" assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}\n" -"\n" -"#[allow(dead_code)]\n" -"fn main() {}\n" -"```" +"The `Box` type here is a smart pointer, and will be covered in detail later " +"in the course. An expression can be \"boxed\" with `Box::new` as seen in the " +"tests. To evaluate a boxed expression, use the deref operator to \"unbox\" " +"it: `eval(*boxed_expr)`." +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:105 +msgid "" +"Some expressions cannot be evaluated and will return an error. The `Res` " +"type represents either a successful value or an error with a message. This " +"is very similar to the standard-library `Result` which we will see later." +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:109 +msgid "" +"Copy and paste the code into the Rust playground, and begin implementing " +"`eval`. The final product should pass the tests. It may be helpful to use " +"`todo!()` and get the tests to pass one-by-one." +msgstr "" + +#: src/exercises/day-1/pattern-matching.md:113 +msgid "" +"If you finish early, try writing a test that results in an integer overflow. " +"How could you handle this with `Res::Err` instead of a panic?" msgstr "" #: src/welcome-day-2.md:1 @@ -6084,30 +5700,11 @@ msgstr "" "Al crear un `String`, los metadatos de tamaño fijo se colocan en la _stack_ " "y los datos de tamaño dinámico (la cadena real) en el _heap_:" -#: src/memory-management/stack.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1 = String::from(\"Hello\");\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/stack.md:12 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| H | e | l | l | o | :\n" -": | len | 5 | : : +----+----+----+----+----+ :\n" -": | capacity | 5 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" +#: src/memory-management/stack.md:8 src/memory-management/stack.md:39 +#: src/std/string.md:8 src/traits/read-write.md:35 src/testing/unit-tests.md:20 +#: src/testing/unit-tests.md:25 src/testing/test-modules.md:12 +#: src/concurrency/scoped-threads.md:9 src/concurrency/scoped-threads.md:26 +msgid "\"Hello\"" msgstr "" #: src/memory-management/stack.md:28 @@ -6132,32 +5729,37 @@ msgstr "" "asignadores personalizados mediante el [_Allocator API_](https://doc.rust-" "lang.org/std/alloc/index.html)." -#: src/memory-management/stack.md:32 +#: src/memory-management/stack.md:34 +#, fuzzy +#| msgid "" +#| "We can inspect the memory layout with `unsafe` code. However, you should " +#| "point out that this is rightfully unsafe!" msgid "" -"We can inspect the memory layout with `unsafe` code. However, you should " +"We can inspect the memory layout with `unsafe` Rust. However, you should " "point out that this is rightfully unsafe!" msgstr "" "Podemos inspeccionar la disposición de la memoria con código `unsafe`. Sin " "embargo, debes señalar que esto no es seguro." -#: src/memory-management/stack.md:34 +#: src/memory-management/stack.md:40 src/testing/unit-tests.md:7 +#: src/exercises/day-1/solutions-afternoon.md:13 +msgid "' '" +msgstr "" + +#: src/memory-management/stack.md:41 +msgid "\"world\"" +msgstr "" + +#: src/memory-management/stack.md:42 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut s1 = String::from(\"Hello\");\n" -" s1.push(' ');\n" -" s1.push_str(\"world\");\n" -" // DON'T DO THIS AT HOME! For educational purposes only.\n" +"// DON'T DO THIS AT HOME! For educational purposes only.\n" " // String provides no guarantees about its layout, so this could lead " "to\n" " // undefined behavior.\n" -" unsafe {\n" -" let (ptr, capacity, len): (usize, usize, usize) = std::mem::" -"transmute(s1);\n" -" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" -" }\n" -"}\n" -"```" +msgstr "" + +#: src/memory-management/stack.md:47 +msgid "\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\"" msgstr "" #: src/memory-management/manual.md:3 @@ -6180,17 +5782,11 @@ msgstr "Ejemplo en C" msgid "You must call `free` on every pointer you allocate with `malloc`:" msgstr "Debes llamar a `free` en cada puntero que asignes con `malloc`:" -#: src/memory-management/manual.md:11 +#: src/memory-management/manual.md:14 msgid "" -"```c\n" -"void foo(size_t n) {\n" -" int* int_array = malloc(n * sizeof(int));\n" -" //\n" +"//\n" " // ... lots of code\n" " //\n" -" free(int_array);\n" -"}\n" -"```" msgstr "" #: src/memory-management/manual.md:21 @@ -6235,20 +5831,6 @@ msgstr "" msgid "C++ Example" msgstr "Ejemplo en C++" -#: src/memory-management/scope-based.md:14 -msgid "" -"```c++\n" -"void say_hello(std::unique_ptr person) {\n" -" std::cout << \"Hello \" << person->name << std::endl;\n" -"}\n" -"```" -msgstr "" -"```c++\n" -"void say_hello(std::unique_ptr person) {\n" -" std::cout << \"Hola \" << person->name << std::endl;\n" -"}\n" -"```" - #: src/memory-management/scope-based.md:20 msgid "" "The `std::unique_ptr` object is allocated on the stack, and points to memory " @@ -6272,14 +5854,6 @@ msgstr "" "Los constructores de movimiento especiales se utilizan cuando se pasa el " "_ownership_ a una función:" -#: src/memory-management/scope-based.md:27 -msgid "" -"```c++\n" -"std::unique_ptr person = find_person(\"Carla\");\n" -"say_hello(std::move(person));\n" -"```" -msgstr "" - #: src/memory-management/garbage-collection.md:1 msgid "Automatic Memory Management" msgstr "Gestión Automática de la Memoria" @@ -6315,20 +5889,6 @@ msgstr "" "El objeto `person` no se libera después de que `sayHello` devuelva el " "siguiente resultado:" -#: src/memory-management/garbage-collection.md:13 -msgid "" -"```java\n" -"void sayHello(Person person) {\n" -" System.out.println(\"Hello \" + person.getName());\n" -"}\n" -"```" -msgstr "" -"```java\n" -"void sayHello(Person person) {\n" -" System.out.println(\"Hola \" + person.getName());\n" -"}\n" -"```" - #: src/memory-management/rust.md:1 msgid "Memory Management in Rust" msgstr "Gestión de la Memoria en Rust" @@ -6394,31 +5954,16 @@ msgstr "" "Todos los enlaces a variables tienen un _ámbito_ donde son válidos y se " "produce un error cuando se usan fuera de él:" -#: src/ownership.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"struct Point(i32, i32);\n" -"\n" -"fn main() {\n" -" {\n" -" let p = Point(3, 4);\n" -" println!(\"x: {}\", p.0);\n" -" }\n" -" println!(\"y: {}\", p.1);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership.md:18 +#: src/ownership.md:19 msgid "" "At the end of the scope, the variable is _dropped_ and the data is freed." msgstr "Al final del ámbito, la variable _se elimina_ y los datos se liberan." -#: src/ownership.md:19 +#: src/ownership.md:20 msgid "A destructor can run here to free up resources." msgstr "Se puede ejecutar un destructor para liberar recursos." -#: src/ownership.md:20 +#: src/ownership.md:21 msgid "We say that the variable _owns_ the value." msgstr "Decimos que el valor _pertenece_ a la variable." @@ -6426,25 +5971,15 @@ msgstr "Decimos que el valor _pertenece_ a la variable." msgid "An assignment will transfer _ownership_ between variables:" msgstr "Una asignación transferirá su _ownership_ entre variables:" -#: src/ownership/move-semantics.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1: String = String::from(\"Hello!\");\n" -" let s2: String = s1;\n" -" println!(\"s2: {s2}\");\n" -" // println!(\"s1: {s1}\");\n" -"}\n" -"```" +#: src/ownership/move-semantics.md:7 +#, fuzzy +#| msgid "Hello World!" +msgid "\"Hello!\"" +msgstr "¡Hola, mundo!" + +#: src/ownership/move-semantics.md:10 +msgid "// println!(\"s1: {s1}\");\n" msgstr "" -"```rust,editable\n" -"fn main() {\n" -" let s1: String = String::from(\"Hola!\");\n" -" let s2: String = s1;\n" -" println!(\"s2: {s2}\");\n" -" // println!(\"s1: {s1}\");\n" -"}\n" -"```" #: src/ownership/move-semantics.md:14 msgid "The assignment of `s1` to `s2` transfers ownership." @@ -6493,51 +6028,23 @@ msgstr "" msgid "In Rust, clones are explicit (by using `clone`)." msgstr "En Rust, la clonación es explícita (usando `clone`)." -#: src/ownership/moved-strings-rust.md:3 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1: String = String::from(\"Rust\");\n" -" let s2: String = s1;\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/moved-strings-rust.md:10 +#: src/ownership/moved-strings-rust.md:11 msgid "The heap data from `s1` is reused for `s2`." msgstr "Los datos del _heap_ de `s1` se reutilizan en `s2`." -#: src/ownership/moved-strings-rust.md:11 +#: src/ownership/moved-strings-rust.md:12 msgid "When `s1` goes out of scope, nothing happens (it has been moved from)." msgstr "Cuando `s1` sale del ámbito, no ocurre nada (ha sido movida)." -#: src/ownership/moved-strings-rust.md:13 +#: src/ownership/moved-strings-rust.md:14 msgid "Before move to `s2`:" msgstr "Antes de mover a `s2`:" -#: src/ownership/moved-strings-rust.md:15 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| R | u | s | t | :\n" -": | len | 4 | : : +----+----+----+----+ :\n" -": | capacity | 4 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - -'\n" -": :\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/ownership/moved-strings-rust.md:30 +#: src/ownership/moved-strings-rust.md:31 msgid "After move to `s2`:" msgstr "Después de mover a `s2`:" -#: src/ownership/moved-strings-rust.md:32 +#: src/ownership/moved-strings-rust.md:33 msgid "" "```bob\n" " Stack Heap\n" @@ -6590,17 +6097,13 @@ msgstr "Double free en código C++ moderno" msgid "Modern C++ solves this differently:" msgstr "La versión moderna de C++ soluciona este problema de forma diferente:" -#: src/ownership/double-free-modern-cpp.md:5 -msgid "" -"```c++\n" -"std::string s1 = \"Cpp\";\n" -"std::string s2 = s1; // Duplicate the data in s1.\n" -"```" +#: src/ownership/double-free-modern-cpp.md:6 +msgid "\"Cpp\"" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:7 +msgid "// Duplicate the data in s1.\n" msgstr "" -"```c++\n" -"std::string s1 = \"Cpp\";\n" -"std::string s2 = s1; // Duplicar datos en s1.\n" -"```" #: src/ownership/double-free-modern-cpp.md:10 msgid "" @@ -6618,84 +6121,10 @@ msgstr "" msgid "Before copy-assignment:" msgstr "Antes de la asignación de copias:" -#: src/ownership/double-free-modern-cpp.md:16 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" -"```bob\n" -" _Stack_ _Heap_\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" - #: src/ownership/double-free-modern-cpp.md:30 msgid "After copy-assignment:" msgstr "Después de la asignación de copia:" -#: src/ownership/double-free-modern-cpp.md:32 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : : :\n" -": s2 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+-----+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" -"```bob\n" -" _Stack_ _Heap_\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : : :\n" -": s2 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+-----+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" - #: src/ownership/double-free-modern-cpp.md:57 msgid "" "C++ has made a slightly different choice than Rust. Because `=` copies data, " @@ -6726,19 +6155,19 @@ msgstr "" "Cuando pasas un valor a una función, el valor se asigna al parámetro de la " "función. Esta acción transfiere el _ownership_:" -#: src/ownership/moves-function-calls.md:6 -msgid "" -"```rust,editable\n" -"fn say_hello(name: String) {\n" -" println!(\"Hello {name}\")\n" -"}\n" -"\n" -"fn main() {\n" -" let name = String::from(\"Alice\");\n" -" say_hello(name);\n" -" // say_hello(name);\n" -"}\n" -"```" +#: src/ownership/moves-function-calls.md:8 src/traits/impl-trait.md:10 +msgid "\"Hello {name}\"" +msgstr "" + +#: src/ownership/moves-function-calls.md:12 +#: src/android/interoperability/java.md:56 +#, fuzzy +#| msgid "Slices" +msgid "\"Alice\"" +msgstr "Slices" + +#: src/ownership/moves-function-calls.md:14 +msgid "// say_hello(name);\n" msgstr "" #: src/ownership/moves-function-calls.md:20 @@ -6789,58 +6218,31 @@ msgstr "" "Aunque la semántica de movimiento es la opción predeterminada, algunos tipos " "se copian de forma predeterminada:" -#: src/ownership/copy-clone.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let x = 42;\n" -" let y = x;\n" -" println!(\"x: {x}\");\n" -" println!(\"y: {y}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/copy-clone.md:14 +#: src/ownership/copy-clone.md:15 msgid "These types implement the `Copy` trait." msgstr "Estos tipos implementan el trait `Copy`." -#: src/ownership/copy-clone.md:16 +#: src/ownership/copy-clone.md:17 msgid "You can opt-in your own types to use copy semantics:" msgstr "" "Puedes habilitar tus propios tipos para que usen la semántica de copia:" -#: src/ownership/copy-clone.md:18 -msgid "" -"```rust,editable\n" -"#[derive(Copy, Clone, Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = p1;\n" -" println!(\"p1: {p1:?}\");\n" -" println!(\"p2: {p2:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/copy-clone.md:30 +#: src/ownership/copy-clone.md:32 msgid "After the assignment, both `p1` and `p2` own their own data." msgstr "" "Después de la asignación, tanto `p1` como `p2` tienen sus propios datos." -#: src/ownership/copy-clone.md:31 +#: src/ownership/copy-clone.md:33 msgid "We can also use `p1.clone()` to explicitly copy the data." msgstr "" "También podemos utilizar `p1.clone()` para copiar los datos de forma " "explícita." -#: src/ownership/copy-clone.md:35 +#: src/ownership/copy-clone.md:37 msgid "Copying and cloning are not the same thing:" msgstr "Copiar y clonar no es lo mismo:" -#: src/ownership/copy-clone.md:37 +#: src/ownership/copy-clone.md:39 msgid "" "Copying refers to bitwise copies of memory regions and does not work on " "arbitrary objects." @@ -6848,14 +6250,14 @@ msgstr "" "Copiar hace referencia a las copias bit a bit de regiones de memoria y no " "funciona en cualquier objeto." -#: src/ownership/copy-clone.md:38 +#: src/ownership/copy-clone.md:40 msgid "" "Copying does not allow for custom logic (unlike copy constructors in C++)." msgstr "" "Copiar no permite lógica personalizada (a diferencia de los constructores de " "copias de C++)." -#: src/ownership/copy-clone.md:39 +#: src/ownership/copy-clone.md:41 msgid "" "Cloning is a more general operation and also allows for custom behavior by " "implementing the `Clone` trait." @@ -6863,15 +6265,15 @@ msgstr "" "Clonar es una operación más general y que permite un comportamiento " "personalizado implementando el trait `Clone`." -#: src/ownership/copy-clone.md:40 +#: src/ownership/copy-clone.md:42 msgid "Copying does not work on types that implement the `Drop` trait." msgstr "Copiar no funciona en los tipos que implementan el trait `Drop`." -#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 +#: src/ownership/copy-clone.md:44 src/ownership/lifetimes-function-calls.md:30 msgid "In the above example, try the following:" msgstr "En el ejemplo anterior, prueba lo siguiente:" -#: src/ownership/copy-clone.md:44 +#: src/ownership/copy-clone.md:46 msgid "" "Add a `String` field to `struct Point`. It will not compile because `String` " "is not a `Copy` type." @@ -6879,7 +6281,7 @@ msgstr "" "Añade un campo `String` a `struct Point`. No se compilará porque `String` no " "es de tipo `Copy`." -#: src/ownership/copy-clone.md:45 +#: src/ownership/copy-clone.md:47 msgid "" "Remove `Copy` from the `derive` attribute. The compiler error is now in the " "`println!` for `p1`." @@ -6887,11 +6289,11 @@ msgstr "" "Elimina `Copy` del atributo `derive`. El error del compilador se encuentra " "ahora en `println!` para `p1`." -#: src/ownership/copy-clone.md:46 +#: src/ownership/copy-clone.md:48 msgid "Show that it works if you clone `p1` instead." msgstr "Demuestra que funciona si clonas `p1`." -#: src/ownership/copy-clone.md:48 +#: src/ownership/copy-clone.md:50 msgid "" "If students ask about `derive`, it is sufficient to say that this is a way " "to generate code in Rust at compile time. In this case the default " @@ -6910,38 +6312,19 @@ msgstr "" "En lugar de transferir el _ownership_ al llamar a una función, puedes " "permitir que una función _tome prestado_ el valor:" -#: src/ownership/borrowing.md:6 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn add(p1: &Point, p2: &Point) -> Point {\n" -" Point(p1.0 + p2.0, p1.1 + p2.1)\n" -"}\n" -"\n" -"fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" -" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/borrowing.md:22 +#: src/ownership/borrowing.md:23 msgid "The `add` function _borrows_ two points and returns a new point." msgstr "La función `add` _toma prestados_ dos puntos y devuelve uno nuevo." -#: src/ownership/borrowing.md:23 +#: src/ownership/borrowing.md:24 msgid "The caller retains ownership of the inputs." msgstr "El llamador conserva el _ownership_ de las entradas." -#: src/ownership/borrowing.md:27 +#: src/ownership/borrowing.md:28 msgid "Notes on stack returns:" msgstr "Notas sobre la devolución de resultados de la _stack_:" -#: src/ownership/borrowing.md:28 +#: src/ownership/borrowing.md:29 msgid "" "Demonstrate that the return from `add` is cheap because the compiler can " "eliminate the copy operation. Change the above code to print stack addresses " @@ -6958,34 +6341,12 @@ msgstr "" "deberían cambiar. Sin embargo, deberían mantenerse igual modificar la " "configuración \"RELEASE\":" -#: src/ownership/borrowing.md:30 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn add(p1: &Point, p2: &Point) -> Point {\n" -" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" -" println!(\"&p.0: {:p}\", &p.0);\n" -" p\n" -"}\n" -"\n" -"pub fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" -" println!(\"&p3.0: {:p}\", &p3.0);\n" -" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/borrowing.md:48 +#: src/ownership/borrowing.md:50 msgid "The Rust compiler can do return value optimization (RVO)." msgstr "" "El compilador de Rust puede hacer la optimización del valor devuelto (RVO)." -#: src/ownership/borrowing.md:49 +#: src/ownership/borrowing.md:51 msgid "" "In C++, copy elision has to be defined in the language specification because " "constructors can have side effects. In Rust, this is not an issue at all. If " @@ -7009,25 +6370,7 @@ msgstr "Puedes tener uno o varios valores `&T` en un momento dado, _o_" msgid "You can have exactly one `&mut T` value." msgstr "puedes tener exactamente un valor `&mut T`." -#: src/ownership/shared-unique-borrows.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let mut a: i32 = 10;\n" -" let b: &i32 = &a;\n" -"\n" -" {\n" -" let c: &mut i32 = &mut a;\n" -" *c = 20;\n" -" }\n" -"\n" -" println!(\"a: {a}\");\n" -" println!(\"b: {b}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:25 +#: src/ownership/shared-unique-borrows.md:26 msgid "" "The above code does not compile because `a` is borrowed as mutable (through " "`c`) and as immutable (through `b`) at the same time." @@ -7035,7 +6378,7 @@ msgstr "" "El código anterior no se compila porque `a` se toma prestada como mutable (a " "través de `c`) y como inmutable (a través de `b`) al mismo tiempo." -#: src/ownership/shared-unique-borrows.md:26 +#: src/ownership/shared-unique-borrows.md:27 msgid "" "Move the `println!` statement for `b` before the scope that introduces `c` " "to make the code compile." @@ -7043,7 +6386,7 @@ msgstr "" "Mueve la instrucción `println!` de `b` antes del ámbito que introduce `c` " "para que el código compile." -#: src/ownership/shared-unique-borrows.md:27 +#: src/ownership/shared-unique-borrows.md:28 msgid "" "After that change, the compiler realizes that `b` is only ever used before " "the new mutable borrow of `a` through `c`. This is a feature of the borrow " @@ -7068,7 +6411,7 @@ msgid "Lifetimes can also be explicit: `&'a Point`, `&'document str`." msgstr "" "Tiempo de vida también puede ser explícito: `&'a Point`, `&'document str`." -#: src/ownership/lifetimes.md:7 src/ownership/lifetimes-function-calls.md:23 +#: src/ownership/lifetimes.md:7 src/ownership/lifetimes-function-calls.md:24 msgid "" "Read `&'a Point` as \"a borrowed `Point` which is valid for at least the " "lifetime `a`\"." @@ -7110,43 +6453,24 @@ msgstr "" "Además de tomar prestados sus argumentos, una función puede devolver un " "valor que se ha tomado prestado:" -#: src/ownership/lifetimes-function-calls.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" -" if p1.0 < p2.0 { p1 } else { p2 }\n" -"}\n" -"\n" -"fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p2: Point = Point(20, 20);\n" -" let p3: &Point = left_most(&p1, &p2);\n" -" println!(\"left-most point: {:?}\", p3);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:21 +#: src/ownership/lifetimes-function-calls.md:22 msgid "`'a` is a generic parameter, it is inferred by the compiler." msgstr "`'a` es un parámetro genérico que infiere el compilador." -#: src/ownership/lifetimes-function-calls.md:22 +#: src/ownership/lifetimes-function-calls.md:23 msgid "Lifetimes start with `'` and `'a` is a typical default name." msgstr "" "Los tiempos de vida comienzan por `'` y `'a` suele ser un nombre " "predeterminado habitual." -#: src/ownership/lifetimes-function-calls.md:25 +#: src/ownership/lifetimes-function-calls.md:26 msgid "" "The _at least_ part is important when parameters are in different scopes." msgstr "" "La parte _al menos_ es importante cuando los parámetros están en ámbitos " "distintos." -#: src/ownership/lifetimes-function-calls.md:31 +#: src/ownership/lifetimes-function-calls.md:32 msgid "" "Move the declaration of `p2` and `p3` into a new scope (`{ ... }`), " "resulting in the following code:" @@ -7154,34 +6478,12 @@ msgstr "" "Mueve la declaración de `p2` y `p3` a un nuevo ámbito (`{ ... }`), lo que " "dará como resultado el siguiente código:" -#: src/ownership/lifetimes-function-calls.md:32 -msgid "" -"```rust,ignore\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" -" if p1.0 < p2.0 { p1 } else { p2 }\n" -"}\n" -"\n" -"fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p3: &Point;\n" -" {\n" -" let p2: Point = Point(20, 20);\n" -" p3 = left_most(&p1, &p2);\n" -" }\n" -" println!(\"left-most point: {:?}\", p3);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:50 +#: src/ownership/lifetimes-function-calls.md:52 msgid "Note how this does not compile since `p3` outlives `p2`." msgstr "" "Ten en cuenta que no se puede compilar, ya que `p3` dura más tiempo que `p2`." -#: src/ownership/lifetimes-function-calls.md:52 +#: src/ownership/lifetimes-function-calls.md:54 msgid "" "Reset the workspace and change the function signature to `fn left_most<'a, " "'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " @@ -7192,11 +6494,11 @@ msgstr "" "compilará porque la relación entre los tiempos de vida de `'a` y `'b` no " "está clara." -#: src/ownership/lifetimes-function-calls.md:53 +#: src/ownership/lifetimes-function-calls.md:55 msgid "Another way to explain it:" msgstr "Otra forma de explicarlo:" -#: src/ownership/lifetimes-function-calls.md:54 +#: src/ownership/lifetimes-function-calls.md:56 msgid "" "Two references to two values are borrowed by a function and the function " "returns another reference." @@ -7204,13 +6506,13 @@ msgstr "" "Una función toma prestadas dos referencias a dos valores y devuelve otra " "referencia." -#: src/ownership/lifetimes-function-calls.md:56 +#: src/ownership/lifetimes-function-calls.md:58 msgid "" "It must have come from one of those two inputs (or from a global variable)." msgstr "" "Esta debe proceder de una de esas dos entradas (o de una variable global)." -#: src/ownership/lifetimes-function-calls.md:57 +#: src/ownership/lifetimes-function-calls.md:59 msgid "" "Which one is it? The compiler needs to know, so at the call site the " "returned reference is not used for longer than a variable from where the " @@ -7227,26 +6529,24 @@ msgstr "" "Si un tipo de datos almacena datos prestados, se debe anotar con tiempo de " "vida:" -#: src/ownership/lifetimes-data-structures.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Highlight<'doc>(&'doc str);\n" -"\n" -"fn erase(text: String) {\n" -" println!(\"Bye {text}!\");\n" -"}\n" -"\n" -"fn main() {\n" -" let text = String::from(\"The quick brown fox jumps over the lazy dog." -"\");\n" -" let fox = Highlight(&text[4..19]);\n" -" let dog = Highlight(&text[35..43]);\n" -" // erase(text);\n" -" println!(\"{fox:?}\");\n" -" println!(\"{dog:?}\");\n" -"}\n" -"```" +#: src/ownership/lifetimes-data-structures.md:10 +msgid "\"Bye {text}!\"" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:14 +msgid "\"The quick brown fox jumps over the lazy dog.\"" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:17 +msgid "// erase(text);\n" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:18 +msgid "\"{fox:?}\"" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:19 +msgid "\"{dog:?}\"" msgstr "" #: src/ownership/lifetimes-data-structures.md:25 @@ -7300,31 +6600,17 @@ msgstr "" msgid "Like C and C++, Rust has support for custom structs:" msgstr "Al igual que C y C++, Rust admite estructuras (struct) personalizadas:" -#: src/structs.md:5 -msgid "" -"```rust,editable\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"\n" -"fn main() {\n" -" let mut peter = Person {\n" -" name: String::from(\"Peter\"),\n" -" age: 27,\n" -" };\n" -" println!(\"{} is {} years old\", peter.name, peter.age);\n" -" \n" -" peter.age = 28;\n" -" println!(\"{} is {} years old\", peter.name, peter.age);\n" -" \n" -" let jackie = Person {\n" -" name: String::from(\"Jackie\"),\n" -" ..peter\n" -" };\n" -" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" -"}\n" -"```" +#: src/structs.md:13 src/structs/field-shorthand.md:20 src/methods.md:21 +#: src/android/interoperability/with-c/bindgen.md:87 +msgid "\"Peter\"" +msgstr "" + +#: src/structs.md:16 src/structs.md:19 src/structs.md:25 +msgid "\"{} is {} years old\"" +msgstr "" + +#: src/structs.md:22 +msgid "\"Jackie\"" msgstr "" #: src/structs.md:33 @@ -7358,8 +6644,13 @@ msgstr "" "diferentes tipos de estructuras. " #: src/structs.md:38 +#, fuzzy +#| msgid "" +#| "Zero-sized structs `e.g., struct Foo;` might be used when implementing a " +#| "trait on some type but don’t have any data that you want to store in the " +#| "value itself. " msgid "" -"Zero-sized structs `e.g., struct Foo;` might be used when implementing a " +"Zero-sized structs (e.g. `struct Foo;`) might be used when implementing a " "trait on some type but don’t have any data that you want to store in the " "value itself. " msgstr "" @@ -7391,16 +6682,8 @@ msgstr "" "Si los nombres de los campos no son importantes, puedes utilizar una " "estructura de tuplas:" -#: src/structs/tuple-structs.md:5 -msgid "" -"```rust,editable\n" -"struct Point(i32, i32);\n" -"\n" -"fn main() {\n" -" let p = Point(17, 23);\n" -" println!(\"({}, {})\", p.0, p.1);\n" -"}\n" -"```" +#: src/structs/tuple-structs.md:10 +msgid "\"({}, {})\"" msgstr "" #: src/structs/tuple-structs.md:14 @@ -7409,26 +6692,14 @@ msgstr "" "Esto se suele utilizar para envoltorios de campo único (denominados " "newtypes):" -#: src/structs/tuple-structs.md:16 -msgid "" -"```rust,editable,compile_fail\n" -"struct PoundsOfForce(f64);\n" -"struct Newtons(f64);\n" -"\n" -"fn compute_thruster_force() -> PoundsOfForce {\n" -" todo!(\"Ask a rocket scientist at NASA\")\n" -"}\n" -"\n" -"fn set_thruster_force(force: Newtons) {\n" -" // ...\n" -"}\n" -"\n" -"fn main() {\n" -" let force = compute_thruster_force();\n" -" set_thruster_force(force);\n" -"}\n" -"\n" -"```" +#: src/structs/tuple-structs.md:21 +msgid "\"Ask a rocket scientist at NASA\"" +msgstr "" + +#: src/structs/tuple-structs.md:25 +#: src/bare-metal/microcontrollers/type-state.md:14 +#: src/async/pitfalls/cancellation.md:96 src/async/pitfalls/cancellation.md:99 +msgid "// ...\n" msgstr "" #: src/structs/tuple-structs.md:37 @@ -7445,9 +6716,14 @@ msgstr "" "El número se mide en algunas unidades: `Newtons` en el ejemplo anterior." #: src/structs/tuple-structs.md:39 +#, fuzzy +#| msgid "" +#| "The value passed some validation when it was created, so you no longer " +#| "have to validate it again at every use: " +#| "'PhoneNumber(String)`or`OddNumber(u32)\\`." msgid "" "The value passed some validation when it was created, so you no longer have " -"to validate it again at every use: 'PhoneNumber(String)`or`OddNumber(u32)\\`." +"to validate it again at every use: `PhoneNumber(String)` or `OddNumber(u32)`." msgstr "" "El valor ha pasado alguna validación cuando se ha creado, por lo que ya no " "tendrás que volver a validarlo cada vez que lo uses: `PhoneNumber(String)` u " @@ -7489,26 +6765,8 @@ msgstr "" "Si ya dispones de variables con los nombres adecuados, puedes crear la " "estructura con un método abreviado:" -#: src/structs/field-shorthand.md:6 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"\n" -"impl Person {\n" -" fn new(name: String, age: u8) -> Person {\n" -" Person { name, age }\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let peter = Person::new(String::from(\"Peter\"), 27);\n" -" println!(\"{peter:?}\");\n" -"}\n" -"```" +#: src/structs/field-shorthand.md:21 +msgid "\"{peter:?}\"" msgstr "" #: src/structs/field-shorthand.md:27 @@ -7519,22 +6777,6 @@ msgstr "" "La función `new` se podría escribir utilizando `Self` como tipo, ya que es " "intercambiable con el nombre de tipo de estructura." -#: src/structs/field-shorthand.md:29 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"impl Person {\n" -" fn new(name: String, age: u8) -> Self {\n" -" Self { name, age }\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/structs/field-shorthand.md:41 msgid "" "Implement the `Default` trait for the struct. Define some fields and use the " @@ -7543,32 +6785,12 @@ msgstr "" "Implementa el trait `Default` en la estructura. Define algunos campos y usa " "los valores predeterminados para el resto de los campos." -#: src/structs/field-shorthand.md:43 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"impl Default for Person {\n" -" fn default() -> Person {\n" -" Person {\n" -" name: \"Bot\".to_string(),\n" -" age: 0,\n" -" }\n" -" }\n" -"}\n" -"fn create_default() {\n" -" let tmp = Person {\n" -" ..Person::default()\n" -" };\n" -" let tmp = Person {\n" -" name: \"Sam\".to_string(),\n" -" ..Person::default()\n" -" };\n" -"}\n" -"```" +#: src/structs/field-shorthand.md:52 +msgid "\"Bot\"" +msgstr "" + +#: src/structs/field-shorthand.md:62 +msgid "\"Sam\"" msgstr "" #: src/structs/field-shorthand.md:68 @@ -7599,29 +6821,8 @@ msgstr "" "Rust te permite asociar funciones a los nuevos tipos. Para ello, usa un " "bloque `impl`:" -#: src/methods.md:6 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"\n" -"impl Person {\n" -" fn say_hello(&self) {\n" -" println!(\"Hello, my name is {}\", self.name);\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let peter = Person {\n" -" name: String::from(\"Peter\"),\n" -" age: 27,\n" -" };\n" -" peter.say_hello();\n" -"}\n" -"```" +#: src/methods.md:15 +msgid "\"Hello, my name is {}\"" msgstr "" #: src/methods.md:31 @@ -7761,50 +6962,40 @@ msgstr "" "referenciar una estructura desde varias ubicaciones y llamar a un método " "mutable (`&mut self`) en ella." -#: src/methods/example.md:3 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Race {\n" -" name: String,\n" -" laps: Vec,\n" -"}\n" -"\n" -"impl Race {\n" -" fn new(name: &str) -> Race { // No receiver, a static method\n" -" Race { name: String::from(name), laps: Vec::new() }\n" -" }\n" -"\n" -" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write " -"access to self\n" -" self.laps.push(lap);\n" -" }\n" -"\n" -" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" -" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" -" for (idx, lap) in self.laps.iter().enumerate() {\n" -" println!(\"Lap {idx}: {lap} sec\");\n" -" }\n" -" }\n" -"\n" -" fn finish(self) { // Exclusive ownership of self\n" -" let total = self.laps.iter().sum::();\n" -" println!(\"Race {} is finished, total lap time: {}\", self.name, " -"total);\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let mut race = Race::new(\"Monaco Grand Prix\");\n" -" race.add_lap(70);\n" -" race.add_lap(68);\n" -" race.print_laps();\n" -" race.add_lap(71);\n" -" race.print_laps();\n" -" race.finish();\n" -" // race.add_lap(42);\n" -"}\n" -"```" +#: src/methods/example.md:11 +msgid "// No receiver, a static method\n" +msgstr "" + +#: src/methods/example.md:15 +msgid "// Exclusive borrowed read-write access to self\n" +msgstr "" + +#: src/methods/example.md:19 +msgid "// Shared and read-only borrowed access to self\n" +msgstr "" + +#: src/methods/example.md:20 +msgid "\"Recorded {} laps for {}:\"" +msgstr "" + +#: src/methods/example.md:22 +msgid "\"Lap {idx}: {lap} sec\"" +msgstr "" + +#: src/methods/example.md:26 +msgid "// Exclusive ownership of self\n" +msgstr "" + +#: src/methods/example.md:28 +msgid "\"Race {} is finished, total lap time: {}\"" +msgstr "" + +#: src/methods/example.md:33 +msgid "\"Monaco Grand Prix\"" +msgstr "" + +#: src/methods/example.md:40 +msgid "// race.add_lap(42);\n" msgstr "" #: src/methods/example.md:47 @@ -7872,19 +7063,12 @@ msgstr "" "Mañana conoceremos mucho mejor _structs_ y el tipo `Vec`. Por ahora, solo " "debes conocer parte de su API:" -#: src/exercises/day-2/book-library.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut vec = vec![10, 20];\n" -" vec.push(30);\n" -" let midpoint = vec.len() / 2;\n" -" println!(\"middle value: {}\", vec[midpoint]);\n" -" for item in &vec {\n" -" println!(\"item: {item}\");\n" -" }\n" -"}\n" -"```" +#: src/exercises/day-2/book-library.md:11 +msgid "\"middle value: {}\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:13 +msgid "\"item: {item}\"" msgstr "" #: src/exercises/day-2/book-library.md:18 @@ -7896,98 +7080,93 @@ msgstr "" "Copia el código que aparece abajo en y " "actualiza los tipos para que compile:" -#: src/exercises/day-2/book-library.md:21 +#: src/exercises/day-2/book-library.md:32 +#: src/exercises/day-2/solutions-morning.md:18 +msgid "// This is a constructor, used below.\n" +msgstr "" + +#: src/exercises/day-2/book-library.md:40 +#: src/exercises/day-2/solutions-morning.md:26 msgid "" -"```rust,should_panic\n" -"struct Library {\n" -" books: Vec,\n" -"}\n" -"\n" -"struct Book {\n" -" title: String,\n" -" year: u16,\n" -"}\n" -"\n" -"impl Book {\n" -" // This is a constructor, used below.\n" -" fn new(title: &str, year: u16) -> Book {\n" -" Book {\n" -" title: String::from(title),\n" -" year,\n" -" }\n" -" }\n" -"}\n" -"\n" -"// Implement the methods below. Update the `self` parameter to\n" -"// indicate the method's required level of ownership over the object:\n" +"// Implement the methods below. Notice how the `self` parameter\n" +"// changes type to indicate the method's required level of ownership\n" +"// over the object:\n" "//\n" "// - `&self` for shared read-only access,\n" "// - `&mut self` for unique and mutable access,\n" "// - `self` for unique access by value.\n" -"impl Library {\n" -" fn new() -> Library {\n" -" todo!(\"Initialize and return a `Library` value\")\n" -" }\n" -"\n" -" //fn len(self) -> usize {\n" -" // todo!(\"Return the length of `self.books`\")\n" -" //}\n" -"\n" -" //fn is_empty(self) -> bool {\n" -" // todo!(\"Return `true` if `self.books` is empty\")\n" -" //}\n" -"\n" -" //fn add_book(self, book: Book) {\n" -" // todo!(\"Add a new book to `self.books`\")\n" -" //}\n" -"\n" -" //fn print_books(self) {\n" -" // todo!(\"Iterate over `self.books` and each book's title and " -"year\")\n" -" //}\n" -"\n" -" //fn oldest_book(self) -> Option<&Book> {\n" -" // todo!(\"Return a reference to the oldest book (if any)\")\n" -" //}\n" -"}\n" -"\n" -"// This shows the desired behavior. Uncomment the code below and\n" -"// implement the missing methods. You will need to update the\n" -"// method signatures, including the \"self\" parameter! You may\n" -"// also need to update the variable bindings within main.\n" -"fn main() {\n" -" let library = Library::new();\n" -"\n" -" //println!(\"The library is empty: library.is_empty() -> {}\", library." -"is_empty());\n" -" //\n" -" //library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " -"1865));\n" -" //\n" -" //println!(\"The library is no longer empty: library.is_empty() -> {}\", " -"library.is_empty());\n" -" //\n" -" //\n" -" //library.print_books();\n" -" //\n" -" //match library.oldest_book() {\n" -" // Some(book) => println!(\"The oldest book is {}\", book.title),\n" -" // None => println!(\"The library is empty!\"),\n" -" //}\n" -" //\n" -" //println!(\"The library has {} books\", library.len());\n" -" //library.print_books();\n" -"}\n" -"```" msgstr "" -#: src/exercises/day-2/book-library.md:102 -msgid "[Solution](solutions-afternoon.md#designing-a-library)" -msgstr "[Soluciones](solutions-afternoon.md#designing-a-library)" +#: src/exercises/day-2/book-library.md:50 +msgid "\"Initialize and return a `Library` value\"" +msgstr "" -#: src/exercises/day-2/health-statistics.md:3 -msgid "" +#: src/exercises/day-2/book-library.md:54 +msgid "\"Return the length of `self.books`\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:58 +msgid "\"Return `true` if `self.books` is empty\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:62 +msgid "\"Add a new book to `self.books`\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:66 +msgid "\"Iterate over `self.books` and print each book's title and year\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:70 +msgid "\"Return a reference to the oldest book (if any)\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:78 +#: src/exercises/day-2/solutions-morning.md:78 +msgid "\"The library is empty: library.is_empty() -> {}\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:82 +#: src/exercises/day-2/solutions-morning.md:82 +#: src/exercises/day-2/solutions-morning.md:107 +#: src/exercises/day-2/solutions-morning.md:118 +#: src/exercises/day-2/solutions-morning.md:125 +#: src/exercises/day-2/solutions-morning.md:137 +#: src/exercises/day-2/solutions-morning.md:140 +msgid "\"Lord of the Rings\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:83 +#: src/exercises/day-2/solutions-morning.md:83 +#: src/exercises/day-2/solutions-morning.md:108 +#: src/exercises/day-2/solutions-morning.md:126 +#: src/exercises/day-2/solutions-morning.md:143 +#: src/exercises/day-2/solutions-morning.md:146 +msgid "\"Alice's Adventures in Wonderland\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:86 +#: src/exercises/day-2/solutions-morning.md:86 +msgid "\"The library is no longer empty: library.is_empty() -> {}\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:93 +#: src/exercises/day-2/solutions-morning.md:93 +msgid "\"The oldest book is {}\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:94 +#: src/exercises/day-2/solutions-morning.md:94 +msgid "\"The library is empty!\"" +msgstr "" + +#: src/exercises/day-2/book-library.md:97 +#: src/exercises/day-2/solutions-morning.md:97 +msgid "\"The library has {} books\"" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:3 +msgid "" "You're working on implementing a health-monitoring system. As part of that, " "you need to keep track of users' health statistics." msgstr "" @@ -8013,113 +7192,70 @@ msgstr "" "Copia el fragmento de código que aparece más abajo en la página y rellena los métodos que faltan:" -#: src/exercises/day-2/health-statistics.md:13 +#: src/exercises/day-2/health-statistics.md:39 +msgid "\"Create a new User instance\"" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:43 +msgid "\"Return the user's name\"" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:47 +msgid "\"Return the user's age\"" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:51 +#, fuzzy +#| msgid "Run the server with:" +msgid "\"Return the user's height\"" +msgstr "Ejecuta el servidor con:" + +#: src/exercises/day-2/health-statistics.md:55 +msgid "\"Return the number of time the user has visited the doctor\"" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:59 +msgid "\"Set the user's age\"" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:63 +msgid "\"Set the user's height\"" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:67 msgid "" -"```rust,should_panic\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]\n" -"\n" -"pub struct User {\n" -" name: String,\n" -" age: u32,\n" -" height: f32,\n" -" visit_count: usize,\n" -" last_blood_pressure: Option<(u32, u32)>,\n" -"}\n" -"\n" -"pub struct Measurements {\n" -" height: f32,\n" -" blood_pressure: (u32, u32),\n" -"}\n" -"\n" -"pub struct HealthReport<'a> {\n" -" patient_name: &'a str,\n" -" visit_count: u32,\n" -" height_change: f32,\n" -" blood_pressure_change: Option<(i32, i32)>,\n" -"}\n" -"\n" -"impl User {\n" -" pub fn new(name: String, age: u32, height: f32) -> Self {\n" -" unimplemented!()\n" -" }\n" -"\n" -" pub fn name(&self) -> &str {\n" -" unimplemented!()\n" -" }\n" -"\n" -" pub fn age(&self) -> u32 {\n" -" unimplemented!()\n" -" }\n" -"\n" -" pub fn height(&self) -> f32 {\n" -" unimplemented!()\n" -" }\n" -"\n" -" pub fn doctor_visits(&self) -> u32 {\n" -" unimplemented!()\n" -" }\n" -"\n" -" pub fn set_age(&mut self, new_age: u32) {\n" -" unimplemented!()\n" -" }\n" -"\n" -" pub fn set_height(&mut self, new_height: f32) {\n" -" unimplemented!()\n" -" }\n" -"\n" -" pub fn visit_doctor(&mut self, measurements: Measurements) -> " -"HealthReport {\n" -" unimplemented!()\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" println!(\"I'm {} and my age is {}\", bob.name(), bob.age());\n" -"}\n" -"\n" -"#[test]\n" -"fn test_height() {\n" -" let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" assert_eq!(bob.height(), 155.2);\n" -"}\n" -"\n" -"#[test]\n" -"fn test_set_age() {\n" -" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" assert_eq!(bob.age(), 32);\n" -" bob.set_age(33);\n" -" assert_eq!(bob.age(), 33);\n" -"}\n" -"\n" -"#[test]\n" -"fn test_visit() {\n" -" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" assert_eq!(bob.doctor_visits(), 0);\n" -" let report = bob.visit_doctor(Measurements {\n" -" height: 156.1,\n" -" blood_pressure: (120, 80),\n" -" });\n" -" assert_eq!(report.patient_name, \"Bob\");\n" -" assert_eq!(report.visit_count, 1);\n" -" assert_eq!(report.blood_pressure_change, None);\n" -"\n" -" let report = bob.visit_doctor(Measurements {\n" -" height: 156.1,\n" -" blood_pressure: (115, 76),\n" -" });\n" -"\n" -" assert_eq!(report.visit_count, 2);\n" -" assert_eq!(report.blood_pressure_change, Some((-5, -4)));\n" -"}\n" -"```" +"\"Update a user's statistics based on measurements from a visit to the " +"doctor\"" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:72 +#: src/exercises/day-2/health-statistics.md:78 +#: src/exercises/day-2/health-statistics.md:84 +#: src/exercises/day-2/health-statistics.md:92 +#: src/exercises/day-2/health-statistics.md:98 +#: src/android/build-rules/library.md:44 src/android/aidl/client.md:23 +#: src/exercises/day-2/solutions-morning.md:233 +#: src/exercises/day-2/solutions-morning.md:239 +#: src/exercises/day-2/solutions-morning.md:245 +#: src/exercises/day-2/solutions-morning.md:253 +#: src/exercises/day-2/solutions-morning.md:259 +msgid "\"Bob\"" +msgstr "" + +#: src/exercises/day-2/health-statistics.md:73 +#: src/exercises/day-2/solutions-morning.md:234 +msgid "\"I'm {} and my age is {}\"" msgstr "" #: src/std.md:3 +#, fuzzy +#| msgid "" +#| "Rust comes with a standard library which helps establish a set of common " +#| "types used by Rust library and programs. This way, two libraries can work " +#| "together smoothly because they both use the same `String` type." msgid "" "Rust comes with a standard library which helps establish a set of common " -"types used by Rust library and programs. This way, two libraries can work " +"types used by Rust libraries and programs. This way, two libraries can work " "together smoothly because they both use the same `String` type." msgstr "" "Rust viene con una biblioteca estándar que ayuda a establecer un conjunto de " @@ -8210,18 +7346,12 @@ msgstr "`Option` y `Result`" msgid "The types represent optional data:" msgstr "Los tipos representan datos opcionales:" -#: src/std/option-result.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let numbers = vec![10, 20, 30];\n" -" let first: Option<&i8> = numbers.first();\n" -" println!(\"first: {first:?}\");\n" -"\n" -" let idx: Result = numbers.binary_search(&10);\n" -" println!(\"idx: {idx:?}\");\n" -"}\n" -"```" +#: src/std/option-result.md:9 +msgid "\"first: {first:?}\"" +msgstr "" + +#: src/std/option-result.md:12 +msgid "\"arr: {arr:?}\"" msgstr "" #: src/std/option-result.md:18 @@ -8241,21 +7371,19 @@ msgstr "" "como veremos el día 3." #: src/std/option-result.md:21 -msgid "`binary_search` returns `Result`." -msgstr "`binary_search` devuelve `Result`." +msgid "" +"`try_into` attempts to convert the vector into a fixed-sized array. This can " +"fail:" +msgstr "" #: src/std/option-result.md:22 -msgid "If found, `Result::Ok` holds the index where the element is found." +msgid "" +"If the vector has the right size, `Result::Ok` is returned with the array." msgstr "" -"Si se encuentra, `Result::Ok` contiene el índice donde se halla el elemento." #: src/std/option-result.md:23 -msgid "" -"Otherwise, `Result::Err` contains the index where such an element should be " -"inserted." +msgid "Otherwise, `Result::Err` is returned with the original vector." msgstr "" -"De lo contrario, `Result::Err` contendrá el índice donde se debe insertar " -"dicho elemento." #: src/std/string.md:3 msgid "" @@ -8265,24 +7393,24 @@ msgstr "" "[`String`](https://doc.rust-lang.org/std/string/struct.String.html) es el " "búfer de cadena UTF-8 estándar, ampliable y asignado a un _heap_:" -#: src/std/string.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut s1 = String::new();\n" -" s1.push_str(\"Hello\");\n" -" println!(\"s1: len = {}, capacity = {}\", s1.len(), s1.capacity());\n" -"\n" -" let mut s2 = String::with_capacity(s1.len() + 1);\n" -" s2.push_str(&s1);\n" -" s2.push('!');\n" -" println!(\"s2: len = {}, capacity = {}\", s2.len(), s2.capacity());\n" -"\n" -" let s3 = String::from(\"🇨🇭\");\n" -" println!(\"s3: len = {}, number of chars = {}\", s3.len(),\n" -" s3.chars().count());\n" -"}\n" -"```" +#: src/std/string.md:9 +msgid "\"s1: len = {}, capacity = {}\"" +msgstr "" + +#: src/std/string.md:13 +msgid "'!'" +msgstr "" + +#: src/std/string.md:14 +msgid "\"s2: len = {}, capacity = {}\"" +msgstr "" + +#: src/std/string.md:16 +msgid "\"🇨🇭\"" +msgstr "" + +#: src/std/string.md:17 +msgid "\"s3: len = {}, number of chars = {}\"" msgstr "" #: src/std/string.md:22 @@ -8347,7 +7475,9 @@ msgstr "" "transparente a los métodos de `str`." #: src/std/string.md:36 -msgid "Write and compare `let s3 = s1.deref();` and `let s3 = &*s1`;." +#, fuzzy +#| msgid "Write and compare `let s3 = s1.deref();` and `let s3 = &*s1`;." +msgid "Write and compare `let s3 = s1.deref();` and `let s3 = &*s1;`." msgstr "Escribe y compara `let s3 = s1.deref();` y `let s3 = &*s1`;." #: src/std/string.md:37 @@ -8392,31 +7522,28 @@ msgstr "" "[`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html) es el búfer " "estándar redimensionable asignado al _heap_:" -#: src/std/vec.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut v1 = Vec::new();\n" -" v1.push(42);\n" -" println!(\"v1: len = {}, capacity = {}\", v1.len(), v1.capacity());\n" -"\n" -" let mut v2 = Vec::with_capacity(v1.len() + 1);\n" -" v2.extend(v1.iter());\n" -" v2.push(9999);\n" -" println!(\"v2: len = {}, capacity = {}\", v2.len(), v2.capacity());\n" -"\n" -" // Canonical macro to initialize a vector with elements.\n" -" let mut v3 = vec![0, 0, 1, 2, 3, 4];\n" -"\n" -" // Retain only the even elements.\n" -" v3.retain(|x| x % 2 == 0);\n" -" println!(\"{v3:?}\");\n" -"\n" -" // Remove consecutive duplicates.\n" -" v3.dedup();\n" -" println!(\"{v3:?}\");\n" -"}\n" -"```" +#: src/std/vec.md:9 +msgid "\"v1: len = {}, capacity = {}\"" +msgstr "" + +#: src/std/vec.md:14 +msgid "\"v2: len = {}, capacity = {}\"" +msgstr "" + +#: src/std/vec.md:16 +msgid "// Canonical macro to initialize a vector with elements.\n" +msgstr "" + +#: src/std/vec.md:19 +msgid "// Retain only the even elements.\n" +msgstr "" + +#: src/std/vec.md:21 src/std/vec.md:25 +msgid "\"{v3:?}\"" +msgstr "" + +#: src/std/vec.md:23 +msgid "// Remove consecutive duplicates.\n" msgstr "" #: src/std/vec.md:29 @@ -8484,42 +7611,44 @@ msgstr "`HashMap`" msgid "Standard hash map with protection against HashDoS attacks:" msgstr "Mapa hash estándar con protección frente a ataques HashDoS:" -#: src/std/hashmap.md:5 -msgid "" -"```rust,editable\n" -"use std::collections::HashMap;\n" -"\n" -"fn main() {\n" -" let mut page_counts = HashMap::new();\n" -" page_counts.insert(\"Adventures of Huckleberry Finn\".to_string(), " -"207);\n" -" page_counts.insert(\"Grimms' Fairy Tales\".to_string(), 751);\n" -" page_counts.insert(\"Pride and Prejudice\".to_string(), 303);\n" -"\n" -" if !page_counts.contains_key(\"Les Misérables\") {\n" -" println!(\"We know about {} books, but not Les Misérables.\",\n" -" page_counts.len());\n" -" }\n" -"\n" -" for book in [\"Pride and Prejudice\", \"Alice's Adventure in " -"Wonderland\"] {\n" -" match page_counts.get(book) {\n" -" Some(count) => println!(\"{book}: {count} pages\"),\n" -" None => println!(\"{book} is unknown.\")\n" -" }\n" -" }\n" -"\n" -" // Use the .entry() method to insert a value if nothing is found.\n" -" for book in [\"Pride and Prejudice\", \"Alice's Adventure in " -"Wonderland\"] {\n" -" let page_count: &mut i32 = page_counts.entry(book.to_string())." -"or_insert(0);\n" -" *page_count += 1;\n" -" }\n" -"\n" -" println!(\"{page_counts:#?}\");\n" -"}\n" -"```" +#: src/std/hashmap.md:10 +msgid "\"Adventures of Huckleberry Finn\"" +msgstr "" + +#: src/std/hashmap.md:11 +msgid "\"Grimms' Fairy Tales\"" +msgstr "" + +#: src/std/hashmap.md:12 src/std/hashmap.md:19 src/std/hashmap.md:27 +msgid "\"Pride and Prejudice\"" +msgstr "" + +#: src/std/hashmap.md:14 +msgid "\"Les Misérables\"" +msgstr "" + +#: src/std/hashmap.md:15 +msgid "\"We know about {} books, but not Les Misérables.\"" +msgstr "" + +#: src/std/hashmap.md:19 src/std/hashmap.md:27 +msgid "\"Alice's Adventure in Wonderland\"" +msgstr "" + +#: src/std/hashmap.md:21 +msgid "\"{book}: {count} pages\"" +msgstr "" + +#: src/std/hashmap.md:22 +msgid "\"{book} is unknown.\"" +msgstr "" + +#: src/std/hashmap.md:26 +msgid "// Use the .entry() method to insert a value if nothing is found.\n" +msgstr "" + +#: src/std/hashmap.md:32 +msgid "\"{page_counts:#?}\"" msgstr "" #: src/std/hashmap.md:38 @@ -8538,16 +7667,12 @@ msgstr "" "La segunda línea insertará el valor alternativo en el hashmap si el libro no " "se encuentra." -#: src/std/hashmap.md:41 -msgid "" -"```rust,ignore\n" -" let pc1 = page_counts\n" -" .get(\"Harry Potter and the Sorcerer's Stone \")\n" -" .unwrap_or(&336);\n" -" let pc2 = page_counts\n" -" .entry(\"The Hunger Games\".to_string())\n" -" .or_insert(374);\n" -"```" +#: src/std/hashmap.md:43 +msgid "\"Harry Potter and the Sorcerer's Stone \"" +msgstr "" + +#: src/std/hashmap.md:46 src/std/hashmap.md:55 +msgid "\"The Hunger Games\"" msgstr "" #: src/std/hashmap.md:49 @@ -8569,14 +7694,8 @@ msgstr "" "nos permite inicializar fácilmente un mapa hash a partir de un _array_ " "literal:" -#: src/std/hashmap.md:52 -msgid "" -"```rust,ignore\n" -" let page_counts = HashMap::from([\n" -" (\"Harry Potter and the Sorcerer's Stone\".to_string(), 336),\n" -" (\"The Hunger Games\".to_string(), 374),\n" -" ]);\n" -"```" +#: src/std/hashmap.md:54 +msgid "\"Harry Potter and the Sorcerer's Stone\"" msgstr "" #: src/std/hashmap.md:59 @@ -8629,43 +7748,9 @@ msgstr "" "[`Box`](https://doc.rust-lang.org/std/boxed/struct.Box.html) es un puntero " "propio de datos en el _heap_:" -#: src/std/box.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let five = Box::new(5);\n" -" println!(\"five: {}\", *five);\n" -"}\n" -"```" -msgstr "" - -#: src/std/box.md:13 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - -. .- - - - - - -.\n" -": : : :\n" -": five : : :\n" -": +-----+ : : +-----+ :\n" -": | o---|---+-----+-->| 5 | :\n" -": +-----+ : : +-----+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - -' `- - - - - - -'\n" -"```" +#: src/std/box.md:8 +msgid "\"five: {}\"" msgstr "" -"```bob\n" -" _Stack_ _Heap_\n" -".- - - - - - -. .- - - - - - -.\n" -": : : :\n" -": five : : :\n" -": +-----+ : : +-----+ :\n" -": | o---|---+-----+-->| 5 | :\n" -": +-----+ : : +-----+ :\n" -": : : :\n" -": : : :\n" -"`- - - - - - -' `- - - - - - -'\n" -"```" #: src/std/box.md:26 msgid "" @@ -8726,21 +7811,8 @@ msgstr "" "Los tipos de datos recursivos o los tipos de datos con tamaños dinámicos " "deben utilizar un `Box`:" -#: src/std/box-recursive.md:5 src/std/box-niche.md:3 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"enum List {\n" -" Cons(T, Box>),\n" -" Nil,\n" -"}\n" -"\n" -"fn main() {\n" -" let list: List = List::Cons(1, Box::new(List::Cons(2, Box::" -"new(List::Nil))));\n" -" println!(\"{list:?}\");\n" -"}\n" -"```" +#: src/std/box-recursive.md:14 src/std/box-niche.md:12 +msgid "\"{list:?}\"" msgstr "" #: src/std/box-recursive.md:18 @@ -8874,19 +7946,12 @@ msgstr "" "compartido de referencia contada. Utilízalo cuando necesites hacer " "referencia a los mismos datos desde varios lugares:" -#: src/std/rc.md:6 -msgid "" -"```rust,editable\n" -"use std::rc::Rc;\n" -"\n" -"fn main() {\n" -" let mut a = Rc::new(10);\n" -" let mut b = Rc::clone(&a);\n" -"\n" -" println!(\"a: {a}\");\n" -" println!(\"b: {b}\");\n" -"}\n" -"```" +#: src/std/rc.md:13 +msgid "\"a: {a}\"" +msgstr "" + +#: src/std/rc.md:14 +msgid "\"b: {b}\"" msgstr "" #: src/std/rc.md:18 @@ -8978,41 +8043,12 @@ msgstr "" "exclusivas en tiempo de ejecución y entra en pánico si se utilizan de forma " "incorrecta." -#: src/std/cell.md:12 -msgid "" -"```rust,editable\n" -"use std::cell::RefCell;\n" -"use std::rc::Rc;\n" -"\n" -"#[derive(Debug, Default)]\n" -"struct Node {\n" -" value: i64,\n" -" children: Vec>>,\n" -"}\n" -"\n" -"impl Node {\n" -" fn new(value: i64) -> Rc> {\n" -" Rc::new(RefCell::new(Node { value, ..Node::default() }))\n" -" }\n" -"\n" -" fn sum(&self) -> i64 {\n" -" self.value + self.children.iter().map(|c| c.borrow().sum()).sum::" -"()\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let root = Node::new(1);\n" -" root.borrow_mut().children.push(Node::new(5));\n" -" let subtree = Node::new(10);\n" -" subtree.borrow_mut().children.push(Node::new(11));\n" -" subtree.borrow_mut().children.push(Node::new(12));\n" -" root.borrow_mut().children.push(subtree);\n" -"\n" -" println!(\"graph: {root:#?}\");\n" -" println!(\"graph sum: {}\", root.borrow().sum());\n" -"}\n" -"```" +#: src/std/cell.md:40 +msgid "\"graph: {root:#?}\"" +msgstr "" + +#: src/std/cell.md:41 +msgid "\"graph sum: {}\"" msgstr "" #: src/std/cell.md:47 @@ -9067,26 +8103,12 @@ msgstr "" "Del mismo modo, `mod` nos permite asignar espacios de nombres a funciones y " "tipos:" -#: src/modules.md:7 -msgid "" -"```rust,editable\n" -"mod foo {\n" -" pub fn do_something() {\n" -" println!(\"In the foo module\");\n" -" }\n" -"}\n" -"\n" -"mod bar {\n" -" pub fn do_something() {\n" -" println!(\"In the bar module\");\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" foo::do_something();\n" -" bar::do_something();\n" -"}\n" -"```" +#: src/modules.md:10 +msgid "\"In the foo module\"" +msgstr "" + +#: src/modules.md:16 +msgid "\"In the bar module\"" msgstr "" #: src/modules.md:28 @@ -9133,34 +8155,20 @@ msgstr "" "Es decir, si un elemento está visible en el módulo `foo`, se verá en todos " "los elementos descendientes de `foo`." -#: src/modules/visibility.md:10 -msgid "" -"```rust,editable\n" -"mod outer {\n" -" fn private() {\n" -" println!(\"outer::private\");\n" -" }\n" -"\n" -" pub fn public() {\n" -" println!(\"outer::public\");\n" -" }\n" -"\n" -" mod inner {\n" -" fn private() {\n" -" println!(\"outer::inner::private\");\n" -" }\n" -"\n" -" pub fn public() {\n" -" println!(\"outer::inner::public\");\n" -" super::private();\n" -" }\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" outer::public();\n" -"}\n" -"```" +#: src/modules/visibility.md:13 +msgid "\"outer::private\"" +msgstr "" + +#: src/modules/visibility.md:17 +msgid "\"outer::public\"" +msgstr "" + +#: src/modules/visibility.md:22 +msgid "\"outer::inner::private\"" +msgstr "" + +#: src/modules/visibility.md:26 +msgid "\"outer::inner::public\"" msgstr "" #: src/modules/visibility.md:39 @@ -9236,27 +8244,12 @@ msgstr "" "Un módulo puede incluir símbolos de otro módulo en el ámbito con `use`. " "Normalmente, se ve algo como esto en la parte superior de cada módulo:" -#: src/modules/paths.md:16 -msgid "" -"```rust,editable\n" -"use std::collections::HashSet;\n" -"use std::mem::transmute;\n" -"```" -msgstr "" - #: src/modules/filesystem.md:3 msgid "" "Omitting the module content will tell Rust to look for it in another file:" msgstr "" "Omitir el contenido del módulo hará que Rust lo busque en otro archivo:" -#: src/modules/filesystem.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"mod garden;\n" -"```" -msgstr "" - #: src/modules/filesystem.md:9 msgid "" "This tells rust that the `garden` module content is found at `src/garden." @@ -9289,23 +8282,23 @@ msgstr "" "\"comentarios internos del documento\". En ellos se indica el elemento que " "los contiene, en este caso, un módulo." -#: src/modules/filesystem.md:20 +#: src/modules/filesystem.md:21 msgid "" -"```rust,editable,compile_fail\n" "//! This module implements the garden, including a highly performant " "germination\n" "//! implementation.\n" -"\n" -"// Re-export types from this module.\n" -"pub use seeds::SeedPacket;\n" -"pub use garden::Garden;\n" -"\n" -"/// Sow the given seed packets.\n" -"pub fn sow(seeds: Vec) { todo!() }\n" -"\n" -"/// Harvest the produce in the garden that is ready.\n" -"pub fn harvest(garden: &mut Garden) { todo!() }\n" -"```" +msgstr "" + +#: src/modules/filesystem.md:23 +msgid "// Re-export types from this module.\n" +msgstr "" + +#: src/modules/filesystem.md:27 +msgid "/// Sow the given seed packets.\n" +msgstr "" + +#: src/modules/filesystem.md:30 +msgid "/// Harvest the produce in the garden that is ready.\n" msgstr "" #: src/modules/filesystem.md:37 @@ -9332,17 +8325,6 @@ msgstr "" "Un anidamiento más profundo puede usar carpetas, incluso si el módulo " "principal es un archivo:" -#: src/modules/filesystem.md:44 -msgid "" -"```ignore\n" -"src/\n" -"├── main.rs\n" -"├── top_module.rs\n" -"└── top_module/\n" -" └── sub_module.rs\n" -"```" -msgstr "" - #: src/modules/filesystem.md:52 msgid "" "The place rust will look for modules can be changed with a compiler " @@ -9351,12 +8333,8 @@ msgstr "" "El lugar donde Rust buscará los módulos se puede cambiar con una directiva " "del compilador:" -#: src/modules/filesystem.md:54 -msgid "" -"```rust,ignore\n" -"#[path = \"some/path.rs\"]\n" -"mod some_module;\n" -"```" +#: src/modules/filesystem.md:55 +msgid "\"some/path.rs\"" msgstr "" #: src/modules/filesystem.md:59 @@ -9402,50 +8380,33 @@ msgstr "" "de un tipo. El trait `Iterator` indica que se puede llamar a `next` hasta " "que se obtenga `None`:" -#: src/exercises/day-2/iterators-and-ownership.md:13 -msgid "" -"```rust\n" -"pub trait Iterator {\n" -" type Item;\n" -" fn next(&mut self) -> Option;\n" -"}\n" -"```" -msgstr "" - #: src/exercises/day-2/iterators-and-ownership.md:20 msgid "You use this trait like this:" msgstr "Utiliza este trait de la siguiente forma:" -#: src/exercises/day-2/iterators-and-ownership.md:22 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();\n" -"\n" -" println!(\"v[0]: {:?}\", iter.next());\n" -" println!(\"v[1]: {:?}\", iter.next());\n" -" println!(\"v[2]: {:?}\", iter.next());\n" -" println!(\"No more items: {:?}\", iter.next());\n" -"}\n" -"```" +#: src/exercises/day-2/iterators-and-ownership.md:27 +msgid "\"v[0]: {:?}\"" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:28 +msgid "\"v[1]: {:?}\"" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:29 +msgid "\"v[2]: {:?}\"" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:30 +msgid "\"No more items: {:?}\"" msgstr "" #: src/exercises/day-2/iterators-and-ownership.md:34 msgid "What is the type returned by the iterator? Test your answer here:" msgstr "¿Qué tipo devuelve el iterador? Prueba tu respuesta aquí:" -#: src/exercises/day-2/iterators-and-ownership.md:36 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();\n" -"\n" -" let v0: Option<..> = iter.next();\n" -" println!(\"v0: {v0:?}\");\n" -"}\n" -"```" +#: src/exercises/day-2/iterators-and-ownership.md:42 +#: src/exercises/day-2/iterators-and-ownership.md:79 +msgid "\"v0: {v0:?}\"" msgstr "" #: src/exercises/day-2/iterators-and-ownership.md:46 @@ -9465,18 +8426,6 @@ msgstr "" "El trait `Iterator` te indica cómo _iterar_ una vez que has creado un " "iterador. El trait relacionado `IntoIterator` indica cómo crear el iterador:" -#: src/exercises/day-2/iterators-and-ownership.md:53 -msgid "" -"```rust\n" -"pub trait IntoIterator {\n" -" type Item;\n" -" type IntoIter: Iterator;\n" -"\n" -" fn into_iter(self) -> Self::IntoIter;\n" -"}\n" -"```" -msgstr "" - #: src/exercises/day-2/iterators-and-ownership.md:62 msgid "" "The syntax here means that every implementation of `IntoIterator` must " @@ -9505,18 +8454,10 @@ msgstr "" msgid "Like before, what is the type returned by the iterator?" msgstr "Al igual que antes, ¿qué tipo devuelve el iterador?" -#: src/exercises/day-2/iterators-and-ownership.md:73 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::" -"from(\"bar\")];\n" -" let mut iter = v.into_iter();\n" -"\n" -" let v0: Option<..> = iter.next();\n" -" println!(\"v0: {v0:?}\");\n" -"}\n" -"```" +#: src/exercises/day-2/iterators-and-ownership.md:75 +#: src/exercises/day-2/iterators-and-ownership.md:91 +#: src/testing/test-modules.md:21 +msgid "\"bar\"" msgstr "" #: src/exercises/day-2/iterators-and-ownership.md:83 @@ -9533,22 +8474,9 @@ msgstr "" "Llaman a `into_iter()` sobre una expresión e iteran sobre el iterador " "resultante:" -#: src/exercises/day-2/iterators-and-ownership.md:89 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::" -"from(\"bar\")];\n" -"\n" -" for word in &v {\n" -" println!(\"word: {word}\");\n" -" }\n" -"\n" -" for word in v {\n" -" println!(\"word: {word}\");\n" -" }\n" -"}\n" -"```" +#: src/exercises/day-2/iterators-and-ownership.md:94 +#: src/exercises/day-2/iterators-and-ownership.md:98 +msgid "\"word: {word}\"" msgstr "" #: src/exercises/day-2/iterators-and-ownership.md:103 @@ -9591,53 +8519,79 @@ msgstr "" "org/> para hacer la prueba. Prueba a no asignar un `Vec` a los resultados " "intermedios:" -#: src/exercises/day-2/strings-iterators.md:12 -msgid "" -"```rust\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]\n" -"\n" -"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" -" unimplemented!()\n" -"}\n" -"\n" -"#[test]\n" -"fn test_matches_without_wildcard() {\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/" -"abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/" -"books\"));\n" -"\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/" -"publishers\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_matches_with_wildcard() {\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books\"\n" -" ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/bar/books\"\n" -" ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books/book1\"\n" -" ));\n" -"\n" -" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/" -"publishers\"));\n" -" assert!(!prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/booksByAuthor\"\n" -" ));\n" -"}\n" -"```" +#: src/exercises/day-2/strings-iterators.md:22 +#: src/exercises/day-2/strings-iterators.md:23 +#: src/exercises/day-2/strings-iterators.md:24 +#: src/exercises/day-2/strings-iterators.md:26 +#: src/exercises/day-2/strings-iterators.md:27 +#: src/exercises/day-2/strings-iterators.md:28 +#: src/exercises/day-2/strings-iterators.md:46 +#: src/exercises/day-2/solutions-afternoon.md:32 +#: src/exercises/day-2/solutions-afternoon.md:33 +#: src/exercises/day-2/solutions-afternoon.md:34 +#: src/exercises/day-2/solutions-afternoon.md:36 +#: src/exercises/day-2/solutions-afternoon.md:37 +#: src/exercises/day-2/solutions-afternoon.md:38 +#: src/exercises/day-2/solutions-afternoon.md:56 +msgid "\"/v1/publishers\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:23 +#: src/exercises/day-2/solutions-afternoon.md:33 +msgid "\"/v1/publishers/abc-123\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:24 +#: src/exercises/day-2/solutions-afternoon.md:34 +msgid "\"/v1/publishers/abc/books\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:26 +#: src/exercises/day-2/solutions-afternoon.md:36 +msgid "\"/v1\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:27 +#: src/exercises/day-2/solutions-afternoon.md:37 +msgid "\"/v1/publishersBooks\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:28 +#: src/exercises/day-2/solutions-afternoon.md:38 +msgid "\"/v1/parent/publishers\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:34 +#: src/exercises/day-2/strings-iterators.md:38 +#: src/exercises/day-2/strings-iterators.md:42 +#: src/exercises/day-2/strings-iterators.md:46 +#: src/exercises/day-2/strings-iterators.md:48 +#: src/exercises/day-2/solutions-afternoon.md:44 +#: src/exercises/day-2/solutions-afternoon.md:48 +#: src/exercises/day-2/solutions-afternoon.md:52 +#: src/exercises/day-2/solutions-afternoon.md:56 +#: src/exercises/day-2/solutions-afternoon.md:58 +msgid "\"/v1/publishers/*/books\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:35 +#: src/exercises/day-2/solutions-afternoon.md:45 +msgid "\"/v1/publishers/foo/books\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:39 +#: src/exercises/day-2/solutions-afternoon.md:49 +msgid "\"/v1/publishers/bar/books\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:43 +#: src/exercises/day-2/solutions-afternoon.md:53 +msgid "\"/v1/publishers/foo/books/book1\"" +msgstr "" + +#: src/exercises/day-2/strings-iterators.md:49 +#: src/exercises/day-2/solutions-afternoon.md:59 +msgid "\"/v1/publishers/foo/booksByAuthor\"" msgstr "" #: src/welcome-day-3.md:1 @@ -9696,21 +8650,8 @@ msgstr "" msgid "You can use generics to abstract over the concrete field type:" msgstr "Puedes usar genéricos para abstraer el tipo de campo concreto:" -#: src/generics/data-types.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point {\n" -" x: T,\n" -" y: T,\n" -"}\n" -"\n" -"fn main() {\n" -" let integer = Point { x: 5, y: 10 };\n" -" let float = Point { x: 1.0, y: 4.0 };\n" -" println!(\"{integer:?} and {float:?}\");\n" -"}\n" -"```" +#: src/generics/data-types.md:15 +msgid "\"{integer:?} and {float:?}\"" msgstr "" #: src/generics/data-types.md:21 @@ -9728,25 +8669,16 @@ msgstr "" msgid "You can declare a generic type on your `impl` block:" msgstr "Puedes declarar un tipo genérico en tu bloque `impl`:" -#: src/generics/methods.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(T, T);\n" -"\n" -"impl Point {\n" -" fn x(&self) -> &T {\n" -" &self.0 // + 10\n" -" }\n" -"\n" -" // fn set_x(&mut self, x: T)\n" -"}\n" -"\n" -"fn main() {\n" -" let p = Point(5, 10);\n" -" println!(\"p.x = {}\", p.x());\n" -"}\n" -"```" +#: src/generics/methods.md:11 +msgid "// + 10\n" +msgstr "" + +#: src/generics/methods.md:14 +msgid "// fn set_x(&mut self, x: T)\n" +msgstr "" + +#: src/generics/methods.md:19 +msgid "\"p.x = {}\"" msgstr "" #: src/generics/methods.md:25 @@ -9787,40 +8719,10 @@ msgstr "" "El código genérico se convierte en código no genérico en función de los " "sitios de llamada:" -#: src/generics/monomorphization.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let integer = Some(5);\n" -" let float = Some(5.0);\n" -"}\n" -"```" -msgstr "" - #: src/generics/monomorphization.md:12 msgid "behaves as if you wrote" msgstr "se comporta como si se hubiera escrito" -#: src/generics/monomorphization.md:14 -msgid "" -"```rust,editable\n" -"enum Option_i32 {\n" -" Some(i32),\n" -" None,\n" -"}\n" -"\n" -"enum Option_f64 {\n" -" Some(f64),\n" -" None,\n" -"}\n" -"\n" -"fn main() {\n" -" let integer = Option_i32::Some(5);\n" -" let float = Option_f64::Some(5.0);\n" -"}\n" -"```" -msgstr "" - #: src/generics/monomorphization.md:31 msgid "" "This is a zero-cost abstraction: you get exactly the same result as if you " @@ -9837,44 +8739,24 @@ msgstr "" "Rust te permite abstraer sobre tipos con _traits_. Son similares a las " "interfaces:" -#: src/traits.md:5 -msgid "" -"```rust,editable\n" -"trait Pet {\n" -" fn name(&self) -> String;\n" -"}\n" -"\n" -"struct Dog {\n" -" name: String,\n" -"}\n" -"\n" -"struct Cat;\n" -"\n" -"impl Pet for Dog {\n" -" fn name(&self) -> String {\n" -" self.name.clone()\n" -" }\n" -"}\n" -"\n" -"impl Pet for Cat {\n" -" fn name(&self) -> String {\n" -" String::from(\"The cat\") // No name, cats won't respond to it " -"anyway.\n" -" }\n" -"}\n" -"\n" -"fn greet(pet: &P) {\n" -" println!(\"Who's a cutie? {} is!\", pet.name());\n" -"}\n" -"\n" -"fn main() {\n" -" let fido = Dog { name: \"Fido\".into() };\n" -" greet(&fido);\n" -"\n" -" let captain_floof = Cat;\n" -" greet(&captain_floof);\n" -"}\n" -"```" +#: src/traits.md:7 src/traits/trait-objects.md:7 +msgid "// No name needed, cats won't respond anyway.\n" +msgstr "" + +#: src/traits.md:14 src/traits/trait-objects.md:14 +msgid "\"Woof, my name is {}!\"" +msgstr "" + +#: src/traits.md:18 src/traits/trait-objects.md:18 +msgid "\"Miau!\"" +msgstr "" + +#: src/traits.md:22 +msgid "\"Oh you're a cutie! What's your name? {}\"" +msgstr "" + +#: src/traits.md:27 src/traits/trait-objects.md:24 +msgid "\"Fido\"" msgstr "" #: src/traits/trait-objects.md:3 @@ -9885,97 +8767,122 @@ msgstr "" "Los objetos de _traits_ permiten valores de diferentes tipos, por ejemplo, " "en una colección:" -#: src/traits/trait-objects.md:5 -msgid "" -"```rust,editable\n" -"trait Pet {\n" -" fn name(&self) -> String;\n" -"}\n" -"\n" -"struct Dog {\n" -" name: String,\n" -"}\n" -"\n" -"struct Cat;\n" -"\n" -"impl Pet for Dog {\n" -" fn name(&self) -> String {\n" -" self.name.clone()\n" -" }\n" -"}\n" -"\n" -"impl Pet for Cat {\n" -" fn name(&self) -> String {\n" -" String::from(\"The cat\") // No name, cats won't respond to it " -"anyway.\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let pets: Vec> = vec![\n" -" Box::new(Cat),\n" -" Box::new(Dog { name: String::from(\"Fido\") }),\n" -" ];\n" -" for pet in pets {\n" -" println!(\"Hello {}!\", pet.name());\n" -" }\n" -"}\n" -"```" +#: src/traits/trait-objects.md:27 +msgid "\"Hello, who are you? {}\"" msgstr "" -#: src/traits/trait-objects.md:40 +#: src/traits/trait-objects.md:32 msgid "Memory layout after allocating `pets`:" msgstr "Diseño de la memoria después de asignar `pets`:" -#: src/traits/trait-objects.md:42 +#: src/traits/trait-objects.md:34 +#, fuzzy +#| msgid "" +#| "```bob\n" +#| " Stack Heap\n" +#| ".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - " +#| "- - - -.\n" +#| ": : : :\n" +#| ": " +#| "pets : : :\n" +#| ": +-----------+-------+ : : +-----+-----" +#| "+ :\n" +#| ": | ptr | o---+---+-----+-->| o o | o o " +#| "| :\n" +#| ": | len | 2 | : : +-|-|-+-|-|-" +#| "+ :\n" +#| ": | capacity | 2 | : : | | | | +---------------" +#| "+ :\n" +#| ": +-----------+-------+ : : | | | '-->| name: \"Fido\" " +#| "| :\n" +#| ": : : | | | +---------------" +#| "+ :\n" +#| "`- - - - - - - - - - - - - -' : | | " +#| "| :\n" +#| " : | | | " +#| "+----------------------+ : \n" +#| " : | | '---->| \"::" +#| "name\" | :\n" +#| " : | | " +#| "+----------------------+ : \n" +#| " : | " +#| "| : \n" +#| " : | | +-" +#| "+ : \n" +#| " : | '-->|" +#| "\\| : \n" +#| " : | +-" +#| "+ : \n" +#| " : " +#| "| : \n" +#| " : | +----------------------" +#| "+ : \n" +#| " : '---->| \"::name\" " +#| "| : \n" +#| " : +----------------------" +#| "+ :\n" +#| " : :\n" +#| " '- - - - - - - - - - - - - - - - - - - " +#| "- - - -'\n" +#| "\n" +#| "```" msgid "" "```bob\n" " Stack Heap\n" ".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - " "- -.\n" ": : : :\n" -": " -"pets : : :\n" -": +-----------+-------+ : : +-----+-----" -"+ :\n" -": | ptr | o---+---+-----+-->| o o | o o " -"| :\n" -": | len | 2 | : : +-|-|-+-|-|-" -"+ :\n" -": | capacity | 2 | : : | | | | +---------------" -"+ :\n" -": +-----------+-------+ : : | | | '-->| name: \"Fido\" " -"| :\n" -": : : | | | +---------------" -"+ :\n" -"`- - - - - - - - - - - - - -' : | | " +": pets : : +----+----+----+----" +"+ :\n" +": +-----------+-------+ : : +-----+-----+ .->| F | i | d | o " +"| :\n" +": | ptr | o---+---+-----+-->| o o | o o | | +----+----+----+----" +"+ :\n" +": | len | 2 | : : +-|-|-+-|-|-+ " +"`---------. :\n" +": | capacity | 2 | : : | | | | data " +"| :\n" +": +-----------+-------+ : : | | | | +-------+--|-------" +"+ :\n" +": : : | | | '-->| name | o, 4, 4 " +"| :\n" +": : : | | | | age | 5 " +"| :\n" +"`- - - - - - - - - - - - - -' : | | | +-------+----------" +"+ :\n" +" : | | " "| :\n" +" : | | | " +"vtable :\n" " : | | | +----------------------" -"+ : \n" -" : | | '---->| \"::name\" " +"+ :\n" +" : | | '---->| \"::talk\" " "| :\n" " : | | +----------------------" -"+ : \n" +"+ :\n" " : | " -"| : \n" -" : | | +-" -"+ : \n" -" : | '-->|" -"\\| : \n" -" : | +-" -"+ : \n" +"| :\n" +" : | | " +"data :\n" +" : | | +-------+-------" +"+ :\n" +" : | '-->| lives | 9 " +"| :\n" +" : | +-------+-------" +"+ :\n" " : " -"| : \n" +"| :\n" +" : | " +"vtable :\n" " : | +----------------------" -"+ : \n" -" : '---->| \"::name\" " -"| : \n" +"+ :\n" +" : '---->| \"::talk\" " +"| :\n" " : +----------------------" "+ :\n" " : :\n" " '- - - - - - - - - - - - - - - - - - - - - " "- -'\n" -"\n" "```" msgstr "" "```bob\n" @@ -10027,16 +8934,20 @@ msgstr "" "\n" "```" -#: src/traits/trait-objects.md:72 +#: src/traits/trait-objects.md:68 +#, fuzzy +#| msgid "" +#| "Types that implement a given trait may be of different sizes. This makes " +#| "it impossible to have things like `Vec` in the example above." msgid "" "Types that implement a given trait may be of different sizes. This makes it " -"impossible to have things like `Vec` in the example above." +"impossible to have things like `Vec` in the example above." msgstr "" "Los tipos que implementan un trait determinado pueden tener diferentes " "tamaños. Esto hace imposible tener elementos como `Vec` en el ejemplo " "anterior." -#: src/traits/trait-objects.md:73 +#: src/traits/trait-objects.md:70 msgid "" "`dyn Pet` is a way to tell the compiler about a dynamically sized type that " "implements `Pet`." @@ -10044,32 +8955,50 @@ msgstr "" "`dyn Pet` es una forma de indicar al compilador un tipo de tamaño dinámico " "que implementa `Pet`." +#: src/traits/trait-objects.md:72 +msgid "" +"In the example, `pets` is allocated on the stack and the vector data is on " +"the heap. The two vector elements are _fat pointers_:" +msgstr "" + #: src/traits/trait-objects.md:74 +#, fuzzy +#| msgid "" +#| "In the example, `pets` holds _fat pointers_ to objects that implement " +#| "`Pet`. The fat pointer consists of two components, a pointer to the " +#| "actual object and a pointer to the virtual method table for the `Pet` " +#| "implementation of that particular object." msgid "" -"In the example, `pets` holds _fat pointers_ to objects that implement `Pet`. " -"The fat pointer consists of two components, a pointer to the actual object " -"and a pointer to the virtual method table for the `Pet` implementation of " -"that particular object." +"A fat pointer is a double-width pointer. It has two components: a pointer to " +"the actual object and a pointer to the [virtual method table](https://en." +"wikipedia.org/wiki/Virtual_method_table) (vtable) for the `Pet` " +"implementation of that particular object." msgstr "" "En el ejemplo, `pets` contiene _punteros grandes_ en los objetos que " "implementan `Pet`. El puntero grande consta de dos componentes: un puntero " "al objeto real y un puntero a la tabla de métodos virtuales para la " "implementación de `Pet` en ese objeto concreto." -#: src/traits/trait-objects.md:75 +#: src/traits/trait-objects.md:77 +msgid "" +"The data for the `Dog` named Fido is the `name` and `age` fields. The `Cat` " +"has a `lives` field." +msgstr "" + +#: src/traits/trait-objects.md:79 msgid "Compare these outputs in the above example:" msgstr "Compara estas salidas en el ejemplo anterior:" -#: src/traits/trait-objects.md:76 -msgid "" -"```rust,ignore\n" -" println!(\"{} {}\", std::mem::size_of::(), std::mem::size_of::" -"());\n" -" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::" -"<&Cat>());\n" -" println!(\"{}\", std::mem::size_of::<&dyn Pet>());\n" -" println!(\"{}\", std::mem::size_of::>());\n" -"```" +#: src/traits/trait-objects.md:81 src/traits/trait-objects.md:82 +#: src/traits/closures.md:54 +msgid "\"{} {}\"" +msgstr "" + +#: src/traits/trait-objects.md:83 src/traits/trait-objects.md:84 +#: src/testing/test-modules.md:12 src/android/build-rules/library.md:44 +#: src/async/pitfalls/cancellation.md:59 +#: src/exercises/day-3/solutions-morning.md:128 +msgid "\"{}\"" msgstr "" #: src/traits/deriving-traits.md:3 @@ -10086,23 +9015,18 @@ msgstr "" "Puedes dejar que el compilador derive una serie de _traits_ de la siguiente " "manera:" -#: src/traits/deriving-traits.md:7 -msgid "" -"```rust,editable\n" -"#[derive(Debug, Clone, PartialEq, Eq, Default)]\n" -"struct Player {\n" -" name: String,\n" -" strength: u8,\n" -" hit_points: u8,\n" -"}\n" -"\n" -"fn main() {\n" -" let p1 = Player::default();\n" -" let p2 = p1.clone();\n" -" println!(\"Is {:?}\\nequal to {:?}?\\nThe answer is {}!\", &p1, &p2,\n" -" if p1 == p2 { \"yes\" } else { \"no\" });\n" -"}\n" -"```" +#: src/traits/deriving-traits.md:18 +msgid "\"Is {:?}\\nequal to {:?}?\\nThe answer is {}!\"" +msgstr "" + +#: src/traits/deriving-traits.md:19 +#: src/exercises/day-1/solutions-afternoon.md:43 +msgid "\"yes\"" +msgstr "" + +#: src/traits/deriving-traits.md:19 +#: src/exercises/day-1/solutions-afternoon.md:43 +msgid "\"no\"" msgstr "" #: src/traits/default-methods.md:3 @@ -10111,32 +9035,12 @@ msgstr "" "Los _traits_ pueden implementar comportamientos en función de otros métodos " "de _traits_:" -#: src/traits/default-methods.md:5 -msgid "" -"```rust,editable\n" -"trait Equals {\n" -" fn equals(&self, other: &Self) -> bool;\n" -" fn not_equals(&self, other: &Self) -> bool {\n" -" !self.equals(other)\n" -" }\n" -"}\n" -"\n" -"#[derive(Debug)]\n" -"struct Centimeter(i16);\n" -"\n" -"impl Equals for Centimeter {\n" -" fn equals(&self, other: &Centimeter) -> bool {\n" -" self.0 == other.0\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let a = Centimeter(10);\n" -" let b = Centimeter(20);\n" -" println!(\"{a:?} equals {b:?}: {}\", a.equals(&b));\n" -" println!(\"{a:?} not_equals {b:?}: {}\", a.not_equals(&b));\n" -"}\n" -"```" +#: src/traits/default-methods.md:25 +msgid "\"{a:?} equals {b:?}: {}\"" +msgstr "" + +#: src/traits/default-methods.md:26 +msgid "\"{a:?} not_equals {b:?}: {}\"" msgstr "" #: src/traits/default-methods.md:32 @@ -10158,43 +9062,10 @@ msgstr "Mueve el método `not_equals` a un nuevo trait `NotEquals`." msgid "Make `Equals` a super trait for `NotEquals`." msgstr "Haz que `Equals` sea un supertrait para `NotEquals`." -#: src/traits/default-methods.md:38 -msgid "" -"```rust,editable,compile_fail\n" -"trait NotEquals: Equals {\n" -" fn not_equals(&self, other: &Self) -> bool {\n" -" !self.equals(other)\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust,editable,compile_fail\n" -"trait NotEquals: Equals {\n" -" fn not_equals(&self, other: &Self) -> bool {\n" -" !self.equals(other)\n" -" }\n" -"}\n" -"```" - #: src/traits/default-methods.md:46 msgid "Provide a blanket implementation of `NotEquals` for `Equals`." msgstr "Proporciona una implementación general de `NotEquals` para `Equals`." -#: src/traits/default-methods.md:47 -msgid "" -"```rust,editable,compile_fail\n" -"trait NotEquals {\n" -" fn not_equals(&self, other: &Self) -> bool;\n" -"}\n" -"\n" -"impl NotEquals for T where T: Equals {\n" -" fn not_equals(&self, other: &Self) -> bool {\n" -" !self.equals(other)\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/traits/default-methods.md:58 msgid "" "With the blanket implementation, you no longer need `Equals` as a super " @@ -10216,32 +9087,26 @@ msgstr "" msgid "You can do this with `T: Trait` or `impl Trait`:" msgstr "Puedes hacerlo con `T: Trait` o `impl Trait`:" -#: src/traits/trait-bounds.md:8 +#: src/traits/trait-bounds.md:12 msgid "" -"```rust,editable\n" -"fn duplicate(a: T) -> (T, T) {\n" -" (a.clone(), a.clone())\n" -"}\n" -"\n" "// Syntactic sugar for:\n" "// fn add_42_millions>(x: T) -> i32 {\n" -"fn add_42_millions(x: impl Into) -> i32 {\n" -" x.into() + 42_000_000\n" -"}\n" -"\n" -"// struct NotClonable;\n" -"\n" -"fn main() {\n" -" let foo = String::from(\"foo\");\n" -" let pair = duplicate(foo);\n" -" println!(\"{pair:?}\");\n" -"\n" -" let many = add_42_millions(42_i8);\n" -" println!(\"{many}\");\n" -" let many_more = add_42_millions(10_000_000);\n" -" println!(\"{many_more}\");\n" -"}\n" -"```" +msgstr "" + +#: src/traits/trait-bounds.md:18 +msgid "// struct NotClonable;\n" +msgstr "" + +#: src/traits/trait-bounds.md:24 +msgid "\"{pair:?}\"" +msgstr "" + +#: src/traits/trait-bounds.md:27 +msgid "\"{many}\"" +msgstr "" + +#: src/traits/trait-bounds.md:29 +msgid "\"{many_more}\"" msgstr "" #: src/traits/trait-bounds.md:35 @@ -10250,18 +9115,6 @@ msgstr "" "Muestra una cláusula `where` para que los alumnos la encuentren al leer el " "código." -#: src/traits/trait-bounds.md:37 -msgid "" -"```rust,ignore\n" -"fn duplicate(a: T) -> (T, T)\n" -"where\n" -" T: Clone,\n" -"{\n" -" (a.clone(), a.clone())\n" -"}\n" -"```" -msgstr "" - #: src/traits/trait-bounds.md:46 msgid "It declutters the function signature if you have many parameters." msgstr "Despeja la firma de la función si tienes muchos parámetros." @@ -10290,22 +9143,6 @@ msgstr "" "De forma similar a los límites de _traits_, se puede usar la sintaxis `impl " "Trait` en argumentos de funciones y valores devueltos:" -#: src/traits/impl-trait.md:6 -msgid "" -"```rust,editable\n" -"use std::fmt::Display;\n" -"\n" -"fn get_x(name: impl Display) -> impl Display {\n" -" format!(\"Hello {name}\")\n" -"}\n" -"\n" -"fn main() {\n" -" let x = get_x(\"foo\");\n" -" println!(\"{x}\");\n" -"}\n" -"```" -msgstr "" - #: src/traits/impl-trait.md:19 msgid "`impl Trait` allows you to work with types which you cannot name." msgstr "" @@ -10444,32 +9281,8 @@ msgstr "" "Se puede implementar el trait [`Iterator`](https://doc.rust-lang.org/std/" "iter/trait.Iterator.html) en tus propios tipos:" -#: src/traits/iterator.md:5 -msgid "" -"```rust,editable\n" -"struct Fibonacci {\n" -" curr: u32,\n" -" next: u32,\n" -"}\n" -"\n" -"impl Iterator for Fibonacci {\n" -" type Item = u32;\n" -"\n" -" fn next(&mut self) -> Option {\n" -" let new_next = self.curr + self.next;\n" -" self.curr = self.next;\n" -" self.next = new_next;\n" -" Some(self.curr)\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let fib = Fibonacci { curr: 0, next: 1 };\n" -" for (i, n) in fib.enumerate().take(5) {\n" -" println!(\"fib({i}): {n}\");\n" -" }\n" -"}\n" -"```" +#: src/traits/iterator.md:25 +msgid "\"fib({i}): {n}\"" msgstr "" #: src/traits/iterator.md:32 @@ -10509,20 +9322,11 @@ msgstr "" "permite construir una colección a partir de un [`Iterator`](https://doc.rust-" "lang.org/std/iter/trait.Iterator.html)." -#: src/traits/from-iterator.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let primes = vec![2, 3, 5, 7];\n" -" let prime_squares = primes\n" -" .into_iter()\n" -" .map(|prime| prime * prime)\n" -" .collect::>();\n" -"}\n" -"```" +#: src/traits/from-iterator.md:12 +msgid "\"prime_squares: {prime_squares:?}\"" msgstr "" -#: src/traits/from-iterator.md:17 +#: src/traits/from-iterator.md:18 msgid "" "`Iterator` implements `fn collect(self) -> B where B: FromIterator, Self: Sized`" @@ -10530,7 +9334,7 @@ msgstr "" "`Iterator` implementa `fn collect(self) -> B where B: FromIterator, Self: Sized`." -#: src/traits/from-iterator.md:23 +#: src/traits/from-iterator.md:24 msgid "" "There are also implementations which let you do cool things like convert an " "`Iterator>` into a `Result, E>`." @@ -10552,17 +9356,8 @@ msgstr "" "From.html) y [`Into`](https://doc.rust-lang.org/std/convert/trait.Into.html) " "para facilitar las conversiones de tipos:" -#: src/traits/from-into.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s = String::from(\"hello\");\n" -" let addr = std::net::Ipv4Addr::from([127, 0, 0, 1]);\n" -" let one = i16::from(true);\n" -" let bigger = i32::from(123i16);\n" -" println!(\"{s}, {addr}, {one}, {bigger}\");\n" -"}\n" -"```" +#: src/traits/from-into.md:11 src/traits/from-into.md:23 +msgid "\"{s}, {addr}, {one}, {bigger}\"" msgstr "" #: src/traits/from-into.md:15 @@ -10575,19 +9370,6 @@ msgstr "" "implementa automáticamente cuando se implementa [`From`](https://doc.rust-" "lang.org/std/convert/trait.From.html):" -#: src/traits/from-into.md:17 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s: String = \"hello\".into();\n" -" let addr: std::net::Ipv4Addr = [127, 0, 0, 1].into();\n" -" let one: i16 = true.into();\n" -" let bigger: i32 = 123i16.into();\n" -" println!(\"{s}, {addr}, {one}, {bigger}\");\n" -"}\n" -"```" -msgstr "" - #: src/traits/from-into.md:29 msgid "" "That's why it is common to only implement `From`, as your type will get " @@ -10622,25 +9404,16 @@ msgstr "" "[`BufRead`](https://doc.rust-lang.org/std/io/trait.BufRead.html), se puede " "abstraer sobre fuentes `u8`:" -#: src/traits/read-write.md:5 -msgid "" -"```rust,editable\n" -"use std::io::{BufRead, BufReader, Read, Result};\n" -"\n" -"fn count_lines(reader: R) -> usize {\n" -" let buf_reader = BufReader::new(reader);\n" -" buf_reader.lines().count()\n" -"}\n" -"\n" -"fn main() -> Result<()> {\n" -" let slice: &[u8] = b\"foo\\nbar\\nbaz\\n\";\n" -" println!(\"lines in slice: {}\", count_lines(slice));\n" -"\n" -" let file = std::fs::File::open(std::env::current_exe()?)?;\n" -" println!(\"lines in file: {}\", count_lines(file));\n" -" Ok(())\n" -"}\n" -"```" +#: src/traits/read-write.md:14 +msgid "b\"foo\\nbar\\nbaz\\n\"" +msgstr "" + +#: src/traits/read-write.md:15 +msgid "\"lines in slice: {}\"" +msgstr "" + +#: src/traits/read-write.md:18 +msgid "\"lines in file: {}\"" msgstr "" #: src/traits/read-write.md:23 @@ -10651,24 +9424,12 @@ msgstr "" "De forma similar, [`Write`](https://doc.rust-lang.org/std/io/trait.Write." "html) te permite abstraer sobre fuentes `u8`:" -#: src/traits/read-write.md:25 -msgid "" -"```rust,editable\n" -"use std::io::{Result, Write};\n" -"\n" -"fn log(writer: &mut W, msg: &str) -> Result<()> {\n" -" writer.write_all(msg.as_bytes())?;\n" -" writer.write_all(\"\\n\".as_bytes())\n" -"}\n" -"\n" -"fn main() -> Result<()> {\n" -" let mut buffer = Vec::new();\n" -" log(&mut buffer, \"Hello\")?;\n" -" log(&mut buffer, \"World\")?;\n" -" println!(\"Logged: {:?}\", buffer);\n" -" Ok(())\n" -"}\n" -"```" +#: src/traits/read-write.md:30 +msgid "\"\\n\"" +msgstr "" + +#: src/traits/read-write.md:37 +msgid "\"Logged: {:?}\"" msgstr "" #: src/traits/drop.md:1 @@ -10684,45 +9445,82 @@ msgstr "" "Drop.html) pueden especificar el código que se ejecutará cuando salgan del " "ámbito:" -#: src/traits/drop.md:5 -msgid "" -"```rust,editable\n" -"struct Droppable {\n" -" name: &'static str,\n" -"}\n" -"\n" -"impl Drop for Droppable {\n" -" fn drop(&mut self) {\n" -" println!(\"Dropping {}\", self.name);\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let a = Droppable { name: \"a\" };\n" -" {\n" -" let b = Droppable { name: \"b\" };\n" -" {\n" -" let c = Droppable { name: \"c\" };\n" -" let d = Droppable { name: \"d\" };\n" -" println!(\"Exiting block B\");\n" -" }\n" -" println!(\"Exiting block A\");\n" -" }\n" -" drop(a);\n" -" println!(\"Exiting main\");\n" -"}\n" -"```" +#: src/traits/drop.md:12 +msgid "\"Dropping {}\"" +msgstr "" + +#: src/traits/drop.md:17 src/exercises/concurrency/link-checker.md:92 +#: src/exercises/day-1/solutions-morning.md:86 +#: src/exercises/concurrency/solutions-morning.md:123 +msgid "\"a\"" +msgstr "" + +#: src/traits/drop.md:19 src/exercises/day-1/solutions-morning.md:86 +msgid "\"b\"" +msgstr "" + +#: src/traits/drop.md:21 src/exercises/day-1/solutions-morning.md:86 +msgid "\"c\"" +msgstr "" + +#: src/traits/drop.md:22 src/exercises/day-1/solutions-morning.md:86 +msgid "\"d\"" +msgstr "" + +#: src/traits/drop.md:23 +msgid "\"Exiting block B\"" +msgstr "" + +#: src/traits/drop.md:25 +msgid "\"Exiting block A\"" +msgstr "" + +#: src/traits/drop.md:28 +msgid "\"Exiting main\"" +msgstr "" + +#: src/traits/drop.md:34 +msgid "Note that `std::mem::drop` is not the same as `std::ops::Drop::drop`." +msgstr "" + +#: src/traits/drop.md:35 +msgid "Values are automatically dropped when they go out of scope." +msgstr "" + +#: src/traits/drop.md:36 +msgid "" +"When a value is dropped, if it implements `std::ops::Drop` then its `Drop::" +"drop` implementation will be called." +msgstr "" + +#: src/traits/drop.md:38 +msgid "" +"All its fields will then be dropped too, whether or not it implements `Drop`." +msgstr "" + +#: src/traits/drop.md:39 +msgid "" +"`std::mem::drop` is just an empty function that takes any value. The " +"significance is that it takes ownership of the value, so at the end of its " +"scope it gets dropped. This makes it a convenient way to explicitly drop " +"values earlier than they would otherwise go out of scope." msgstr "" -#: src/traits/drop.md:34 src/traits/operators.md:26 +#: src/traits/drop.md:42 +msgid "" +"This can be useful for objects that do some work on `drop`: releasing locks, " +"closing files, etc." +msgstr "" + +#: src/traits/drop.md:45 src/traits/operators.md:26 msgid "Discussion points:" msgstr "Cuestiones de debate:" -#: src/traits/drop.md:36 +#: src/traits/drop.md:47 msgid "Why doesn't `Drop::drop` take `self`?" msgstr "¿Por qué `Drop::drop` no acepta `self`?" -#: src/traits/drop.md:37 +#: src/traits/drop.md:48 msgid "" "Short-answer: If it did, `std::mem::drop` would be called at the end of the " "block, resulting in another call to `Drop::drop`, and a stack overflow!" @@ -10731,7 +9529,7 @@ msgstr "" "bloque, lo que daría como resultado otra llamada a `Drop::drop` y un " "desbordamiento de la _stack_." -#: src/traits/drop.md:40 +#: src/traits/drop.md:51 msgid "Try replacing `drop(a)` with `a.drop()`." msgstr "Prueba a sustituir `drop(a)` por `a.drop()`." @@ -10747,40 +9545,24 @@ msgstr "" "El trait [`Default`](https://doc.rust-lang.org/std/default/trait.Default." "html) produce un valor predeterminado para un tipo." -#: src/traits/default.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug, Default)]\n" -"struct Derived {\n" -" x: u32,\n" -" y: String,\n" -" z: Implemented,\n" -"}\n" -"\n" -"#[derive(Debug)]\n" -"struct Implemented(String);\n" -"\n" -"impl Default for Implemented {\n" -" fn default() -> Self {\n" -" Self(\"John Smith\".into())\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let default_struct = Derived::default();\n" -" println!(\"{default_struct:#?}\");\n" -"\n" -" let almost_default_struct = Derived {\n" -" y: \"Y is set!\".into(),\n" -" ..Derived::default()\n" -" };\n" -" println!(\"{almost_default_struct:#?}\");\n" -"\n" -" let nothing: Option = None;\n" -" println!(\"{:#?}\", nothing.unwrap_or_default());\n" -"}\n" -"\n" -"```" +#: src/traits/default.md:18 +msgid "\"John Smith\"" +msgstr "" + +#: src/traits/default.md:24 +msgid "\"{default_struct:#?}\"" +msgstr "" + +#: src/traits/default.md:27 +msgid "\"Y is set!\"" +msgstr "" + +#: src/traits/default.md:30 +msgid "\"{almost_default_struct:#?}\"" +msgstr "" + +#: src/traits/default.md:33 +msgid "\"{:#?}\"" msgstr "" #: src/traits/default.md:40 @@ -10849,26 +9631,8 @@ msgstr "" "La sobrecarga de operadores se implementa mediante _traits_ en [`std::ops`]" "(https://doc.rust-lang.org/std/ops/index.html):" -#: src/traits/operators.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug, Copy, Clone)]\n" -"struct Point { x: i32, y: i32 }\n" -"\n" -"impl std::ops::Add for Point {\n" -" type Output = Self;\n" -"\n" -" fn add(self, other: Self) -> Self {\n" -" Self {x: self.x + other.x, y: self.y + other.y}\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let p1 = Point { x: 10, y: 20 };\n" -" let p2 = Point { x: 100, y: 200 };\n" -" println!(\"{:?} + {:?} = {:?}\", p1, p2, p1 + p2);\n" -"}\n" -"```" +#: src/traits/operators.md:20 +msgid "\"{:?} + {:?} = {:?}\"" msgstr "" #: src/traits/operators.md:28 @@ -10930,31 +9694,22 @@ msgstr "" "FnMut.html) y [`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce." "html):" -#: src/traits/closures.md:8 -msgid "" -"```rust,editable\n" -"fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {\n" -" println!(\"Calling function on {input}\");\n" -" func(input)\n" -"}\n" -"\n" -"fn main() {\n" -" let add_3 = |x| x + 3;\n" -" println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" -" println!(\"add_3: {}\", apply_with_log(add_3, 20));\n" -"\n" -" let mut v = Vec::new();\n" -" let mut accumulate = |x: i32| {\n" -" v.push(x);\n" -" v.iter().sum::()\n" -" };\n" -" println!(\"accumulate: {}\", apply_with_log(&mut accumulate, 4));\n" -" println!(\"accumulate: {}\", apply_with_log(&mut accumulate, 5));\n" -"\n" -" let multiply_sum = |x| x * v.into_iter().sum::();\n" -" println!(\"multiply_sum: {}\", apply_with_log(multiply_sum, 3));\n" -"}\n" -"```" +#: src/traits/closures.md:10 +#, fuzzy +#| msgid "Calling Unsafe Functions" +msgid "\"Calling function on {input}\"" +msgstr "Llamar Funciones Unsafe (Inseguras)" + +#: src/traits/closures.md:16 src/traits/closures.md:17 +msgid "\"add_3: {}\"" +msgstr "" + +#: src/traits/closures.md:24 src/traits/closures.md:25 +msgid "\"accumulate: {}\"" +msgstr "" + +#: src/traits/closures.md:28 +msgid "\"multiply_sum: {}\"" msgstr "" #: src/traits/closures.md:34 @@ -11010,18 +9765,12 @@ msgstr "" "De forma predeterminada, los cierres capturan, si pueden, por referencia. La " "palabra clave `move` hace que capturen por valor." -#: src/traits/closures.md:52 -msgid "" -"```rust,editable\n" -"fn make_greeter(prefix: String) -> impl Fn(&str) {\n" -" return move |name| println!(\"{} {}\", prefix, name)\n" -"}\n" -"\n" -"fn main() {\n" -" let hi = make_greeter(\"Hi\".to_string());\n" -" hi(\"there\");\n" -"}\n" -"```" +#: src/traits/closures.md:58 +msgid "\"Hi\"" +msgstr "" + +#: src/traits/closures.md:59 +msgid "\"there\"" msgstr "" #: src/exercises/day-3/morning.md:1 @@ -11040,10 +9789,22 @@ msgstr "" "También veremos la asignación de enumeraciones con un ejercicio que " "involucra puntos y polígonos." +#: src/exercises/day-3/simple-gui.md:1 +#: src/exercises/day-3/solutions-morning.md:3 +#, fuzzy +#| msgid "A Simple GUI Library" +msgid "Drawing A Simple GUI" +msgstr "Una Biblioteca GUI sencilla" + #: src/exercises/day-3/simple-gui.md:3 +#, fuzzy +#| msgid "" +#| "Let us design a classical GUI library using our new knowledge of traits " +#| "and trait objects." msgid "" "Let us design a classical GUI library using our new knowledge of traits and " -"trait objects." +"trait objects. We'll only implement the drawing of it (as text) for " +"simplicity." msgstr "" "Vamos a diseñar una biblioteca GUI clásica con nuestro recién adquirido " "conocimiento sobre _traits_ y objetos trait." @@ -11058,21 +9819,20 @@ msgstr "`Window`: tiene un `title` y contiene otros widgets." #: src/exercises/day-3/simple-gui.md:9 msgid "" -"`Button`: has a `label` and a callback function which is invoked when the " -"button is pressed." +"`Button`: has a `label`. In reality, it would also take a callback function " +"to allow the program to do something when the button is clicked but we won't " +"include that since we're only drawing the GUI." msgstr "" -"`Button`: tiene una `label` y una función de retrollamada que se invoca " -"cuando se pulsa el botón." -#: src/exercises/day-3/simple-gui.md:11 +#: src/exercises/day-3/simple-gui.md:12 msgid "`Label`: has a `label`." msgstr "`Label`: tiene una `label`." -#: src/exercises/day-3/simple-gui.md:13 +#: src/exercises/day-3/simple-gui.md:14 msgid "The widgets will implement a `Widget` trait, see below." msgstr "Los widgets implementarán un trait `Widget`, como se indica más abajo." -#: src/exercises/day-3/simple-gui.md:15 +#: src/exercises/day-3/simple-gui.md:16 msgid "" "Copy the code below to , fill in the missing " "`draw_into` methods so that you implement the `Widget` trait:" @@ -11081,140 +9841,46 @@ msgstr "" "org/> y rellena los métodos `draw_into` que faltan para implementar el trait " "`Widget`:" -#: src/exercises/day-3/simple-gui.md:18 -msgid "" -"```rust,should_panic\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_imports, unused_variables, dead_code)]\n" -"\n" -"pub trait Widget {\n" -" /// Natural width of `self`.\n" -" fn width(&self) -> usize;\n" -"\n" -" /// Draw the widget into a buffer.\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" -"\n" -" /// Draw the widget on standard output.\n" -" fn draw(&self) {\n" -" let mut buffer = String::new();\n" -" self.draw_into(&mut buffer);\n" -" println!(\"{buffer}\");\n" -" }\n" -"}\n" -"\n" -"pub struct Label {\n" -" label: String,\n" -"}\n" -"\n" -"impl Label {\n" -" fn new(label: &str) -> Label {\n" -" Label {\n" -" label: label.to_owned(),\n" -" }\n" -" }\n" -"}\n" -"\n" -"pub struct Button {\n" -" label: Label,\n" -" callback: Box,\n" -"}\n" -"\n" -"impl Button {\n" -" fn new(label: &str, callback: Box) -> Button {\n" -" Button {\n" -" label: Label::new(label),\n" -" callback,\n" -" }\n" -" }\n" -"}\n" -"\n" -"pub struct Window {\n" -" title: String,\n" -" widgets: Vec>,\n" -"}\n" -"\n" -"impl Window {\n" -" fn new(title: &str) -> Window {\n" -" Window {\n" -" title: title.to_owned(),\n" -" widgets: Vec::new(),\n" -" }\n" -" }\n" -"\n" -" fn add_widget(&mut self, widget: Box) {\n" -" self.widgets.push(widget);\n" -" }\n" -"\n" -" fn inner_width(&self) -> usize {\n" -" std::cmp::max(\n" -" self.title.chars().count(),\n" -" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" -" )\n" -" }\n" -"}\n" -"\n" -"\n" -"impl Widget for Label {\n" -" fn width(&self) -> usize {\n" -" unimplemented!()\n" -" }\n" -"\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" unimplemented!()\n" -" }\n" -"}\n" -"\n" -"impl Widget for Button {\n" -" fn width(&self) -> usize {\n" -" unimplemented!()\n" -" }\n" -"\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" unimplemented!()\n" -" }\n" -"}\n" -"\n" -"impl Widget for Window {\n" -" fn width(&self) -> usize {\n" -" unimplemented!()\n" -" }\n" -"\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" unimplemented!()\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" -" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo." -"\")));\n" -" window.add_widget(Box::new(Button::new(\n" -" \"Click me!\",\n" -" Box::new(|| println!(\"You clicked the button!\")),\n" -" )));\n" -" window.draw();\n" -"}\n" -"```" +#: src/exercises/day-3/simple-gui.md:24 +#: src/exercises/day-3/solutions-morning.md:9 +msgid "/// Natural width of `self`.\n" msgstr "" -#: src/exercises/day-3/simple-gui.md:130 -msgid "The output of the above program can be something simple like this:" -msgstr "La salida del programa anterior puede ser algo sencillo como esto:" +#: src/exercises/day-3/simple-gui.md:27 +#: src/exercises/day-3/solutions-morning.md:12 +msgid "/// Draw the widget into a buffer.\n" +msgstr "" -#: src/exercises/day-3/simple-gui.md:132 -msgid "" -"```text\n" -"========\n" -"Rust GUI Demo 1.23\n" -"========\n" -"\n" -"This is a small text GUI demo.\n" -"\n" -"| Click me! |\n" -"```" +#: src/exercises/day-3/simple-gui.md:30 +#: src/exercises/day-3/solutions-morning.md:15 +msgid "/// Draw the widget on standard output.\n" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:34 +#: src/exercises/day-3/solutions-morning.md:19 +msgid "\"{buffer}\"" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:119 +#: src/exercises/day-3/solutions-morning.md:133 +msgid "\"Rust GUI Demo 1.23\"" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:120 +#: src/exercises/day-3/solutions-morning.md:134 +msgid "\"This is a small text GUI demo.\"" +msgstr "" + +#: src/exercises/day-3/simple-gui.md:122 +#: src/exercises/day-3/solutions-morning.md:136 +msgid "\"Click me!\"" msgstr "" -#: src/exercises/day-3/simple-gui.md:142 +#: src/exercises/day-3/simple-gui.md:128 +msgid "The output of the above program can be something simple like this:" +msgstr "La salida del programa anterior puede ser algo sencillo como esto:" + +#: src/exercises/day-3/simple-gui.md:140 msgid "" "If you want to draw aligned text, you can use the [fill/alignment](https://" "doc.rust-lang.org/std/fmt/index.html#fillalignment) formatting operators. In " @@ -11226,39 +9892,25 @@ msgstr "" "html#fillalignment). En concreto, observa cómo puedes rellenar con distintos " "caracteres (en este caso, `'/'`) y cómo puedes controlar la alineación:" -#: src/exercises/day-3/simple-gui.md:147 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let width = 10;\n" -" println!(\"left aligned: |{:/width$}|\", \"foo\");\n" -"}\n" -"```" +#: src/exercises/day-3/simple-gui.md:148 +msgid "\"left aligned: |{:/width$}|\"" msgstr "" -#: src/exercises/day-3/simple-gui.md:156 +#: src/exercises/day-3/simple-gui.md:154 msgid "" "Using such alignment tricks, you can for example produce output like this:" msgstr "" "Con estos trucos de alineación puedes, por ejemplo, obtener resultados como " "el siguiente:" -#: src/exercises/day-3/simple-gui.md:158 -msgid "" -"```text\n" -"+--------------------------------+\n" -"| Rust GUI Demo 1.23 |\n" -"+================================+\n" -"| This is a small text GUI demo. |\n" -"| +-----------+ |\n" -"| | Click me! | |\n" -"| +-----------+ |\n" -"+--------------------------------+\n" -"```" -msgstr "" - #: src/exercises/day-3/points-polygons.md:1 msgid "Polygon Struct" msgstr "Estructura de polígono" @@ -11273,117 +9925,20 @@ msgstr "" "siguiente fragmento de código en la página y " "rellena los métodos que faltan para pasar las pruebas:" -#: src/exercises/day-3/points-polygons.md:7 -msgid "" -"```rust\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]\n" -"\n" -"pub struct Point {\n" -" // add fields\n" -"}\n" -"\n" -"impl Point {\n" -" // add methods\n" -"}\n" -"\n" -"pub struct Polygon {\n" -" // add fields\n" -"}\n" -"\n" -"impl Polygon {\n" -" // add methods\n" -"}\n" -"\n" -"pub struct Circle {\n" -" // add fields\n" -"}\n" -"\n" -"impl Circle {\n" -" // add methods\n" -"}\n" -"\n" -"pub enum Shape {\n" -" Polygon(Polygon),\n" -" Circle(Circle),\n" -"}\n" -"\n" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;\n" -"\n" -" fn round_two_digits(x: f64) -> f64 {\n" -" (x * 100.0).round() / 100.0\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_magnitude() {\n" -" let p1 = Point::new(12, 13);\n" -" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_dist() {\n" -" let p1 = Point::new(10, 10);\n" -" let p2 = Point::new(14, 13);\n" -" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_add() {\n" -" let p1 = Point::new(16, 16);\n" -" let p2 = p1 + Point::new(-4, 3);\n" -" assert_eq!(p2, Point::new(12, 19));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_left_most_point() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -" assert_eq!(poly.left_most_point(), Some(p1));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_iter() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -"\n" -" let points = poly.iter().cloned().collect::>();\n" -" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_shape_perimeters() {\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(Point::new(12, 13));\n" -" poly.add_point(Point::new(17, 11));\n" -" poly.add_point(Point::new(16, 16));\n" -" let shapes = vec![\n" -" Shape::from(poly),\n" -" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" -" ];\n" -" let perimeters = shapes\n" -" .iter()\n" -" .map(Shape::perimeter)\n" -" .map(round_two_digits)\n" -" .collect::>();\n" -" assert_eq!(perimeters, vec![15.48, 31.42]);\n" -" }\n" -"}\n" -"\n" -"#[allow(dead_code)]\n" -"fn main() {}\n" -"```" +#: src/exercises/day-3/points-polygons.md:12 +#: src/exercises/day-3/points-polygons.md:20 +#: src/exercises/day-3/points-polygons.md:28 +msgid "// add fields\n" msgstr "" +#: src/exercises/day-3/points-polygons.md:16 +#: src/exercises/day-3/points-polygons.md:24 +#: src/exercises/day-3/points-polygons.md:32 +#, fuzzy +#| msgid "Structs and methods." +msgid "// add methods\n" +msgstr "Estructuras (_Structs_) y métodos." + #: src/exercises/day-3/points-polygons.md:117 msgid "" "Since the method signatures are missing from the problem statements, the key " @@ -11435,14 +9990,8 @@ msgstr "No hay excepciones." msgid "Rust will trigger a panic if a fatal error happens at runtime:" msgstr "Rust activará un _panic_ si se produce un error grave en _runtime_:" -#: src/error-handling/panics.md:5 -msgid "" -"```rust,editable,should_panic\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" println!(\"v[100]: {}\", v[100]);\n" -"}\n" -"```" +#: src/error-handling/panics.md:8 +msgid "\"v[100]: {}\"" msgstr "" #: src/error-handling/panics.md:12 @@ -11472,23 +10021,16 @@ msgstr "" "De forma predeterminada, el _panic_ hará que la _stack_ se desenrolle. El " "proceso de desenrrollado se puede detectar:" -#: src/error-handling/panic-unwind.md:5 -msgid "" -"```rust,editable\n" -"use std::panic;\n" -"\n" -"fn main() {\n" -" let result = panic::catch_unwind(|| {\n" -" println!(\"hello!\");\n" -" });\n" -" assert!(result.is_ok());\n" -" \n" -" let result = panic::catch_unwind(|| {\n" -" panic!(\"oh no!\");\n" -" });\n" -" assert!(result.is_err());\n" -"}\n" -"```" +#: src/error-handling/panic-unwind.md:10 +msgid "\"No problem here!\"" +msgstr "" + +#: src/error-handling/panic-unwind.md:12 src/error-handling/panic-unwind.md:17 +msgid "\"{result:?}\"" +msgstr "" + +#: src/error-handling/panic-unwind.md:15 +msgid "\"oh no!\"" msgstr "" #: src/error-handling/panic-unwind.md:21 @@ -11515,26 +10057,16 @@ msgstr "" "Ya hemos visto la _enum_ `Result`. Se utiliza normalmente cuando se esperan " "errores como parte del funcionamiento normal:" -#: src/error-handling/result.md:6 -msgid "" -"```rust,editable\n" -"use std::fs;\n" -"use std::io::Read;\n" -"\n" -"fn main() {\n" -" let file = fs::File::open(\"diary.txt\");\n" -" match file {\n" -" Ok(mut file) => {\n" -" let mut contents = String::new();\n" -" file.read_to_string(&mut contents);\n" -" println!(\"Dear diary: {contents}\");\n" -" },\n" -" Err(err) => {\n" -" println!(\"The diary could not be opened: {err}\");\n" -" }\n" -" }\n" -"}\n" -"```" +#: src/error-handling/result.md:11 +msgid "\"diary.txt\"" +msgstr "" + +#: src/error-handling/result.md:16 +msgid "\"Dear diary: {contents}\"" +msgstr "" + +#: src/error-handling/result.md:19 +msgid "\"The diary could not be opened: {err}\"" msgstr "" #: src/error-handling/result.md:27 @@ -11572,57 +10104,29 @@ msgstr "" "El operador try `?` se utiliza para devolver errores al llamador. Te permite " "convertir" -#: src/error-handling/try-operator.md:6 -msgid "" -"```rust,ignore\n" -"match some_expression {\n" -" Ok(value) => value,\n" -" Err(err) => return Err(err),\n" -"}\n" -"```" -msgstr "" - #: src/error-handling/try-operator.md:13 msgid "into the much simpler" msgstr "en algo mucho más sencillo:" -#: src/error-handling/try-operator.md:15 -msgid "" -"```rust,ignore\n" -"some_expression?\n" -"```" -msgstr "" - #: src/error-handling/try-operator.md:19 msgid "We can use this to simplify our error handling code:" msgstr "Podemos utilizarlo para simplificar el código de gestión de errores:" -#: src/error-handling/try-operator.md:21 -msgid "" -"```rust,editable\n" -"use std::{fs, io};\n" -"use std::io::Read;\n" -"\n" -"fn read_username(path: &str) -> Result {\n" -" let username_file_result = fs::File::open(path);\n" -" let mut username_file = match username_file_result {\n" -" Ok(file) => file,\n" -" Err(err) => return Err(err),\n" -" };\n" -"\n" -" let mut username = String::new();\n" -" match username_file.read_to_string(&mut username) {\n" -" Ok(_) => Ok(username),\n" -" Err(err) => Err(err),\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" //fs::write(\"config.dat\", \"alice\").unwrap();\n" -" let username = read_username(\"config.dat\");\n" -" println!(\"username or error: {username:?}\");\n" -"}\n" -"```" +#: src/error-handling/try-operator.md:40 +msgid "//fs::write(\"config.dat\", \"alice\").unwrap();\n" +msgstr "" + +#: src/error-handling/try-operator.md:41 +#: src/error-handling/converting-error-types-example.md:43 +#: src/error-handling/deriving-error-enums.md:30 +#: src/error-handling/dynamic-errors.md:27 +#: src/error-handling/error-contexts.md:26 +msgid "\"config.dat\"" +msgstr "" + +#: src/error-handling/try-operator.md:42 +#: src/error-handling/converting-error-types-example.md:44 +msgid "\"username or error: {username:?}\"" msgstr "" #: src/error-handling/try-operator.md:50 @@ -11675,27 +10179,10 @@ msgstr "" "La expansión efectiva de `?` es un poco más complicada de lo que se ha " "indicado anteriormente:" -#: src/error-handling/converting-error-types.md:5 -msgid "" -"```rust,ignore\n" -"expression?\n" -"```" -msgstr "" - #: src/error-handling/converting-error-types.md:9 msgid "works the same as" msgstr "funciona igual que" -#: src/error-handling/converting-error-types.md:11 -msgid "" -"```rust,ignore\n" -"match expression {\n" -" Ok(value) => value,\n" -" Err(err) => return Err(From::from(err)),\n" -"}\n" -"```" -msgstr "" - #: src/error-handling/converting-error-types.md:18 msgid "" "The `From::from` call here means we attempt to convert the error type to the " @@ -11704,53 +10191,19 @@ msgstr "" "Aquí la llamada a `From::from` significa que intentamos convertir el tipo de " "error al tipo que devuelve la función:" -#: src/error-handling/converting-error-types-example.md:3 -msgid "" -"```rust,editable\n" -"use std::error::Error;\n" -"use std::fmt::{self, Display, Formatter};\n" -"use std::fs::{self, File};\n" -"use std::io::{self, Read};\n" -"\n" -"#[derive(Debug)]\n" -"enum ReadUsernameError {\n" -" IoError(io::Error),\n" -" EmptyUsername(String),\n" -"}\n" -"\n" -"impl Error for ReadUsernameError {}\n" -"\n" -"impl Display for ReadUsernameError {\n" -" fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" -" match self {\n" -" Self::IoError(e) => write!(f, \"IO error: {e}\"),\n" -" Self::EmptyUsername(filename) => write!(f, \"Found no username " -"in {filename}\"),\n" -" }\n" -" }\n" -"}\n" -"\n" -"impl From for ReadUsernameError {\n" -" fn from(err: io::Error) -> ReadUsernameError {\n" -" ReadUsernameError::IoError(err)\n" -" }\n" -"}\n" -"\n" -"fn read_username(path: &str) -> Result {\n" -" let mut username = String::with_capacity(100);\n" -" File::open(path)?.read_to_string(&mut username)?;\n" -" if username.is_empty() {\n" -" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" -" }\n" -" Ok(username)\n" -"}\n" -"\n" -"fn main() {\n" -" //fs::write(\"config.dat\", \"\").unwrap();\n" -" let username = read_username(\"config.dat\");\n" -" println!(\"username or error: {username:?}\");\n" -"}\n" -"```" +#: src/error-handling/converting-error-types-example.md:20 +msgid "\"IO error: {e}\"" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:21 +msgid "\"Found no username in {filename}\"" +msgstr "" + +#: src/error-handling/converting-error-types-example.md:42 +#: src/error-handling/deriving-error-enums.md:29 +#: src/error-handling/dynamic-errors.md:26 +#: src/error-handling/error-contexts.md:25 +msgid "//fs::write(\"config.dat\", \"\").unwrap();\n" msgstr "" #: src/error-handling/converting-error-types-example.md:55 @@ -11786,38 +10239,24 @@ msgstr "" "errores es el crate [thiserror](https://docs.rs/thiserror/), como hicimos en " "la página anterior:" -#: src/error-handling/deriving-error-enums.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"use std::{fs, io};\n" -"use std::io::Read;\n" -"use thiserror::Error;\n" -"\n" -"#[derive(Debug, Error)]\n" -"enum ReadUsernameError {\n" -" #[error(\"Could not read: {0}\")]\n" -" IoError(#[from] io::Error),\n" -" #[error(\"Found no username in {0}\")]\n" -" EmptyUsername(String),\n" -"}\n" -"\n" -"fn read_username(path: &str) -> Result {\n" -" let mut username = String::new();\n" -" fs::File::open(path)?.read_to_string(&mut username)?;\n" -" if username.is_empty() {\n" -" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" -" }\n" -" Ok(username)\n" -"}\n" -"\n" -"fn main() {\n" -" //fs::write(\"config.dat\", \"\").unwrap();\n" -" match read_username(\"config.dat\") {\n" -" Ok(username) => println!(\"Username: {username}\"),\n" -" Err(err) => println!(\"Error: {err}\"),\n" -" }\n" -"}\n" -"```" +#: src/error-handling/deriving-error-enums.md:13 +msgid "\"Could not read: {0}\"" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:15 +#: src/error-handling/dynamic-errors.md:13 +msgid "\"Found no username in {0}\"" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:31 +#: src/error-handling/dynamic-errors.md:28 +#: src/error-handling/error-contexts.md:27 +msgid "\"Username: {username}\"" +msgstr "" + +#: src/error-handling/deriving-error-enums.md:32 +#: src/error-handling/dynamic-errors.md:29 +msgid "\"Error: {err}\"" msgstr "" #: src/error-handling/deriving-error-enums.md:39 @@ -11846,37 +10285,6 @@ msgstr "" "escribir nuestra propia _enum_ que cubra todas las posibilidades. `std::" "error::Error` facilita este proceso." -#: src/error-handling/dynamic-errors.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"use std::fs;\n" -"use std::io::Read;\n" -"use thiserror::Error;\n" -"use std::error::Error;\n" -"\n" -"#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" -"#[error(\"Found no username in {0}\")]\n" -"struct EmptyUsernameError(String);\n" -"\n" -"fn read_username(path: &str) -> Result> {\n" -" let mut username = String::new();\n" -" fs::File::open(path)?.read_to_string(&mut username)?;\n" -" if username.is_empty() {\n" -" return Err(EmptyUsernameError(String::from(path)).into());\n" -" }\n" -" Ok(username)\n" -"}\n" -"\n" -"fn main() {\n" -" //fs::write(\"config.dat\", \"\").unwrap();\n" -" match read_username(\"config.dat\") {\n" -" Ok(username) => println!(\"Username: {username}\"),\n" -" Err(err) => println!(\"Error: {err}\"),\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/error-handling/dynamic-errors.md:36 msgid "" "This saves on code, but gives up the ability to cleanly handle different " @@ -11901,33 +10309,20 @@ msgstr "" "puede ayudar a añadir información contextual a los errores y permite tener " "menos tipos de errores personalizados:" -#: src/error-handling/error-contexts.md:7 -msgid "" -"```rust,editable,compile_fail\n" -"use std::{fs, io};\n" -"use std::io::Read;\n" -"use anyhow::{Context, Result, bail};\n" -"\n" -"fn read_username(path: &str) -> Result {\n" -" let mut username = String::with_capacity(100);\n" -" fs::File::open(path)\n" -" .with_context(|| format!(\"Failed to open {path}\"))?\n" -" .read_to_string(&mut username)\n" -" .context(\"Failed to read\")?;\n" -" if username.is_empty() {\n" -" bail!(\"Found no username in {path}\");\n" -" }\n" -" Ok(username)\n" -"}\n" -"\n" -"fn main() {\n" -" //fs::write(\"config.dat\", \"\").unwrap();\n" -" match read_username(\"config.dat\") {\n" -" Ok(username) => println!(\"Username: {username}\"),\n" -" Err(err) => println!(\"Error: {err:?}\"),\n" -" }\n" -"}\n" -"```" +#: src/error-handling/error-contexts.md:15 +msgid "\"Failed to open {path}\"" +msgstr "" + +#: src/error-handling/error-contexts.md:17 +msgid "\"Failed to read\"" +msgstr "" + +#: src/error-handling/error-contexts.md:19 +msgid "\"Found no username in {path}\"" +msgstr "" + +#: src/error-handling/error-contexts.md:28 +msgid "\"Error: {err:?}\"" msgstr "" #: src/error-handling/error-contexts.md:35 @@ -11979,32 +10374,11 @@ msgstr "" msgid "Mark unit tests with `#[test]`:" msgstr "Marca pruebas unitarias con `#[test]`:" -#: src/testing/unit-tests.md:5 -msgid "" -"```rust,editable,ignore\n" -"fn first_word(text: &str) -> &str {\n" -" match text.find(' ') {\n" -" Some(idx) => &text[..idx],\n" -" None => &text,\n" -" }\n" -"}\n" -"\n" -"#[test]\n" -"fn test_empty() {\n" -" assert_eq!(first_word(\"\"), \"\");\n" -"}\n" -"\n" -"#[test]\n" -"fn test_single_word() {\n" -" assert_eq!(first_word(\"Hello\"), \"Hello\");\n" -"}\n" -"\n" -"#[test]\n" -"fn test_multiple_words() {\n" -" assert_eq!(first_word(\"Hello World\"), \"Hello\");\n" -"}\n" -"```" -msgstr "" +#: src/testing/unit-tests.md:25 +#, fuzzy +#| msgid "Hello World!" +msgid "\"Hello World\"" +msgstr "¡Hola, mundo!" #: src/testing/unit-tests.md:29 msgid "Use `cargo test` to find and run the unit tests." @@ -12018,27 +10392,12 @@ msgstr "" "Las pruebas unitarias se suelen incluir en un módulo anidado (ejecuta las " "pruebas en el [_Playground_](https://play.rust-lang.org/)):" -#: src/testing/test-modules.md:6 -msgid "" -"```rust,editable\n" -"fn helper(a: &str, b: &str) -> String {\n" -" format!(\"{a} {b}\")\n" -"}\n" -"\n" -"pub fn main() {\n" -" println!(\"{}\", helper(\"Hello\", \"World\"));\n" -"}\n" -"\n" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;\n" -"\n" -" #[test]\n" -" fn test_helper() {\n" -" assert_eq!(helper(\"foo\", \"bar\"), \"foo bar\");\n" -" }\n" -"}\n" -"```" +#: src/testing/test-modules.md:8 +msgid "\"{a} {b}\"" +msgstr "" + +#: src/testing/test-modules.md:21 +msgid "\"foo bar\"" msgstr "" #: src/testing/test-modules.md:26 @@ -12054,20 +10413,15 @@ msgstr "" msgid "Rust has built-in support for documentation tests:" msgstr "Rust cuenta con asistencia integrada para pruebas de documentación:" -#: src/testing/doc-tests.md:5 +#: src/testing/doc-tests.md:6 msgid "" -"```rust\n" "/// Shortens a string to the given length.\n" "///\n" "/// ```\n" -"/// use playground::shorten_string;\n" +"/// # use playground::shorten_string;\n" "/// assert_eq!(shorten_string(\"Hello World\", 5), \"Hello\");\n" "/// assert_eq!(shorten_string(\"Hello World\", 20), \"Hello World\");\n" "/// ```\n" -"pub fn shorten_string(s: &str, length: usize) -> &str {\n" -" &s[..std::cmp::min(length, s.len())]\n" -"}\n" -"```" msgstr "" #: src/testing/doc-tests.md:18 @@ -12082,6 +10436,12 @@ msgstr "El código se compilará y ejecutará como parte de `cargo test`." #: src/testing/doc-tests.md:20 msgid "" +"Adding `# ` in the code will hide it from the docs, but will still compile/" +"run it." +msgstr "" + +#: src/testing/doc-tests.md:21 +msgid "" "Test the above code on the [Rust Playground](https://play.rust-lang.org/?" "version=stable&mode=debug&edition=2021&gist=3ce2ad13ea1302f6572cb15cd96becf0)." msgstr "" @@ -12098,18 +10458,6 @@ msgstr "" msgid "Create a `.rs` file under `tests/`:" msgstr "Crea un archivo `.rs` en `tests/`:" -#: src/testing/integration-tests.md:7 -msgid "" -"```rust,ignore\n" -"use my_library::init;\n" -"\n" -"#[test]\n" -"fn test_init() {\n" -" assert!(init().is_ok());\n" -"}\n" -"```" -msgstr "" - #: src/testing/integration-tests.md:16 msgid "These tests only have access to the public API of your crate." msgstr "Estas pruebas solo tienen acceso a la API pública de tu crate." @@ -12238,28 +10586,22 @@ msgstr "" "La creación de punteros es un proceso seguro, pero para anular las " "referencias, es necesario utilizar `unsafe`:" -#: src/unsafe/raw-pointers.md:5 +#: src/unsafe/raw-pointers.md:12 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut num = 5;\n" -"\n" -" let r1 = &mut num as *mut i32;\n" -" let r2 = r1 as *const i32;\n" -"\n" -" // Safe because r1 and r2 were obtained from references and so are\n" +"// Safe because r1 and r2 were obtained from references and so are\n" " // guaranteed to be non-null and properly aligned, the objects " "underlying\n" " // the references from which they were obtained are live throughout the\n" " // whole unsafe block, and they are not accessed either through the\n" " // references or concurrently through any other pointers.\n" -" unsafe {\n" -" println!(\"r1 is: {}\", *r1);\n" -" *r1 = 10;\n" -" println!(\"r2 is: {}\", *r2);\n" -" }\n" -"}\n" -"```" +msgstr "" + +#: src/unsafe/raw-pointers.md:18 +msgid "\"r1 is: {}\"" +msgstr "" + +#: src/unsafe/raw-pointers.md:20 +msgid "\"r2 is: {}\"" msgstr "" #: src/unsafe/raw-pointers.md:27 @@ -12321,15 +10663,14 @@ msgstr "" msgid "It is safe to read an immutable static variable:" msgstr "Es seguro leer una variable estática inmutable:" -#: src/unsafe/mutable-static-variables.md:5 -msgid "" -"```rust,editable\n" -"static HELLO_WORLD: &str = \"Hello, world!\";\n" -"\n" -"fn main() {\n" -" println!(\"HELLO_WORLD: {HELLO_WORLD}\");\n" -"}\n" -"```" +#: src/unsafe/mutable-static-variables.md:6 +#, fuzzy +#| msgid "Hello World!" +msgid "\"Hello, world!\"" +msgstr "¡Hola, mundo!" + +#: src/unsafe/mutable-static-variables.md:9 +msgid "\"HELLO_WORLD: {HELLO_WORLD}\"" msgstr "" #: src/unsafe/mutable-static-variables.md:13 @@ -12340,25 +10681,25 @@ msgstr "" "Sin embargo, dado que pueden producirse carreras de datos, no es seguro leer " "y escribir variables estáticas mutables:" -#: src/unsafe/mutable-static-variables.md:16 -msgid "" -"```rust,editable\n" -"static mut COUNTER: u32 = 0;\n" -"\n" -"fn add_to_counter(inc: u32) {\n" -" unsafe { COUNTER += inc; } // Potential data race!\n" -"}\n" -"\n" -"fn main() {\n" -" add_to_counter(42);\n" -"\n" -" unsafe { println!(\"COUNTER: {COUNTER}\"); } // Potential data race!\n" -"}\n" -"```" +#: src/unsafe/mutable-static-variables.md:20 +#: src/unsafe/mutable-static-variables.md:26 +msgid "// Potential data race!\n" +msgstr "" + +#: src/unsafe/mutable-static-variables.md:26 +msgid "\"COUNTER: {COUNTER}\"" msgstr "" #: src/unsafe/mutable-static-variables.md:32 msgid "" +"The program here is safe because it is single-threaded. However, the Rust " +"compiler is conservative and will assume the worst. Try removing the " +"`unsafe` and see how the compiler explains that it is undefined behavior to " +"mutate a static from multiple threads." +msgstr "" + +#: src/unsafe/mutable-static-variables.md:36 +msgid "" "Using a mutable static is generally a bad idea, but there are some cases " "where it might make sense in low-level `no_std` code, such as implementing a " "heap allocator or working with some C APIs." @@ -12373,23 +10714,20 @@ msgstr "" "Las uniones son como _enums_ (enumeraciones), pero eres tú quien debe hacer " "el seguimiento del campo activo:" -#: src/unsafe/unions.md:5 -msgid "" -"```rust,editable\n" -"#[repr(C)]\n" -"union MyUnion {\n" -" i: u8,\n" -" b: bool,\n" -"}\n" -"\n" -"fn main() {\n" -" let u = MyUnion { i: 42 };\n" -" println!(\"int: {}\", unsafe { u.i });\n" -" println!(\"bool: {}\", unsafe { u.b }); // Undefined behavior!\n" -"}\n" -"```" +#: src/unsafe/unions.md:14 +msgid "\"int: {}\"" +msgstr "" + +#: src/unsafe/unions.md:15 +msgid "\"bool: {}\"" msgstr "" +#: src/unsafe/unions.md:15 +#, fuzzy +#| msgid "No undefined behavior at runtime:" +msgid "// Undefined behavior!\n" +msgstr "No hay comportamientos indefinidos en _runtime_:" + #: src/unsafe/unions.md:21 msgid "" "Unions are very rarely needed in Rust as you can usually use an enum. They " @@ -12419,34 +10757,32 @@ msgstr "" "previas adicionales que debes mantener para evitar un comportamiento " "indefinido:" -#: src/unsafe/calling-unsafe-functions.md:6 +#: src/unsafe/calling-unsafe-functions.md:8 +msgid "\"🗻∈🌏\"" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:10 msgid "" -"```rust,editable\n" -"fn main() {\n" -" let emojis = \"🗻∈🌏\";\n" -"\n" -" // Safe because the indices are in the correct order, within the bounds " -"of\n" +"// Safe because the indices are in the correct order, within the bounds of\n" " // the string slice, and lie on UTF-8 sequence boundaries.\n" -" unsafe {\n" -" println!(\"emoji: {}\", emojis.get_unchecked(0..4));\n" -" println!(\"emoji: {}\", emojis.get_unchecked(4..7));\n" -" println!(\"emoji: {}\", emojis.get_unchecked(7..11));\n" -" }\n" -"\n" -" println!(\"char count: {}\", count_chars(unsafe { emojis." -"get_unchecked(0..7) }));\n" -"\n" -" // Not upholding the UTF-8 encoding requirement breaks memory safety!\n" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:13 +#: src/unsafe/calling-unsafe-functions.md:14 +#: src/unsafe/calling-unsafe-functions.md:15 +msgid "\"emoji: {}\"" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:18 +msgid "\"char count: {}\"" +msgstr "" + +#: src/unsafe/calling-unsafe-functions.md:20 +msgid "" +"// Not upholding the UTF-8 encoding requirement breaks memory safety!\n" " // println!(\"emoji: {}\", unsafe { emojis.get_unchecked(0..3) });\n" " // println!(\"char count: {}\", count_chars(unsafe { emojis." "get_unchecked(0..3) }));\n" -"}\n" -"\n" -"fn count_chars(s: &str) -> usize {\n" -" s.chars().map(|_| 1).sum()\n" -"}\n" -"```" msgstr "" #: src/unsafe/writing-unsafe-functions.md:3 @@ -12457,32 +10793,21 @@ msgstr "" "Puedes marcar tus propias funciones como `unsafe` si requieren condiciones " "concretas para evitar un comportamiento indefinido." -#: src/unsafe/writing-unsafe-functions.md:6 +#: src/unsafe/writing-unsafe-functions.md:7 msgid "" -"```rust,editable\n" "/// Swaps the values pointed to by the given pointers.\n" "///\n" "/// # Safety\n" "///\n" "/// The pointers must be valid and properly aligned.\n" -"unsafe fn swap(a: *mut u8, b: *mut u8) {\n" -" let temp = *a;\n" -" *a = *b;\n" -" *b = temp;\n" -"}\n" -"\n" -"fn main() {\n" -" let mut a = 42;\n" -" let mut b = 66;\n" -"\n" -" // Safe because ...\n" -" unsafe {\n" -" swap(&mut a, &mut b);\n" -" }\n" -"\n" -" println!(\"a = {}, b = {}\", a, b);\n" -"}\n" -"```" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:22 +msgid "// Safe because ...\n" +msgstr "" + +#: src/unsafe/writing-unsafe-functions.md:27 +msgid "\"a = {}, b = {}\"" msgstr "" #: src/unsafe/writing-unsafe-functions.md:33 @@ -12515,20 +10840,30 @@ msgstr "" "Es posible que las funciones de otros lenguajes infrinjan las garantías de " "Rust. Por lo tanto, no es seguro llamarlas:" -#: src/unsafe/extern-functions.md:6 -msgid "" -"```rust,editable\n" -"extern \"C\" {\n" -" fn abs(input: i32) -> i32;\n" -"}\n" -"\n" -"fn main() {\n" -" unsafe {\n" -" // Undefined behavior if abs misbehaves.\n" -" println!(\"Absolute value of -3 according to C: {}\", abs(-3));\n" -" }\n" -"}\n" -"```" +#: src/unsafe/extern-functions.md:7 src/exercises/day-3/safe-ffi-wrapper.md:89 +#: src/android/interoperability/with-c.md:9 +#: src/android/interoperability/with-c/rust.md:15 +#: src/android/interoperability/with-c/rust.md:30 +#: src/bare-metal/aps/inline-assembly.md:18 +#: src/bare-metal/aps/better-uart/using.md:24 +#: src/bare-metal/aps/logging/using.md:23 src/exercises/bare-metal/rtc.md:46 +#: src/exercises/bare-metal/rtc.md:100 src/exercises/bare-metal/rtc.md:106 +#: src/exercises/bare-metal/rtc.md:113 src/exercises/bare-metal/rtc.md:119 +#: src/exercises/bare-metal/rtc.md:125 src/exercises/bare-metal/rtc.md:131 +#: src/exercises/bare-metal/rtc.md:137 src/exercises/bare-metal/rtc.md:143 +#: src/exercises/day-3/solutions-afternoon.md:45 +#: src/exercises/bare-metal/solutions-afternoon.md:43 +msgid "\"C\"" +msgstr "" + +#: src/unsafe/extern-functions.md:13 +#, fuzzy +#| msgid "No undefined behavior at runtime:" +msgid "// Undefined behavior if abs misbehaves.\n" +msgstr "No hay comportamientos indefinidos en _runtime_:" + +#: src/unsafe/extern-functions.md:14 +msgid "\"Absolute value of -3 according to C: {}\"" msgstr "" #: src/unsafe/extern-functions.md:21 @@ -12567,27 +10902,15 @@ msgstr "" "Por ejemplo, el crate `zerocopy` tiene un trait inseguro, [que se parece a " "esto](https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html):" -#: src/unsafe/unsafe-traits.md:9 +#: src/unsafe/unsafe-traits.md:12 msgid "" -"```rust,editable\n" -"use std::mem::size_of_val;\n" -"use std::slice;\n" -"\n" "/// ...\n" "/// # Safety\n" "/// The type must have a defined representation and no padding.\n" -"pub unsafe trait AsBytes {\n" -" fn as_bytes(&self) -> &[u8] {\n" -" unsafe {\n" -" slice::from_raw_parts(self as *const Self as *const u8, " -"size_of_val(self))\n" -" }\n" -" }\n" -"}\n" -"\n" -"// Safe because u32 has a defined representation and no padding.\n" -"unsafe impl AsBytes for u32 {}\n" -"```" +msgstr "" + +#: src/unsafe/unsafe-traits.md:23 +msgid "// Safe because u32 has a defined representation and no padding.\n" msgstr "" #: src/unsafe/unsafe-traits.md:30 @@ -12645,10 +10968,15 @@ msgstr "" "afternoon.md) proporcionada." #: src/exercises/day-3/safe-ffi-wrapper.md:3 +#, fuzzy +#| msgid "" +#| "Rust has great support for calling functions through a _foreign function " +#| "interface_ (FFI). We will use this to build a safe wrapper for the `libc` " +#| "functions you would use from C to read the filenames of a directory." msgid "" "Rust has great support for calling functions through a _foreign function " "interface_ (FFI). We will use this to build a safe wrapper for the `libc` " -"functions you would use from C to read the filenames of a directory." +"functions you would use from C to read the names of files in a directory." msgstr "" "Rust ofrece una gran asisencia para llamar a funciones a través de una " "_interfaz de función externa_ (FFI). Usaremos esto para crear un envoltorio " @@ -12762,9 +11090,13 @@ msgstr "" "final `\\0`," #: src/exercises/day-3/safe-ffi-wrapper.md:27 +#, fuzzy +#| msgid "" +#| "`&CStr` to `&[u8]`: a slice of bytes is the universal interface for " +#| "\"some unknow data\"," msgid "" "`&CStr` to `&[u8]`: a slice of bytes is the universal interface for \"some " -"unknow data\"," +"unknown data\"," msgstr "" "De `&CStr` a `&[u8]`: un slice de bytes es la interfaz universal para " "\"algunos datos desconocidos\"." @@ -12801,111 +11133,88 @@ msgstr "" "Copia el fragmento de código que aparece más abajo en la página y rellena los métodos y funciones que faltan:" -#: src/exercises/day-3/safe-ffi-wrapper.md:48 +#: src/exercises/day-3/safe-ffi-wrapper.md:54 +#: src/exercises/day-3/safe-ffi-wrapper.md:67 +#: src/exercises/day-3/safe-ffi-wrapper.md:78 +#: src/exercises/day-3/safe-ffi-wrapper.md:92 +#: src/exercises/day-3/safe-ffi-wrapper.md:100 +#: src/exercises/day-3/solutions-afternoon.md:10 +#: src/exercises/day-3/solutions-afternoon.md:23 +#: src/exercises/day-3/solutions-afternoon.md:34 +#: src/exercises/day-3/solutions-afternoon.md:48 +#: src/exercises/day-3/solutions-afternoon.md:56 +msgid "\"macos\"" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:57 +#: src/exercises/day-3/solutions-afternoon.md:13 +msgid "// Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:64 +#: src/exercises/day-3/solutions-afternoon.md:20 msgid "" -"```rust,should_panic\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_imports, unused_variables, dead_code)]\n" -"\n" -"mod ffi {\n" -" use std::os::raw::{c_char, c_int};\n" -" #[cfg(not(target_os = \"macos\"))]\n" -" use std::os::raw::{c_long, c_ulong, c_ushort, c_uchar};\n" -"\n" -" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" -" #[repr(C)]\n" -" pub struct DIR {\n" -" _data: [u8; 0],\n" -" _marker: core::marker::PhantomData<(*mut u8, core::marker::" -"PhantomPinned)>,\n" -" }\n" -"\n" -" // Layout according to the Linux man page for readdir(3), where ino_t " -"and\n" +"// Layout according to the Linux man page for readdir(3), where ino_t and\n" " // off_t are resolved according to the definitions in\n" " // /usr/include/x86_64-linux-gnu/{sys/types.h, bits/typesizes.h}.\n" -" #[cfg(not(target_os = \"macos\"))]\n" -" #[repr(C)]\n" -" pub struct dirent {\n" -" pub d_ino: c_ulong,\n" -" pub d_off: c_long,\n" -" pub d_reclen: c_ushort,\n" -" pub d_type: c_uchar,\n" -" pub d_name: [c_char; 256],\n" -" }\n" -"\n" -" // Layout according to the macOS man page for dir(5).\n" -" #[cfg(all(target_os = \"macos\"))]\n" -" #[repr(C)]\n" -" pub struct dirent {\n" -" pub d_fileno: u64,\n" -" pub d_seekoff: u64,\n" -" pub d_reclen: u16,\n" -" pub d_namlen: u16,\n" -" pub d_type: u8,\n" -" pub d_name: [c_char; 1024],\n" -" }\n" -"\n" -" extern \"C\" {\n" -" pub fn opendir(s: *const c_char) -> *mut DIR;\n" -"\n" -" #[cfg(not(all(target_os = \"macos\", target_arch = \"x86_64\")))]\n" -" pub fn readdir(s: *mut DIR) -> *const dirent;\n" -"\n" -" // See https://github.com/rust-lang/libc/issues/414 and the section " -"on\n" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:77 +#: src/exercises/day-3/solutions-afternoon.md:33 +msgid "// Layout according to the macOS man page for dir(5).\n" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:92 +#: src/exercises/day-3/safe-ffi-wrapper.md:100 +#: src/exercises/day-3/solutions-afternoon.md:48 +#: src/exercises/day-3/solutions-afternoon.md:56 +msgid "\"x86_64\"" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:95 +#: src/exercises/day-3/solutions-afternoon.md:51 +msgid "" +"// See https://github.com/rust-lang/libc/issues/414 and the section on\n" " // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2).\n" " //\n" " // \"Platforms that existed before these updates were available\" " "refers\n" " // to macOS (as opposed to iOS / wearOS / etc.) on Intel and " "PowerPC.\n" -" #[cfg(all(target_os = \"macos\", target_arch = \"x86_64\"))]\n" -" #[link_name = \"readdir$INODE64\"]\n" -" pub fn readdir(s: *mut DIR) -> *const dirent;\n" -"\n" -" pub fn closedir(s: *mut DIR) -> c_int;\n" -" }\n" -"}\n" -"\n" -"use std::ffi::{CStr, CString, OsStr, OsString};\n" -"use std::os::unix::ffi::OsStrExt;\n" -"\n" -"#[derive(Debug)]\n" -"struct DirectoryIterator {\n" -" path: CString,\n" -" dir: *mut ffi::DIR,\n" -"}\n" -"\n" -"impl DirectoryIterator {\n" -" fn new(path: &str) -> Result {\n" -" // Call opendir and return a Ok value if that worked,\n" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:101 +#: src/exercises/day-3/solutions-afternoon.md:57 +msgid "\"readdir$INODE64\"" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:119 +#: src/exercises/day-3/solutions-afternoon.md:75 +msgid "" +"// Call opendir and return a Ok value if that worked,\n" " // otherwise return Err with a message.\n" -" unimplemented!()\n" -" }\n" -"}\n" -"\n" -"impl Iterator for DirectoryIterator {\n" -" type Item = OsString;\n" -" fn next(&mut self) -> Option {\n" -" // Keep calling readdir until we get a NULL pointer back.\n" -" unimplemented!()\n" -" }\n" -"}\n" -"\n" -"impl Drop for DirectoryIterator {\n" -" fn drop(&mut self) {\n" -" // Call closedir as needed.\n" -" unimplemented!()\n" -" }\n" -"}\n" -"\n" -"fn main() -> Result<(), String> {\n" -" let iter = DirectoryIterator::new(\".\")?;\n" -" println!(\"files: {:#?}\", iter.collect::>());\n" -" Ok(())\n" -"}\n" -"```" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:128 +msgid "// Keep calling readdir until we get a NULL pointer back.\n" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:135 +#: src/exercises/day-3/solutions-afternoon.md:108 +msgid "// Call closedir as needed.\n" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:141 +#: src/android/interoperability/with-c/rust.md:44 +#: src/exercises/day-3/solutions-afternoon.md:119 +#: src/exercises/day-3/solutions-afternoon.md:143 +#: src/exercises/day-3/solutions-afternoon.md:158 +msgid "\".\"" +msgstr "" + +#: src/exercises/day-3/safe-ffi-wrapper.md:142 +#: src/exercises/day-3/solutions-afternoon.md:120 +msgid "\"files: {:#?}\"" msgstr "" #: src/android.md:1 @@ -12942,15 +11251,6 @@ msgstr "" "Utilizaremos un dispositivo Android virtual para probar el código. Asegúrate " "de que tienes acceso a uno o créalo con:" -#: src/android/setup.md:6 -msgid "" -"```shell\n" -"source build/envsetup.sh\n" -"lunch aosp_cf_x86_64_phone-userdebug\n" -"acloud create\n" -"```" -msgstr "" - #: src/android/setup.md:12 msgid "" "Please see the [Android Developer Codelab](https://source.android.com/docs/" @@ -13076,31 +11376,31 @@ msgstr "" msgid "_hello_rust/Android.bp_:" msgstr "_hello_rust/Android.bp_:" -#: src/android/build-rules/binary.md:8 -msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"hello_rust\",\n" -" crate_name: \"hello_rust\",\n" -" srcs: [\"src/main.rs\"],\n" -"}\n" -"```" +#: src/android/build-rules/binary.md:10 src/android/build-rules/binary.md:11 +msgid "\"hello_rust\"" msgstr "" +#: src/android/build-rules/binary.md:12 src/android/build-rules/library.md:19 +#: src/android/logging.md:12 +#, fuzzy +#| msgid "`src/main.rs`:" +msgid "\"src/main.rs\"" +msgstr "`src/main.rs`:" + #: src/android/build-rules/binary.md:16 src/android/build-rules/library.md:34 msgid "_hello_rust/src/main.rs_:" msgstr "_hello_rust/src/main.rs_:" -#: src/android/build-rules/binary.md:18 -msgid "" -"```rust\n" -"//! Rust demo.\n" -"\n" -"/// Prints a greeting to standard output.\n" -"fn main() {\n" -" println!(\"Hello from Rust!\");\n" -"}\n" -"```" +#: src/android/build-rules/binary.md:19 src/android/build-rules/library.md:37 +msgid "//! Rust demo.\n" +msgstr "" + +#: src/android/build-rules/binary.md:20 src/android/build-rules/library.md:41 +msgid "/// Prints a greeting to standard output.\n" +msgstr "" + +#: src/android/build-rules/binary.md:23 +msgid "\"Hello from Rust!\"" msgstr "" #: src/android/build-rules/binary.md:27 @@ -13116,13 +11416,6 @@ msgid "" "```" msgstr "" -#: src/android/build-rules/binary.md:35 -msgid "" -"```text\n" -"Hello from Rust!\n" -"```" -msgstr "" - #: src/android/build-rules/library.md:1 msgid "Rust Libraries" msgstr "Bibliotecas de Rust" @@ -13149,94 +11442,53 @@ msgstr "" "(https://cs.android.com/android/platform/superproject/+/master:external/rust/" "crates/)." -#: src/android/build-rules/library.md:15 -msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"hello_rust_with_dep\",\n" -" crate_name: \"hello_rust_with_dep\",\n" -" srcs: [\"src/main.rs\"],\n" -" rustlibs: [\n" -" \"libgreetings\",\n" -" \"libtextwrap\",\n" -" ],\n" -" prefer_rlib: true,\n" -"}\n" -"\n" -"rust_library {\n" -" name: \"libgreetings\",\n" -" crate_name: \"greetings\",\n" -" srcs: [\"src/lib.rs\"],\n" -"}\n" -"```" +#: src/android/build-rules/library.md:17 src/android/build-rules/library.md:18 +msgid "\"hello_rust_with_dep\"" msgstr "" -"```javascript\n" -"rust_binary {\n" -" name: \"hello_rust_with_dep\",\n" -" crate_name: \"hello_rust_with_dep\",\n" -" srcs: [\"src/main.rs\"],\n" -" rustlibs: [\n" -" \"libgreetings\",\n" -" \"libtextwrap\",\n" -" ],\n" -" prefer_rlib: true,\n" -"}\n" -"\n" -"rust_library {\n" -" name: \"libgreetings\",\n" -" crate_name: \"greetings\",\n" -" srcs: [\"src/lib.rs\"],\n" -"}\n" -"```" -#: src/android/build-rules/library.md:36 -msgid "" -"```rust,ignore\n" -"//! Rust demo.\n" -"\n" -"use greetings::greeting;\n" -"use textwrap::fill;\n" -"\n" -"/// Prints a greeting to standard output.\n" -"fn main() {\n" -" println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" -"}\n" -"```" +#: src/android/build-rules/library.md:21 src/android/build-rules/library.md:28 +msgid "\"libgreetings\"" msgstr "" -"```rust,ignore\n" -"//! Rust demo.\n" -"\n" -"use greetings::greeting;\n" -"use textwrap::fill;\n" -"\n" -"/// Imprime un saludo en una salida estándar.\n" -"fn main() {\n" -" println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" -"}\n" -"```" + +#: src/android/build-rules/library.md:22 +msgid "\"libtextwrap\"" +msgstr "" + +#: src/android/build-rules/library.md:29 +msgid "\"greetings\"" +msgstr "" + +#: src/android/build-rules/library.md:30 src/android/aidl/implementation.md:31 +#: src/android/interoperability/java.md:38 +#, fuzzy +#| msgid "`src/main.rs`:" +msgid "\"src/lib.rs\"" +msgstr "`src/main.rs`:" #: src/android/build-rules/library.md:48 msgid "_hello_rust/src/lib.rs_:" msgstr "_hello_rust/src/lib.rs_:" -#: src/android/build-rules/library.md:50 -msgid "" -"```rust,ignore\n" -"//! Greeting library.\n" -"\n" -"/// Greet `name`.\n" -"pub fn greeting(name: &str) -> String {\n" -" format!(\"Hello {name}, it is very nice to meet you!\")\n" -"}\n" -"```" +#: src/android/build-rules/library.md:51 +msgid "//! Greeting library.\n" msgstr "" -"```rust,ignore\n" -"//! Greeting library.\n" -"\n" -"/// Saludar a `name`.\n" -"pub fn greeting(name: &str) -> String {\n" -" format!(\"Hello {name}, it is very nice to meet you!\")\n" -"}\n" + +#: src/android/build-rules/library.md:52 +msgid "/// Greet `name`.\n" +msgstr "" + +#: src/android/build-rules/library.md:55 +#, fuzzy +#| msgid "" +#| "```text\n" +#| "Hello Bob, it is very\n" +#| "nice to meet you!\n" +#| "```" +msgid "\"Hello {name}, it is very nice to meet you!\"" +msgstr "" +"```text\n" +"Hello Bob, it is very\n" +"nice to meet you!\n" "```" #: src/android/build-rules/library.md:59 @@ -13259,19 +11511,7 @@ msgstr "" "adb shell /data/local/tmp/hello_rust_with_dep\n" "```" -#: src/android/build-rules/library.md:67 -msgid "" -"```text\n" -"Hello Bob, it is very\n" -"nice to meet you!\n" -"```" -msgstr "" -"```text\n" -"Hello Bob, it is very\n" -"nice to meet you!\n" -"```" - -#: src/android/aidl.md:3 +#: src/android/aidl.md:3 msgid "" "The [Android Interface Definition Language (AIDL)](https://developer.android." "com/guide/components/aidl) is supported in Rust:" @@ -13302,59 +11542,33 @@ msgid "" msgstr "" "_birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl_:" -#: src/android/aidl/interface.md:7 -msgid "" -"```java\n" -"package com.example.birthdayservice;\n" -"\n" -"/** Birthday service interface. */\n" -"interface IBirthdayService {\n" -" /** Generate a Happy Birthday message. */\n" -" String wishHappyBirthday(String name, int years);\n" -"}\n" -"```" +#: src/android/aidl/interface.md:9 src/android/aidl/changing.md:8 +msgid "/** Birthday service interface. */" +msgstr "" + +#: src/android/aidl/interface.md:12 src/android/aidl/changing.md:11 +msgid "/** Generate a Happy Birthday message. */" msgstr "" -"```java\n" -"package com.example.birthdayservice;\n" -"\n" -"/** Birthday service interface. */\n" -"interface IBirthdayService {\n" -" /** Generate a Happy Birthday message. */\n" -" String wishHappyBirthday(String name, int years);\n" -"}\n" -"```" #: src/android/aidl/interface.md:17 msgid "_birthday_service/aidl/Android.bp_:" msgstr "_birthday_service/aidl/Android.bp_:" -#: src/android/aidl/interface.md:19 -msgid "" -"```javascript\n" -"aidl_interface {\n" -" name: \"com.example.birthdayservice\",\n" -" srcs: [\"com/example/birthdayservice/*.aidl\"],\n" -" unstable: true,\n" -" backend: {\n" -" rust: { // Rust is not enabled by default\n" -" enabled: true,\n" -" },\n" -" },\n" -"}\n" -"```" +#: src/android/aidl/interface.md:21 +msgid "\"com.example.birthdayservice\"" +msgstr "" + +#: src/android/aidl/interface.md:22 +#, fuzzy +#| msgid "" +#| "_birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl_:" +msgid "\"com/example/birthdayservice/*.aidl\"" +msgstr "" +"_birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl_:" + +#: src/android/aidl/interface.md:25 +msgid "// Rust is not enabled by default\n" msgstr "" -"```javascript\n" -"aidl_interface {\n" -" name: \"com.example.birthdayservice\",\n" -" srcs: [\"com/example/birthdayservice/*.aidl\"],\n" -" unstable: true,\n" -" backend: {\n" -" rust: { // Rust is not enabled by default\n" -" enabled: true,\n" -" },\n" -" },\n" -"}\n" -"```" #: src/android/aidl/interface.md:32 msgid "" @@ -13376,29 +11590,18 @@ msgstr "Ahora podemos implementar el servicio de AIDL:" msgid "_birthday_service/src/lib.rs_:" msgstr "_birthday_service/src/lib.rs_:" -#: src/android/aidl/implementation.md:7 -msgid "" -"```rust,ignore\n" -"//! Implementation of the `IBirthdayService` AIDL interface.\n" -"use com_example_birthdayservice::aidl::com::example::birthdayservice::" -"IBirthdayService::IBirthdayService;\n" -"use com_example_birthdayservice::binder;\n" -"\n" -"/// The `IBirthdayService` implementation.\n" -"pub struct BirthdayService;\n" -"\n" -"impl binder::Interface for BirthdayService {}\n" -"\n" -"impl IBirthdayService for BirthdayService {\n" -" fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::" -"Result {\n" -" Ok(format!(\n" -" \"Happy Birthday {name}, congratulations with the {years} years!" -"\"\n" -" ))\n" -" }\n" -"}\n" -"```" +#: src/android/aidl/implementation.md:8 +msgid "//! Implementation of the `IBirthdayService` AIDL interface.\n" +msgstr "" + +#: src/android/aidl/implementation.md:11 +#, fuzzy +#| msgid "Service Implementation" +msgid "/// The `IBirthdayService` implementation.\n" +msgstr "Implementación del servicio" + +#: src/android/aidl/implementation.md:20 +msgid "\"Happy Birthday {name}, congratulations with the {years} years!\"" msgstr "" #: src/android/aidl/implementation.md:26 src/android/aidl/server.md:28 @@ -13406,19 +11609,27 @@ msgstr "" msgid "_birthday_service/Android.bp_:" msgstr "_birthday_service/Android.bp_:" -#: src/android/aidl/implementation.md:28 -msgid "" -"```javascript\n" -"rust_library {\n" -" name: \"libbirthdayservice\",\n" -" srcs: [\"src/lib.rs\"],\n" -" crate_name: \"birthdayservice\",\n" -" rustlibs: [\n" -" \"com.example.birthdayservice-rust\",\n" -" \"libbinder_rs\",\n" -" ],\n" -"}\n" -"```" +#: src/android/aidl/implementation.md:30 src/android/aidl/server.md:38 +#, fuzzy +#| msgid "_birthday_service/src/lib.rs_:" +msgid "\"libbirthdayservice\"" +msgstr "_birthday_service/src/lib.rs_:" + +#: src/android/aidl/implementation.md:32 src/android/aidl/server.md:13 +#: src/android/aidl/client.md:12 +#, fuzzy +#| msgid "_birthday_service/src/lib.rs_:" +msgid "\"birthdayservice\"" +msgstr "_birthday_service/src/lib.rs_:" + +#: src/android/aidl/implementation.md:34 src/android/aidl/server.md:36 +#: src/android/aidl/client.md:45 +msgid "\"com.example.birthdayservice-rust\"" +msgstr "" + +#: src/android/aidl/implementation.md:35 src/android/aidl/server.md:37 +#: src/android/aidl/client.md:46 +msgid "\"libbinder_rs\"" msgstr "" #: src/android/aidl/server.md:1 @@ -13433,49 +11644,30 @@ msgstr "Por último, podemos crear un servidor que exponga el servicio:" msgid "_birthday_service/src/server.rs_:" msgstr "_birthday_service/src/server.rs_:" -#: src/android/aidl/server.md:7 -msgid "" -"```rust,ignore\n" -"//! Birthday service.\n" -"use birthdayservice::BirthdayService;\n" -"use com_example_birthdayservice::aidl::com::example::birthdayservice::" -"IBirthdayService::BnBirthdayService;\n" -"use com_example_birthdayservice::binder;\n" -"\n" -"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" -"\n" -"/// Entry point for birthday service.\n" -"fn main() {\n" -" let birthday_service = BirthdayService;\n" -" let birthday_service_binder = BnBirthdayService::new_binder(\n" -" birthday_service,\n" -" binder::BinderFeatures::default(),\n" -" );\n" -" binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder." -"as_binder())\n" -" .expect(\"Failed to register service\");\n" -" binder::ProcessState::join_thread_pool()\n" -"}\n" -"```" +#: src/android/aidl/server.md:8 src/android/aidl/client.md:8 +msgid "//! Birthday service.\n" msgstr "" -#: src/android/aidl/server.md:30 -msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"birthday_server\",\n" -" crate_name: \"birthday_server\",\n" -" srcs: [\"src/server.rs\"],\n" -" rustlibs: [\n" -" \"com.example.birthdayservice-rust\",\n" -" \"libbinder_rs\",\n" -" \"libbirthdayservice\",\n" -" ],\n" -" prefer_rlib: true,\n" -"}\n" -"```" +#: src/android/aidl/server.md:14 +msgid "/// Entry point for birthday service.\n" +msgstr "" + +#: src/android/aidl/server.md:23 +msgid "\"Failed to register service\"" msgstr "" +#: src/android/aidl/server.md:32 src/android/aidl/server.md:33 +#, fuzzy +#| msgid "_birthday_service/src/lib.rs_:" +msgid "\"birthday_server\"" +msgstr "_birthday_service/src/lib.rs_:" + +#: src/android/aidl/server.md:34 +#, fuzzy +#| msgid "`src/bin/server.rs`:" +msgid "\"src/server.rs\"" +msgstr "`src/bin/server.rs`:" + #: src/android/aidl/deploy.md:3 msgid "We can now build, push, and start the service:" msgstr "Ahora podemos crear, insertar e iniciar el servicio:" @@ -13494,46 +11686,10 @@ msgstr "" msgid "In another terminal, check that the service runs:" msgstr "Comprueba que el servicio funciona en otra terminal:" -#: src/android/aidl/deploy.md:13 -msgid "" -"```shell\n" -"adb shell service check birthdayservice\n" -"```" -msgstr "" - -#: src/android/aidl/deploy.md:17 -msgid "" -"```text\n" -"Service birthdayservice: found\n" -"```" -msgstr "" - #: src/android/aidl/deploy.md:21 msgid "You can also call the service with `service call`:" msgstr "También puedes llamar al servicio con `service call`:" -#: src/android/aidl/deploy.md:23 -msgid "" -"```shell\n" -"adb shell service call birthdayservice 1 s16 Bob i32 24\n" -"```" -msgstr "" - -#: src/android/aidl/deploy.md:27 -msgid "" -"```text\n" -"Result: Parcel(\n" -" 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" -" 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" -" 0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'\n" -" 0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'\n" -" 0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'\n" -" 0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'\n" -" 0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'\n" -" 0x00000070: 00210073 00000000 's.!..... ')\n" -"```" -msgstr "" - #: src/android/aidl/client.md:1 msgid "AIDL Client" msgstr "Cliente de AIDL" @@ -13547,58 +11703,34 @@ msgstr "" msgid "_birthday_service/src/client.rs_:" msgstr "_birthday_service/src/client.rs_:" -#: src/android/aidl/client.md:7 -msgid "" -"```rust,ignore\n" -"//! Birthday service.\n" -"use com_example_birthdayservice::aidl::com::example::birthdayservice::" -"IBirthdayService::IBirthdayService;\n" -"use com_example_birthdayservice::binder;\n" -"\n" -"const SERVICE_IDENTIFIER: &str = \"birthdayservice\";\n" -"\n" -"/// Connect to the BirthdayService.\n" -"pub fn connect() -> Result, binder::" -"StatusCode> {\n" -" binder::get_interface(SERVICE_IDENTIFIER)\n" -"}\n" -"\n" -"/// Call the birthday service.\n" -"fn main() -> Result<(), binder::Status> {\n" -" let name = std::env::args()\n" -" .nth(1)\n" -" .unwrap_or_else(|| String::from(\"Bob\"));\n" -" let years = std::env::args()\n" -" .nth(2)\n" -" .and_then(|arg| arg.parse::().ok())\n" -" .unwrap_or(42);\n" -"\n" -" binder::ProcessState::start_thread_pool();\n" -" let service = connect().expect(\"Failed to connect to " -"BirthdayService\");\n" -" let msg = service.wishHappyBirthday(&name, years)?;\n" -" println!(\"{msg}\");\n" -" Ok(())\n" -"}\n" -"```" +#: src/android/aidl/client.md:13 +msgid "/// Connect to the BirthdayService.\n" msgstr "" -#: src/android/aidl/client.md:39 -msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"birthday_client\",\n" -" crate_name: \"birthday_client\",\n" -" srcs: [\"src/client.rs\"],\n" -" rustlibs: [\n" -" \"com.example.birthdayservice-rust\",\n" -" \"libbinder_rs\",\n" -" ],\n" -" prefer_rlib: true,\n" -"}\n" -"```" +#: src/android/aidl/client.md:18 +msgid "/// Call the birthday service.\n" +msgstr "" + +#: src/android/aidl/client.md:30 +msgid "\"Failed to connect to BirthdayService\"" msgstr "" +#: src/android/aidl/client.md:32 +msgid "\"{msg}\"" +msgstr "" + +#: src/android/aidl/client.md:41 src/android/aidl/client.md:42 +#, fuzzy +#| msgid "_birthday_service/src/client.rs_:" +msgid "\"birthday_client\"" +msgstr "_birthday_service/src/client.rs_:" + +#: src/android/aidl/client.md:43 +#, fuzzy +#| msgid "`src/bin/client.rs`:" +msgid "\"src/client.rs\"" +msgstr "`src/bin/client.rs`:" + #: src/android/aidl/client.md:52 msgid "Notice that the client does not depend on `libbirthdayservice`." msgstr "Ten en cuenta que el cliente no depende de `libbirthdayservice`." @@ -13617,13 +11749,6 @@ msgid "" "```" msgstr "" -#: src/android/aidl/client.md:62 -msgid "" -"```text\n" -"Happy Birthday Charlie, congratulations with the 60 years!\n" -"```" -msgstr "" - #: src/android/aidl/changing.md:3 msgid "" "Let us extend the API with more functionality: we want to let clients " @@ -13632,19 +11757,6 @@ msgstr "" "Ampliemos la API con más funciones. Queremos que los clientes puedan indicar " "una lista de líneas para la tarjeta de cumpleaños:" -#: src/android/aidl/changing.md:6 -msgid "" -"```java\n" -"package com.example.birthdayservice;\n" -"\n" -"/** Birthday service interface. */\n" -"interface IBirthdayService {\n" -" /** Generate a Happy Birthday message. */\n" -" String wishHappyBirthday(String name, int years, in String[] text);\n" -"}\n" -"```" -msgstr "" - #: src/android/logging.md:3 msgid "" "You should use the `log` crate to automatically log to `logcat` (on-device) " @@ -13657,46 +11769,46 @@ msgstr "" msgid "_hello_rust_logs/Android.bp_:" msgstr "_hello_rust_logs/Android.bp_:" -#: src/android/logging.md:8 -msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"hello_rust_logs\",\n" -" crate_name: \"hello_rust_logs\",\n" -" srcs: [\"src/main.rs\"],\n" -" rustlibs: [\n" -" \"liblog_rust\",\n" -" \"liblogger\",\n" -" ],\n" -" prefer_rlib: true,\n" -" host_supported: true,\n" -"}\n" -"```" +#: src/android/logging.md:10 src/android/logging.md:11 +#, fuzzy +#| msgid "_hello_rust_logs/Android.bp_:" +msgid "\"hello_rust_logs\"" +msgstr "_hello_rust_logs/Android.bp_:" + +#: src/android/logging.md:14 +msgid "\"liblog_rust\"" +msgstr "" + +#: src/android/logging.md:15 +msgid "\"liblogger\"" msgstr "" #: src/android/logging.md:22 msgid "_hello_rust_logs/src/main.rs_:" msgstr "_hello_rust_logs/src/main.rs_:" -#: src/android/logging.md:24 -msgid "" -"```rust,ignore\n" -"//! Rust logging demo.\n" -"\n" -"use log::{debug, error, info};\n" -"\n" -"/// Logs a greeting.\n" -"fn main() {\n" -" logger::init(\n" -" logger::Config::default()\n" -" .with_tag_on_device(\"rust\")\n" -" .with_min_level(log::Level::Trace),\n" -" );\n" -" debug!(\"Starting program.\");\n" -" info!(\"Things are going fine.\");\n" -" error!(\"Something went wrong!\");\n" -"}\n" -"```" +#: src/android/logging.md:25 +msgid "//! Rust logging demo.\n" +msgstr "" + +#: src/android/logging.md:28 +msgid "/// Logs a greeting.\n" +msgstr "" + +#: src/android/logging.md:33 +msgid "\"rust\"" +msgstr "" + +#: src/android/logging.md:36 +msgid "\"Starting program.\"" +msgstr "" + +#: src/android/logging.md:37 +msgid "\"Things are going fine.\"" +msgstr "" + +#: src/android/logging.md:38 +msgid "\"Something went wrong!\"" msgstr "" #: src/android/logging.md:42 src/android/interoperability/with-c/bindgen.md:98 @@ -13718,24 +11830,6 @@ msgstr "" msgid "The logs show up in `adb logcat`:" msgstr "Los registros se muestran en `adb logcat`:" -#: src/android/logging.md:52 -msgid "" -"```shell\n" -"adb logcat -s rust\n" -"```" -msgstr "" - -#: src/android/logging.md:56 -msgid "" -"```text\n" -"09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.\n" -"09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going " -"fine.\n" -"09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went " -"wrong!\n" -"```" -msgstr "" - #: src/android/interoperability.md:3 msgid "" "Rust has excellent support for interoperability with other languages. This " @@ -13776,19 +11870,8 @@ msgstr "" msgid "You can do it by hand if you want:" msgstr "Si quieres, puedes hacerlo de forma manual:" -#: src/android/interoperability/with-c.md:8 -msgid "" -"```rust\n" -"extern \"C\" {\n" -" fn abs(x: i32) -> i32;\n" -"}\n" -"\n" -"fn main() {\n" -" let x = -42;\n" -" let abs_x = unsafe { abs(x) };\n" -" println!(\"{x}, {abs_x}\");\n" -"}\n" -"```" +#: src/android/interoperability/with-c.md:16 +msgid "\"{x}, {abs_x}\"" msgstr "" #: src/android/interoperability/with-c.md:20 @@ -13832,35 +11915,26 @@ msgstr "En primer lugar, crea una biblioteca de C pequeña:" msgid "_interoperability/bindgen/libbirthday.h_:" msgstr "_interoperability/bindgen/libbirthday.h_:" -#: src/android/interoperability/with-c/bindgen.md:10 -msgid "" -"```c\n" -"typedef struct card {\n" -" const char* name;\n" -" int years;\n" -"} card;\n" -"\n" -"void print_card(const card* card);\n" -"```" -msgstr "" - #: src/android/interoperability/with-c/bindgen.md:19 msgid "_interoperability/bindgen/libbirthday.c_:" msgstr "_interoperability/bindgen/libbirthday.c_:" -#: src/android/interoperability/with-c/bindgen.md:21 -msgid "" -"```c\n" -"#include \n" -"#include \"libbirthday.h\"\n" -"\n" -"void print_card(const card* card) {\n" -" printf(\"+--------------\\n\");\n" -" printf(\"| Happy Birthday %s!\\n\", card->name);\n" -" printf(\"| Congratulations with the %i years!\\n\", card->years);\n" -" printf(\"+--------------\\n\");\n" -"}\n" -"```" +#: src/android/interoperability/with-c/bindgen.md:23 +#: src/android/interoperability/with-c/bindgen.md:50 +msgid "\"libbirthday.h\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:26 +#: src/android/interoperability/with-c/bindgen.md:29 +msgid "\"+--------------\\n\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:27 +msgid "\"| Happy Birthday %s!\\n\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:28 +msgid "\"| Congratulations with the %i years!\\n\"" msgstr "" #: src/android/interoperability/with-c/bindgen.md:33 @@ -13874,14 +11948,13 @@ msgstr "Añade lo siguiente a tu archivo `Android.bp`:" msgid "_interoperability/bindgen/Android.bp_:" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:37 -msgid "" -"```javascript\n" -"cc_library {\n" -" name: \"libbirthday\",\n" -" srcs: [\"libbirthday.c\"],\n" -"}\n" -"```" +#: src/android/interoperability/with-c/bindgen.md:39 +#: src/android/interoperability/with-c/bindgen.md:63 +msgid "\"libbirthday\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:40 +msgid "\"libbirthday.c\"" msgstr "" #: src/android/interoperability/with-c/bindgen.md:44 @@ -13896,67 +11969,49 @@ msgstr "" msgid "_interoperability/bindgen/libbirthday_wrapper.h_:" msgstr "_interoperability/bindgen/libbirthday_wrapper.h_:" -#: src/android/interoperability/with-c/bindgen.md:49 -msgid "" -"```c\n" -"#include \"libbirthday.h\"\n" -"```" -msgstr "" - #: src/android/interoperability/with-c/bindgen.md:53 msgid "You can now auto-generate the bindings:" msgstr "Ahora puedes generar automáticamente los enlaces:" -#: src/android/interoperability/with-c/bindgen.md:57 -msgid "" -"```javascript\n" -"rust_bindgen {\n" -" name: \"libbirthday_bindgen\",\n" -" crate_name: \"birthday_bindgen\",\n" -" wrapper_src: \"libbirthday_wrapper.h\",\n" -" source_stem: \"bindings\",\n" -" static_libs: [\"libbirthday\"],\n" -"}\n" -"```" +#: src/android/interoperability/with-c/bindgen.md:59 +#: src/android/interoperability/with-c/bindgen.md:75 +msgid "\"libbirthday_bindgen\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:60 +#, fuzzy +#| msgid "`rust_bindgen`" +msgid "\"birthday_bindgen\"" +msgstr "`rust_bindgen`" + +#: src/android/interoperability/with-c/bindgen.md:61 +msgid "\"libbirthday_wrapper.h\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:62 +msgid "\"bindings\"" msgstr "" #: src/android/interoperability/with-c/bindgen.md:67 msgid "Finally, we can use the bindings in our Rust program:" msgstr "Por último, podemos utilizar los enlaces de nuestro programa de Rust:" -#: src/android/interoperability/with-c/bindgen.md:71 -msgid "" -"```javascript\n" -"rust_binary {\n" -" name: \"print_birthday_card\",\n" -" srcs: [\"main.rs\"],\n" -" rustlibs: [\"libbirthday_bindgen\"],\n" -"}\n" -"```" +#: src/android/interoperability/with-c/bindgen.md:73 +msgid "\"print_birthday_card\"" msgstr "" +#: src/android/interoperability/with-c/bindgen.md:74 +#, fuzzy +#| msgid "`main.rs`:" +msgid "\"main.rs\"" +msgstr "`main.rs`:" + #: src/android/interoperability/with-c/bindgen.md:79 msgid "_interoperability/bindgen/main.rs_:" msgstr "_interoperability/bindgen/main.rs_:" -#: src/android/interoperability/with-c/bindgen.md:81 -msgid "" -"```rust,compile_fail\n" -"//! Bindgen demo.\n" -"\n" -"use birthday_bindgen::{card, print_card};\n" -"\n" -"fn main() {\n" -" let name = std::ffi::CString::new(\"Peter\").unwrap();\n" -" let card = card {\n" -" name: name.as_ptr(),\n" -" years: 42,\n" -" };\n" -" unsafe {\n" -" print_card(&card as *const card);\n" -" }\n" -"}\n" -"```" +#: src/android/interoperability/with-c/bindgen.md:82 +msgid "//! Bindgen demo.\n" msgstr "" #: src/android/interoperability/with-c/bindgen.md:100 @@ -13975,26 +12030,26 @@ msgstr "" "Por último, podemos ejecutar pruebas generadas automáticamente para " "comprobar que los enlaces funcionan:" -#: src/android/interoperability/with-c/bindgen.md:110 -msgid "" -"```javascript\n" -"rust_test {\n" -" name: \"libbirthday_bindgen_test\",\n" -" srcs: [\":libbirthday_bindgen\"],\n" -" crate_name: \"libbirthday_bindgen_test\",\n" -" test_suites: [\"general-tests\"],\n" -" auto_gen_config: true,\n" -" clippy_lints: \"none\", // Generated file, skip linting\n" -" lints: \"none\",\n" -"}\n" -"```" +#: src/android/interoperability/with-c/bindgen.md:112 +#: src/android/interoperability/with-c/bindgen.md:114 +msgid "\"libbirthday_bindgen_test\"" msgstr "" -#: src/android/interoperability/with-c/bindgen.md:122 -msgid "" -"```shell\n" -"atest libbirthday_bindgen_test\n" -"```" +#: src/android/interoperability/with-c/bindgen.md:113 +msgid "\":libbirthday_bindgen\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:115 +msgid "\"general-tests\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:117 +#: src/android/interoperability/with-c/bindgen.md:118 +msgid "\"none\"" +msgstr "" + +#: src/android/interoperability/with-c/bindgen.md:117 +msgid "// Generated file, skip linting\n" msgstr "" #: src/android/interoperability/with-c/rust.md:1 @@ -14009,58 +12064,41 @@ msgstr "Es fácil exportar las funciones y los tipos de Rust a C:" msgid "_interoperability/rust/libanalyze/analyze.rs_" msgstr "_interoperability/rust/libanalyze/analyze.rs_" -#: src/android/interoperability/with-c/rust.md:7 -msgid "" -"```rust,editable\n" -"//! Rust FFI demo.\n" -"#![deny(improper_ctypes_definitions)]\n" -"\n" -"use std::os::raw::c_int;\n" -"\n" -"/// Analyze the numbers.\n" -"#[no_mangle]\n" -"pub extern \"C\" fn analyze_numbers(x: c_int, y: c_int) {\n" -" if x < y {\n" -" println!(\"x ({x}) is smallest!\");\n" -" } else {\n" -" println!(\"y ({y}) is probably larger than x ({x})\");\n" -" }\n" -"}\n" -"```" +#: src/android/interoperability/with-c/rust.md:8 +msgid "//! Rust FFI demo.\n" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:12 +msgid "/// Analyze the numbers.\n" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:17 +msgid "\"x ({x}) is smallest!\"" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:19 +msgid "\"y ({y}) is probably larger than x ({x})\"" msgstr "" #: src/android/interoperability/with-c/rust.md:24 msgid "_interoperability/rust/libanalyze/analyze.h_" msgstr "_interoperability/rust/libanalyze/analyze.h_" -#: src/android/interoperability/with-c/rust.md:26 -msgid "" -"```c\n" -"#ifndef ANALYSE_H\n" -"#define ANALYSE_H\n" -"\n" -"extern \"C\" {\n" -"void analyze_numbers(int x, int y);\n" -"}\n" -"\n" -"#endif\n" -"```" -msgstr "" - #: src/android/interoperability/with-c/rust.md:37 msgid "_interoperability/rust/libanalyze/Android.bp_" msgstr "_interoperability/rust/libanalyze/Android.bp_" -#: src/android/interoperability/with-c/rust.md:39 -msgid "" -"```javascript\n" -"rust_ffi {\n" -" name: \"libanalyze_ffi\",\n" -" crate_name: \"analyze_ffi\",\n" -" srcs: [\"analyze.rs\"],\n" -" include_dirs: [\".\"],\n" -"}\n" -"```" +#: src/android/interoperability/with-c/rust.md:41 +#: src/android/interoperability/with-c/rust.md:68 +msgid "\"libanalyze_ffi\"" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:42 +msgid "\"analyze_ffi\"" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:43 +msgid "\"analyze.rs\"" msgstr "" #: src/android/interoperability/with-c/rust.md:48 @@ -14071,32 +12109,20 @@ msgstr "Ahora podemos llamarlo desde un binario de C:" msgid "_interoperability/rust/analyze/main.c_" msgstr "_interoperability/rust/analyze/main.c_" -#: src/android/interoperability/with-c/rust.md:52 -msgid "" -"```c\n" -"#include \"analyze.h\"\n" -"\n" -"int main() {\n" -" analyze_numbers(10, 20);\n" -" analyze_numbers(123, 123);\n" -" return 0;\n" -"}\n" -"```" +#: src/android/interoperability/with-c/rust.md:53 +msgid "\"analyze.h\"" msgstr "" #: src/android/interoperability/with-c/rust.md:62 msgid "_interoperability/rust/analyze/Android.bp_" msgstr "_interoperability/rust/analyze/Android.bp_" -#: src/android/interoperability/with-c/rust.md:64 -msgid "" -"```javascript\n" -"cc_binary {\n" -" name: \"analyze_numbers\",\n" -" srcs: [\"main.c\"],\n" -" static_libs: [\"libanalyze_ffi\"],\n" -"}\n" -"```" +#: src/android/interoperability/with-c/rust.md:66 +msgid "\"analyze_numbers\"" +msgstr "" + +#: src/android/interoperability/with-c/rust.md:67 +msgid "\"main.c\"" msgstr "" #: src/android/interoperability/with-c/rust.md:75 @@ -14120,6 +12146,10 @@ msgstr "" "utilizar `#[export_name = \"some_name\"]` para especificar el nombre que " "quieras." +#: src/android/interoperability/cpp.md:1 +msgid "With C++" +msgstr "Con C++" + #: src/android/interoperability/cpp.md:3 msgid "" "The [CXX crate](https://cxx.rs/) makes it possible to do safe " @@ -14210,28 +12240,20 @@ msgstr "En primer lugar, creamos una función de Rust para exportar a Java:" msgid "_interoperability/java/src/lib.rs_:" msgstr "_interoperability/java/src/lib.rs_:" -#: src/android/interoperability/java.md:11 -msgid "" -"```rust,compile_fail\n" -"//! Rust <-> Java FFI demo.\n" -"\n" -"use jni::objects::{JClass, JString};\n" -"use jni::sys::jstring;\n" -"use jni::JNIEnv;\n" -"\n" -"/// HelloWorld::hello method implementation.\n" -"#[no_mangle]\n" -"pub extern \"system\" fn Java_HelloWorld_hello(\n" -" env: JNIEnv,\n" -" _class: JClass,\n" -" name: JString,\n" -") -> jstring {\n" -" let input: String = env.get_string(name).unwrap().into();\n" -" let greeting = format!(\"Hello, {input}!\");\n" -" let output = env.new_string(greeting).unwrap();\n" -" output.into_inner()\n" -"}\n" -"```" +#: src/android/interoperability/java.md:12 +msgid "//! Rust <-> Java FFI demo.\n" +msgstr "" + +#: src/android/interoperability/java.md:17 +msgid "/// HelloWorld::hello method implementation.\n" +msgstr "" + +#: src/android/interoperability/java.md:20 +msgid "\"system\"" +msgstr "" + +#: src/android/interoperability/java.md:26 +msgid "\"Hello, {input}!\"" msgstr "" #: src/android/interoperability/java.md:32 @@ -14239,16 +12261,18 @@ msgstr "" msgid "_interoperability/java/Android.bp_:" msgstr "_interoperability/java/Android.bp_:" -#: src/android/interoperability/java.md:34 -msgid "" -"```javascript\n" -"rust_ffi_shared {\n" -" name: \"libhello_jni\",\n" -" crate_name: \"hello_jni\",\n" -" srcs: [\"src/lib.rs\"],\n" -" rustlibs: [\"libjni\"],\n" -"}\n" -"```" +#: src/android/interoperability/java.md:36 +#: src/android/interoperability/java.md:69 +msgid "\"libhello_jni\"" +msgstr "" + +#: src/android/interoperability/java.md:37 +#: src/android/interoperability/java.md:52 +msgid "\"hello_jni\"" +msgstr "" + +#: src/android/interoperability/java.md:39 +msgid "\"libjni\"" msgstr "" #: src/android/interoperability/java.md:43 @@ -14259,49 +12283,26 @@ msgstr "Por último, podemos llamar a esta función desde Java:" msgid "_interoperability/java/HelloWorld.java_:" msgstr "_interoperability/java/HelloWorld.java_:" -#: src/android/interoperability/java.md:47 -msgid "" -"```java\n" -"class HelloWorld {\n" -" private static native String hello(String name);\n" -"\n" -" static {\n" -" System.loadLibrary(\"hello_jni\");\n" -" }\n" -"\n" -" public static void main(String[] args) {\n" -" String output = HelloWorld.hello(\"Alice\");\n" -" System.out.println(output);\n" -" }\n" -"}\n" -"```" +#: src/android/interoperability/java.md:66 +msgid "\"helloworld_jni\"" msgstr "" -#: src/android/interoperability/java.md:64 -msgid "" -"```javascript\n" -"java_binary {\n" -" name: \"helloworld_jni\",\n" -" srcs: [\"HelloWorld.java\"],\n" -" main_class: \"HelloWorld\",\n" -" required: [\"libhello_jni\"],\n" -"}\n" -"```" -msgstr "" +#: src/android/interoperability/java.md:67 +#, fuzzy +#| msgid "Hello World!" +msgid "\"HelloWorld.java\"" +msgstr "¡Hola, mundo!" + +#: src/android/interoperability/java.md:68 +#, fuzzy +#| msgid "Hello World!" +msgid "\"HelloWorld\"" +msgstr "¡Hola, mundo!" #: src/android/interoperability/java.md:73 msgid "Finally, you can build, sync, and run the binary:" msgstr "Ahora puedes compilar, sincronizar y ejecutar el binario:" -#: src/android/interoperability/java.md:75 -msgid "" -"```shell\n" -"m helloworld_jni\n" -"adb sync # requires adb root && adb remount\n" -"adb shell /system/bin/helloworld_jni\n" -"```" -msgstr "" - #: src/exercises/android/morning.md:3 msgid "" "This is a group exercise: We will look at one of the projects you work with " @@ -14388,74 +12389,16 @@ msgstr "" "Para empezar, instala algunas de las herramientas que necesitarás más " "adelante. En gLinux o Debian:" -#: src/bare-metal.md:22 -msgid "" -"```bash\n" -"sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom pkg-" -"config qemu-system-arm\n" -"rustup update\n" -"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" -"rustup component add llvm-tools-preview\n" -"cargo install cargo-binutils cargo-embed\n" -"```" -msgstr "" -"```bash\n" -"sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom pkg-" -"config qemu-system-arm\n" -"rustup update\n" -"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" -"rustup component add llvm-tools-preview\n" -"cargo install cargo-binutils cargo-embed\n" -"```" - #: src/bare-metal.md:30 msgid "" "And give users in the `plugdev` group access to the micro:bit programmer:" msgstr "" "Permite a los usuarios del grupo `plugdev` acceder al programador micro:bit:" -#: src/bare-metal.md:32 -msgid "" -"```bash\n" -"echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", " -"GROUP=\"plugdev\"' |\\\n" -" sudo tee /etc/udev/rules.d/50-microbit.rules\n" -"sudo udevadm control --reload-rules\n" -"```" -msgstr "" -"```bash\n" -"echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", " -"GROUP=\"plugdev\"' |\\\n" -" sudo tee /etc/udev/rules.d/50-microbit.rules\n" -"sudo udevadm control --reload-rules\n" -"```" - -#: src/bare-metal.md:38 +#: src/bare-metal.md:38 src/bare-metal/microcontrollers/debugging.md:27 msgid "On MacOS:" msgstr "En MacOS:" -#: src/bare-metal.md:40 -msgid "" -"```bash\n" -"xcode-select --install\n" -"brew install gdb picocom qemu\n" -"brew install --cask gcc-aarch64-embedded\n" -"rustup update\n" -"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" -"rustup component add llvm-tools-preview\n" -"cargo install cargo-binutils cargo-embed\n" -"```" -msgstr "" -"```bash\n" -"xcode-select --install\n" -"brew install gdb picocom qemu\n" -"brew install --cask gcc-aarch64-embedded\n" -"rustup update\n" -"rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" -"rustup component add llvm-tools-preview\n" -"cargo install cargo-binutils cargo-embed\n" -"```" - #: src/bare-metal/no_std.md:1 msgid "`no_std`" msgstr "`no_std`" @@ -14568,32 +12511,6 @@ msgstr "`std` vuelve a exportar el contenido de `core` y `alloc`." msgid "A minimal `no_std` program" msgstr "Un programa `no_std` mínimo" -#: src/bare-metal/minimal.md:3 -msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"use core::panic::PanicInfo;\n" -"\n" -"#[panic_handler]\n" -"fn panic(_panic: &PanicInfo) -> ! {\n" -" loop {}\n" -"}\n" -"```" -msgstr "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"use core::panic::PanicInfo;\n" -"\n" -"#[panic_handler]\n" -"fn panic(_panic: &PanicInfo) -> ! {\n" -" loop {}\n" -"}\n" -"```" - #: src/bare-metal/minimal.md:17 msgid "This will compile to an empty binary." msgstr "Se compilará en un binario vacío." @@ -14635,71 +12552,24 @@ msgstr "" "Para utilizar `alloc`, debes implementar un [asignador global (de _heap_)]" "(https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html)." -#: src/bare-metal/alloc.md:6 +#: src/bare-metal/alloc.md:23 msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate alloc;\n" -"extern crate panic_halt as _;\n" -"\n" -"use alloc::string::ToString;\n" -"use alloc::vec::Vec;\n" -"use buddy_system_allocator::LockedHeap;\n" -"\n" -"#[global_allocator]\n" -"static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();\n" -"\n" -"static mut HEAP: [u8; 65536] = [0; 65536];\n" -"\n" -"pub fn entry() {\n" -" // Safe because `HEAP` is only used here and `entry` is only called " -"once.\n" -" unsafe {\n" -" // Give the allocator some memory to allocate.\n" -" HEAP_ALLOCATOR\n" -" .lock()\n" -" .init(HEAP.as_mut_ptr() as usize, HEAP.len());\n" -" }\n" -"\n" -" // Now we can do things that require heap allocation.\n" -" let mut v = Vec::new();\n" -" v.push(\"A string\".to_string());\n" -"}\n" -"```" +"// Safe because `HEAP` is only used here and `entry` is only called once.\n" +msgstr "" + +#: src/bare-metal/alloc.md:25 +msgid "// Give the allocator some memory to allocate.\n" +msgstr "" + +#: src/bare-metal/alloc.md:31 +msgid "// Now we can do things that require heap allocation.\n" msgstr "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate alloc;\n" -"extern crate panic_halt as _;\n" -"\n" -"use alloc::string::ToString;\n" -"use alloc::vec::Vec;\n" -"use buddy_system_allocator::LockedHeap;\n" -"\n" -"#[global_allocator]\n" -"static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();\n" -"\n" -"static mut HEAP: [u8; 65536] = [0; 65536];\n" -"\n" -"pub fn entry() {\n" -" // Safe because `HEAP` is only used here and `entry` is only called " -"once.\n" -" unsafe {\n" -" // Give the allocator some memory to allocate.\n" -" HEAP_ALLOCATOR\n" -" .lock()\n" -" .init(HEAP.as_mut_ptr() as usize, HEAP.len());\n" -" }\n" -"\n" -" // Ahora podemos hacer cosas que requieran asignación de _heap_.\n" -" let mut v = Vec::new();\n" -" v.push(\"A string\".to_string());\n" -"}\n" -"```" + +#: src/bare-metal/alloc.md:33 +#, fuzzy +#| msgid "String" +msgid "\"A string\"" +msgstr "String" #: src/bare-metal/alloc.md:39 msgid "" @@ -14752,25 +12622,6 @@ msgstr "" "El crate `cortex_m_rt` proporciona (entre otras cosas) un controlador de " "reinicio para microcontroladores Cortex M." -#: src/bare-metal/microcontrollers.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate panic_halt as _;\n" -"\n" -"mod interrupts;\n" -"\n" -"use cortex_m_rt::entry;\n" -"\n" -"#[entry]\n" -"fn main() -> ! {\n" -" loop {}\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers.md:21 msgid "" "Next we'll look at how to access peripherals, with increasing levels of " @@ -14800,69 +12651,35 @@ msgstr "" "S asignada a la memoria. Vamos a probar a encender un LED en nuestro micro:" "bit:" -#: src/bare-metal/microcontrollers/mmio.md:6 +#: src/bare-metal/microcontrollers/mmio.md:16 +msgid "/// GPIO port 0 peripheral address\n" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:19 +msgid "// GPIO peripheral offsets\n" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:24 +msgid "// PIN_CNF fields\n" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:34 +#: src/bare-metal/microcontrollers/pacs.md:21 +#: src/bare-metal/microcontrollers/hals.md:25 +msgid "// Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:37 +#: src/bare-metal/microcontrollers/mmio.md:51 msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate panic_halt as _;\n" -"\n" -"mod interrupts;\n" -"\n" -"use core::mem::size_of;\n" -"use cortex_m_rt::entry;\n" -"\n" -"/// GPIO port 0 peripheral address\n" -"const GPIO_P0: usize = 0x5000_0000;\n" -"\n" -"// GPIO peripheral offsets\n" -"const PIN_CNF: usize = 0x700;\n" -"const OUTSET: usize = 0x508;\n" -"const OUTCLR: usize = 0x50c;\n" -"\n" -"// PIN_CNF fields\n" -"const DIR_OUTPUT: u32 = 0x1;\n" -"const INPUT_DISCONNECT: u32 = 0x1 << 1;\n" -"const PULL_DISABLED: u32 = 0x0 << 2;\n" -"const DRIVE_S0S1: u32 = 0x0 << 8;\n" -"const SENSE_DISABLED: u32 = 0x0 << 16;\n" -"\n" -"#[entry]\n" -"fn main() -> ! {\n" -" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" -" let pin_cnf_21 = (GPIO_P0 + PIN_CNF + 21 * size_of::()) as *mut " -"u32;\n" -" let pin_cnf_28 = (GPIO_P0 + PIN_CNF + 28 * size_of::()) as *mut " -"u32;\n" -" // Safe because the pointers are to valid peripheral control registers, " -"and\n" -" // no aliases exist.\n" -" unsafe {\n" -" pin_cnf_21.write_volatile(\n" -" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | " -"SENSE_DISABLED,\n" -" );\n" -" pin_cnf_28.write_volatile(\n" -" DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | " -"SENSE_DISABLED,\n" -" );\n" -" }\n" -"\n" -" // Set pin 28 low and pin 21 high to turn the LED on.\n" -" let gpio0_outset = (GPIO_P0 + OUTSET) as *mut u32;\n" -" let gpio0_outclr = (GPIO_P0 + OUTCLR) as *mut u32;\n" -" // Safe because the pointers are to valid peripheral control registers, " -"and\n" +"// Safe because the pointers are to valid peripheral control registers, and\n" " // no aliases exist.\n" -" unsafe {\n" -" gpio0_outclr.write_volatile(1 << 28);\n" -" gpio0_outset.write_volatile(1 << 21);\n" -" }\n" -"\n" -" loop {}\n" -"}\n" -"```" +msgstr "" + +#: src/bare-metal/microcontrollers/mmio.md:48 +#: src/bare-metal/microcontrollers/pacs.md:39 +#: src/bare-metal/microcontrollers/hals.md:29 +msgid "// Set pin 28 low and pin 21 high to turn the LED on.\n" msgstr "" #: src/bare-metal/microcontrollers/mmio.md:64 @@ -14880,13 +12697,6 @@ msgstr "" msgid "Run the example with:" msgstr "Ejecuta el ejemplo con:" -#: src/bare-metal/microcontrollers/mmio.md:68 -msgid "" -"```sh\n" -"cargo embed --bin mmio\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/pacs.md:1 msgid "Peripheral Access Crates" msgstr "Crates de Acceso Periférico" @@ -14902,49 +12712,6 @@ msgstr "" "de archivos [CMSIS-SVD](https://www.keil.com/pack/doc/CMSIS/SVD/html/index." "html)." -#: src/bare-metal/microcontrollers/pacs.md:7 -msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate panic_halt as _;\n" -"\n" -"use cortex_m_rt::entry;\n" -"use nrf52833_pac::Peripherals;\n" -"\n" -"#[entry]\n" -"fn main() -> ! {\n" -" let p = Peripherals::take().unwrap();\n" -" let gpio0 = p.P0;\n" -"\n" -" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" -" gpio0.pin_cnf[21].write(|w| {\n" -" w.dir().output();\n" -" w.input().disconnect();\n" -" w.pull().disabled();\n" -" w.drive().s0s1();\n" -" w.sense().disabled();\n" -" w\n" -" });\n" -" gpio0.pin_cnf[28].write(|w| {\n" -" w.dir().output();\n" -" w.input().disconnect();\n" -" w.pull().disabled();\n" -" w.drive().s0s1();\n" -" w.sense().disabled();\n" -" w\n" -" });\n" -"\n" -" // Set pin 28 low and pin 21 high to turn the LED on.\n" -" gpio0.outclr.write(|w| w.pin28().clear());\n" -" gpio0.outset.write(|w| w.pin21().set());\n" -"\n" -" loop {}\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/pacs.md:49 msgid "" "SVD (System View Description) files are XML files typically provided by " @@ -14984,13 +12751,6 @@ msgstr "" "Si instalas `cargo install cargo-binutils` puedes ejecutar `cargo objdump --" "bin pac -- -d --no-show-raw-insn` para ver el binario resultante." -#: src/bare-metal/microcontrollers/pacs.md:61 -msgid "" -"```sh\n" -"cargo embed --bin pac\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/hals.md:1 msgid "HAL crates" msgstr "Crates HAL" @@ -15007,37 +12767,8 @@ msgstr "" "alrededor de varios periféricos. Por lo general, implementan traits de " "[`embedded-hal`](https://crates.io/crates/embedded-hal)." -#: src/bare-metal/microcontrollers/hals.md:7 -msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate panic_halt as _;\n" -"\n" -"use cortex_m_rt::entry;\n" -"use nrf52833_hal::gpio::{p0, Level};\n" -"use nrf52833_hal::pac::Peripherals;\n" -"use nrf52833_hal::prelude::*;\n" -"\n" -"#[entry]\n" -"fn main() -> ! {\n" -" let p = Peripherals::take().unwrap();\n" -"\n" -" // Create HAL wrapper for GPIO port 0.\n" -" let gpio0 = p0::Parts::new(p.P0);\n" -"\n" -" // Configure GPIO 0 pins 21 and 28 as push-pull outputs.\n" -" let mut col1 = gpio0.p0_28.into_push_pull_output(Level::High);\n" -" let mut row1 = gpio0.p0_21.into_push_pull_output(Level::Low);\n" -"\n" -" // Set pin 28 low and pin 21 high to turn the LED on.\n" -" col1.set_low().unwrap();\n" -" row1.set_high().unwrap();\n" -"\n" -" loop {}\n" -"}\n" -"```" +#: src/bare-metal/microcontrollers/hals.md:22 +msgid "// Create HAL wrapper for GPIO port 0.\n" msgstr "" #: src/bare-metal/microcontrollers/hals.md:39 @@ -15054,13 +12785,6 @@ msgstr "" "Hay crates HAL para muchos dispositivos Cortex-M y RISC-V, incluidos varios " "microcontroladores STM32, GD32, nRF, NXP, MSP430, AVR y PIC." -#: src/bare-metal/microcontrollers/hals.md:45 -msgid "" -"```sh\n" -"cargo embed --bin hal\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/board-support.md:1 msgid "Board support crates" msgstr "Crates de compatibilidad de placa" @@ -15073,30 +12797,6 @@ msgstr "" "Los crates de compatibilidad de placa proporcionan un nivel adicional de " "envoltorio a una placa específica para mayor comodidad." -#: src/bare-metal/microcontrollers/board-support.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate panic_halt as _;\n" -"\n" -"use cortex_m_rt::entry;\n" -"use microbit::hal::prelude::*;\n" -"use microbit::Board;\n" -"\n" -"#[entry]\n" -"fn main() -> ! {\n" -" let mut board = Board::take().unwrap();\n" -"\n" -" board.display_pins.col1.set_low().unwrap();\n" -" board.display_pins.row1.set_high().unwrap();\n" -"\n" -" loop {}\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/board-support.md:28 msgid "" "In this case the board support crate is just providing more useful names, " @@ -15117,48 +12817,16 @@ msgstr "" msgid "`microbit-v2` includes a simple driver for the LED matrix." msgstr "`microbit-v2` incluye un controlador sencillo para la matriz de LED." -#: src/bare-metal/microcontrollers/board-support.md:36 -msgid "" -"```sh\n" -"cargo embed --bin board_support\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/type-state.md:1 msgid "The type state pattern" msgstr "El patrón de tipo de estado" -#: src/bare-metal/microcontrollers/type-state.md:3 -msgid "" -"```rust,editable,compile_fail\n" -"#[entry]\n" -"fn main() -> ! {\n" -" let p = Peripherals::take().unwrap();\n" -" let gpio0 = p0::Parts::new(p.P0);\n" -"\n" -" let pin: P0_01 = gpio0.p0_01;\n" -"\n" -" // let gpio0_01_again = gpio0.p0_01; // Error, moved.\n" -" let pin_input: P0_01> = pin.into_floating_input();\n" -" if pin_input.is_high().unwrap() {\n" -" // ...\n" -" }\n" -" let mut pin_output: P0_01> = pin_input\n" -" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, " -"Level::Low);\n" -" pin_output.set_high().unwrap();\n" -" // pin_input.is_high(); // Error, moved.\n" -"\n" -" let _pin2: P0_02> = gpio0\n" -" .p0_02\n" -" .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, " -"Level::Low);\n" -" let _pin3: P0_03> = gpio0.p0_03." -"into_push_pull_output(Level::Low);\n" -"\n" -" loop {}\n" -"}\n" -"```" +#: src/bare-metal/microcontrollers/type-state.md:11 +msgid "// let gpio0_01_again = gpio0.p0_01; // Error, moved.\n" +msgstr "" + +#: src/bare-metal/microcontrollers/type-state.md:19 +msgid "// pin_input.is_high(); // Error, moved.\n" msgstr "" #: src/bare-metal/microcontrollers/type-state.md:32 @@ -15281,43 +12949,29 @@ msgstr "" "integradas muy útil, como OpenOCD, pero mejor integrado." #: src/bare-metal/microcontrollers/probe-rs.md:6 -msgid "SWD" -msgstr "SWD" - -#: src/bare-metal/microcontrollers/probe-rs.md:6 -msgid " and JTAG via CMSIS-DAP, ST-Link and J-Link probes" +#, fuzzy +#| msgid " and JTAG via CMSIS-DAP, ST-Link and J-Link probes" +msgid "" +"SWD (Serial Wire Debug) and JTAG via CMSIS-DAP, ST-Link and J-Link probes" msgstr " y JTAG a través de comprobaciones CMSIS-DAP, ST-Link y J-Link" #: src/bare-metal/microcontrollers/probe-rs.md:7 -msgid "GDB stub and Microsoft " -msgstr "GDB stub y el servidor " - -#: src/bare-metal/microcontrollers/probe-rs.md:7 -msgid "DAP" -msgstr "DAP" - -#: src/bare-metal/microcontrollers/probe-rs.md:7 -msgid " server" -msgstr " de Microsoft" +msgid "GDB stub and Microsoft DAP (Debug Adapter Protocol) server" +msgstr "" #: src/bare-metal/microcontrollers/probe-rs.md:8 msgid "Cargo integration" msgstr "Integración de Cargo" #: src/bare-metal/microcontrollers/probe-rs.md:10 -msgid "`cargo-embed` is a cargo subcommand to build and flash binaries, log " -msgstr "" -"`cargo-embed` es un subcomando de Cargo para compilar e instalar binarios, " -"registrar salidas " - -#: src/bare-metal/microcontrollers/probe-rs.md:11 -msgid "RTT" -msgstr "TTR" - -#: src/bare-metal/microcontrollers/probe-rs.md:11 +#, fuzzy +#| msgid "" +#| " output and connect GDB. It's configured by an `Embed.toml` file in your " +#| "project directory." msgid "" -" output and connect GDB. It's configured by an `Embed.toml` file in your " -"project directory." +"`cargo-embed` is a cargo subcommand to build and flash binaries, log RTT " +"(Real Time Transfers) output and connect GDB. It's configured by an `Embed." +"toml` file in your project directory." msgstr "" " y conectar GDB. Se configura mediante un archivo `Embed.toml` en el " "directorio del proyecto." @@ -15382,59 +13036,27 @@ msgstr "" "circulares." #: src/bare-metal/microcontrollers/debugging.md:3 -msgid "Embed.toml:" +#, fuzzy +#| msgid "Embed.toml:" +msgid "_Embed.toml_:" msgstr "Embed.toml:" -#: src/bare-metal/microcontrollers/debugging.md:5 -msgid "" -"```toml\n" -"[default.general]\n" -"chip = \"nrf52833_xxAA\"\n" -"\n" -"[debug.gdb]\n" -"enabled = true\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/debugging.md:13 msgid "In one terminal under `src/bare-metal/microcontrollers/examples/`:" msgstr "En un terminal en `src/bare-metal/microcontrollers/examples/`:" -#: src/bare-metal/microcontrollers/debugging.md:15 -msgid "" -"```sh\n" -"cargo embed --bin board_support debug\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/debugging.md:19 msgid "In another terminal in the same directory:" msgstr "En otro terminal del mismo directorio:" #: src/bare-metal/microcontrollers/debugging.md:21 -msgid "" -"```sh\n" -"gdb-multiarch target/thumbv7em-none-eabihf/debug/board_support --eval-" -"command=\"target remote :1337\"\n" -"```" +msgid "On gLinux or Debian:" msgstr "" -#: src/bare-metal/microcontrollers/debugging.md:27 +#: src/bare-metal/microcontrollers/debugging.md:34 msgid "In GDB, try running:" msgstr "En GDB, prueba a ejecutar:" -#: src/bare-metal/microcontrollers/debugging.md:29 -msgid "" -"```gdb\n" -"b src/bin/board_support.rs:29\n" -"b src/bin/board_support.rs:30\n" -"b src/bin/board_support.rs:32\n" -"c\n" -"c\n" -"c\n" -"```" -msgstr "" - #: src/bare-metal/microcontrollers/other-projects.md:1 #: src/bare-metal/aps/other-projects.md:1 msgid "Other projects" @@ -15620,114 +13242,55 @@ msgstr "" "y busca los siguientes archivos en el directorio `compass`." #: src/exercises/bare-metal/compass.md:26 src/exercises/bare-metal/rtc.md:19 -msgid "`src/main.rs`:" +#, fuzzy +#| msgid "`src/main.rs`:" +msgid "_src/main.rs_:" msgstr "`src/main.rs`:" -#: src/exercises/bare-metal/compass.md:30 +#: src/exercises/bare-metal/compass.md:44 +#: src/exercises/bare-metal/solutions-morning.md:32 +msgid "// Configure serial port.\n" +msgstr "" + +#: src/exercises/bare-metal/compass.md:52 msgid "" -"```rust,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate panic_halt as _;\n" -"\n" -"use core::fmt::Write;\n" -"use cortex_m_rt::entry;\n" -"use microbit::{hal::uarte::{Baudrate, Parity, Uarte}, Board};\n" -"\n" -"#[entry]\n" -"fn main() -> ! {\n" -" let board = Board::take().unwrap();\n" -"\n" -" // Configure serial port.\n" -" let mut serial = Uarte::new(\n" -" board.UARTE0,\n" -" board.uart.into(),\n" -" Parity::EXCLUDED,\n" -" Baudrate::BAUD115200,\n" -" );\n" -"\n" -" // Set up the I2C controller and Inertial Measurement Unit.\n" +"// Set up the I2C controller and Inertial Measurement Unit.\n" " // TODO\n" -"\n" -" writeln!(serial, \"Ready.\").unwrap();\n" -"\n" -" loop {\n" -" // Read compass data and log it to the serial port.\n" -" // TODO\n" -" }\n" -"}\n" -"```" msgstr "" -#: src/exercises/bare-metal/compass.md:64 src/exercises/bare-metal/rtc.md:385 -msgid "`Cargo.toml` (you shouldn't need to change this):" -msgstr "`Cargo.toml` (no debería ser necesario cambiarlo):" +#: src/exercises/bare-metal/compass.md:55 +#: src/exercises/bare-metal/solutions-morning.md:56 +msgid "\"Ready.\"" +msgstr "" -#: src/exercises/bare-metal/compass.md:68 +#: src/exercises/bare-metal/compass.md:58 msgid "" -"```toml\n" -"[workspace]\n" -"\n" -"[package]\n" -"name = \"compass\"\n" -"version = \"0.1.0\"\n" -"edition = \"2021\"\n" -"publish = false\n" -"\n" -"[dependencies]\n" -"cortex-m-rt = \"0.7.3\"\n" -"embedded-hal = \"0.2.6\"\n" -"lsm303agr = \"0.2.2\"\n" -"microbit-v2 = \"0.13.0\"\n" -"panic-halt = \"0.2.0\"\n" -"```" +"// Read compass data and log it to the serial port.\n" +" // TODO\n" msgstr "" +#: src/exercises/bare-metal/compass.md:64 src/exercises/bare-metal/rtc.md:385 +#, fuzzy +#| msgid "`Cargo.toml` (you shouldn't need to change this):" +msgid "_Cargo.toml_ (you shouldn't need to change this):" +msgstr "`Cargo.toml` (no debería ser necesario cambiarlo):" + #: src/exercises/bare-metal/compass.md:85 -msgid "`Embed.toml` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`Embed.toml` (you shouldn't need to change this):" +msgid "_Embed.toml_ (you shouldn't need to change this):" msgstr "`Embed.toml` (no debería ser necesario cambiarlo):" -#: src/exercises/bare-metal/compass.md:89 -msgid "" -"```toml\n" -"[default.general]\n" -"chip = \"nrf52833_xxAA\"\n" -"\n" -"[debug.gdb]\n" -"enabled = true\n" -"\n" -"[debug.reset]\n" -"halt_afterwards = true\n" -"```" -msgstr "" - #: src/exercises/bare-metal/compass.md:100 src/exercises/bare-metal/rtc.md:985 -msgid "`.cargo/config.toml` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`.cargo/config.toml` (you shouldn't need to change this):" +msgid "_.cargo/config.toml_ (you shouldn't need to change this):" msgstr "`.cargo/config.toml` (no debería ser necesario cambiarlo):" -#: src/exercises/bare-metal/compass.md:104 -msgid "" -"```toml\n" -"[build]\n" -"target = \"thumbv7em-none-eabihf\" # Cortex-M4F\n" -"\n" -"[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))']\n" -"rustflags = [\"-C\", \"link-arg=-Tlink.x\"]\n" -"```" -msgstr "" - #: src/exercises/bare-metal/compass.md:112 msgid "See the serial output on Linux with:" msgstr "Consulta la salida de serie en Linux con:" -#: src/exercises/bare-metal/compass.md:114 -msgid "" -"```sh\n" -"picocom --baud 115200 --imap lfcrlf /dev/ttyACM0\n" -"```" -msgstr "" - #: src/exercises/bare-metal/compass.md:118 msgid "" "Or on Mac OS something like (the device name may be slightly different):" @@ -15735,13 +13298,6 @@ msgstr "" "En Mac OS debería ser algo como lo siguiente (el nombre del dispositivo " "puede ser algo diferente):" -#: src/exercises/bare-metal/compass.md:120 -msgid "" -"```sh\n" -"picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502\n" -"```" -msgstr "" - #: src/exercises/bare-metal/compass.md:124 msgid "Use Ctrl+A Ctrl+Q to quit picocom." msgstr "Pulsa Ctrl+A Ctrl+Q para salir de Picocom." @@ -15969,58 +13525,61 @@ msgid "Inline assembly" msgstr "Ensamblaje integrado" #: src/bare-metal/aps/inline-assembly.md:3 +#, fuzzy +#| msgid "" +#| "Sometimes we need to use assembly to do things that aren't possible with " +#| "Rust code. For example, to make an " msgid "" "Sometimes we need to use assembly to do things that aren't possible with " -"Rust code. For example, to make an " +"Rust code. For example, to make an HVC (hypervisor call) to tell the " +"firmware to power off the system:" msgstr "" "A veces necesitamos usar el ensamblador para hacer cosas que no son posibles " "con código Rust. Por ejemplo, hacer un " -#: src/bare-metal/aps/inline-assembly.md:4 -msgid "HVC" -msgstr "HVC" - -#: src/bare-metal/aps/inline-assembly.md:4 -msgid " to tell the firmware to power off the system:" -msgstr " para decirle al firmware que apague el sistema:" - -#: src/bare-metal/aps/inline-assembly.md:6 +#: src/bare-metal/aps/inline-assembly.md:19 msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"use core::arch::asm;\n" -"use core::panic::PanicInfo;\n" -"\n" -"mod exceptions;\n" -"\n" -"const PSCI_SYSTEM_OFF: u32 = 0x84000008;\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) {\n" -" // Safe because this only uses the declared registers and doesn't do\n" +"// Safe because this only uses the declared registers and doesn't do\n" " // anything with memory.\n" -" unsafe {\n" -" asm!(\"hvc #0\",\n" -" inout(\"w0\") PSCI_SYSTEM_OFF => _,\n" -" inout(\"w1\") 0 => _,\n" -" inout(\"w2\") 0 => _,\n" -" inout(\"w3\") 0 => _,\n" -" inout(\"w4\") 0 => _,\n" -" inout(\"w5\") 0 => _,\n" -" inout(\"w6\") 0 => _,\n" -" inout(\"w7\") 0 => _,\n" -" options(nomem, nostack)\n" -" );\n" -" }\n" -"\n" -" loop {}\n" -"}\n" -"```" msgstr "" -#: src/bare-metal/aps/inline-assembly.md:39 +#: src/bare-metal/aps/inline-assembly.md:22 +msgid "\"hvc #0\"" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:23 +msgid "\"w0\"" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:24 +msgid "\"w1\"" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:25 +msgid "\"w2\"" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:26 +msgid "\"w3\"" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:27 +msgid "\"w4\"" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:28 +msgid "\"w5\"" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:29 +msgid "\"w6\"" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:30 +msgid "\"w7\"" +msgstr "" + +#: src/bare-metal/aps/inline-assembly.md:39 msgid "" "(If you actually want to do this, use the [`smccc`](https://crates.io/crates/" "smccc) crate which has wrappers for all these functions.)" @@ -16154,22 +13713,13 @@ msgstr "" "La máquina \"virt\" de QEMU tiene una UART [PL011]https://developer.arm.com/" "documentation/ddi0183/g), así que vamos a escribir un controlador para ella." -#: src/bare-metal/aps/uart.md:5 +#: src/bare-metal/aps/uart.md:9 +msgid "/// Minimal driver for a PL011 UART.\n" +msgstr "" + +#: src/bare-metal/aps/uart.md:17 src/bare-metal/aps/better-uart/driver.md:13 msgid "" -"```rust,editable\n" -"const FLAG_REGISTER_OFFSET: usize = 0x18;\n" -"const FR_BUSY: u8 = 1 << 3;\n" -"const FR_TXFF: u8 = 1 << 5;\n" -"\n" -"/// Minimal driver for a PL011 UART.\n" -"#[derive(Debug)]\n" -"pub struct Uart {\n" -" base_address: *mut u8,\n" -"}\n" -"\n" -"impl Uart {\n" -" /// Constructs a new instance of the UART driver for a PL011 device at " -"the\n" +"/// Constructs a new instance of the UART driver for a PL011 device at the\n" " /// given base address.\n" " ///\n" " /// # Safety\n" @@ -16179,34 +13729,32 @@ msgid "" " /// PL011 device, which must be mapped into the address space of the " "process\n" " /// as device memory and not have any other aliases.\n" -" pub unsafe fn new(base_address: *mut u8) -> Self {\n" -" Self { base_address }\n" -" }\n" -"\n" -" /// Writes a single byte to the UART.\n" -" pub fn write_byte(&self, byte: u8) {\n" -" // Wait until there is room in the TX buffer.\n" -" while self.read_flag_register() & FR_TXFF != 0 {}\n" -"\n" -" // Safe because we know that the base address points to the control\n" -" // registers of a PL011 device which is appropriately mapped.\n" -" unsafe {\n" -" // Write to the TX buffer.\n" -" self.base_address.write_volatile(byte);\n" -" }\n" -"\n" -" // Wait until the UART is no longer busy.\n" -" while self.read_flag_register() & FR_BUSY != 0 {}\n" -" }\n" -"\n" -" fn read_flag_register(&self) -> u8 {\n" -" // Safe because we know that the base address points to the control\n" +msgstr "" + +#: src/bare-metal/aps/uart.md:29 src/bare-metal/aps/better-uart/driver.md:27 +#: src/exercises/bare-metal/rtc.md:336 +msgid "/// Writes a single byte to the UART.\n" +msgstr "" + +#: src/bare-metal/aps/uart.md:31 src/bare-metal/aps/better-uart/driver.md:29 +#: src/exercises/bare-metal/rtc.md:338 +msgid "// Wait until there is room in the TX buffer.\n" +msgstr "" + +#: src/bare-metal/aps/uart.md:34 src/bare-metal/aps/uart.md:46 +msgid "" +"// Safe because we know that the base address points to the control\n" " // registers of a PL011 device which is appropriately mapped.\n" -" unsafe { self.base_address.add(FLAG_REGISTER_OFFSET)." -"read_volatile() }\n" -" }\n" -"}\n" -"```" +msgstr "" + +#: src/bare-metal/aps/uart.md:37 src/bare-metal/aps/better-uart/driver.md:35 +#: src/exercises/bare-metal/rtc.md:344 +msgid "// Write to the TX buffer.\n" +msgstr "" + +#: src/bare-metal/aps/uart.md:41 src/bare-metal/aps/better-uart/driver.md:39 +#: src/exercises/bare-metal/rtc.md:348 +msgid "// Wait until the UART is no longer busy.\n" msgstr "" #: src/bare-metal/aps/uart.md:55 @@ -16258,24 +13806,11 @@ msgstr "" "Hemos derivado el trait `Debug`. También sería útil implementar algunos " "traits más." -#: src/bare-metal/aps/uart/traits.md:5 +#: src/bare-metal/aps/uart/traits.md:16 src/exercises/bare-metal/rtc.md:379 +#: src/exercises/bare-metal/solutions-afternoon.md:231 msgid "" -"```rust,editable,compile_fail\n" -"use core::fmt::{self, Write};\n" -"\n" -"impl Write for Uart {\n" -" fn write_str(&mut self, s: &str) -> fmt::Result {\n" -" for c in s.as_bytes() {\n" -" self.write_byte(*c);\n" -" }\n" -" Ok(())\n" -" }\n" -"}\n" -"\n" "// Safe because it just contains a pointer to device memory, which can be\n" "// accessed from any context.\n" -"unsafe impl Send for Uart {}\n" -"```" msgstr "" #: src/bare-metal/aps/uart/traits.md:24 @@ -16481,37 +14016,54 @@ msgstr "" "El crate [`bitflags`](https://crates.io/crates/bitflags) resulta útil para " "trabajar con bitflags." -#: src/bare-metal/aps/better-uart/bitflags.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"use bitflags::bitflags;\n" -"\n" -"bitflags! {\n" -" /// Flags from the UART flag register.\n" -" #[repr(transparent)]\n" -" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" -" struct Flags: u16 {\n" -" /// Clear to send.\n" -" const CTS = 1 << 0;\n" -" /// Data set ready.\n" -" const DSR = 1 << 1;\n" -" /// Data carrier detect.\n" -" const DCD = 1 << 2;\n" -" /// UART busy transmitting data.\n" -" const BUSY = 1 << 3;\n" -" /// Receive FIFO is empty.\n" -" const RXFE = 1 << 4;\n" -" /// Transmit FIFO is full.\n" -" const TXFF = 1 << 5;\n" -" /// Receive FIFO is full.\n" -" const RXFF = 1 << 6;\n" -" /// Transmit FIFO is empty.\n" -" const TXFE = 1 << 7;\n" -" /// Ring indicator.\n" -" const RI = 1 << 8;\n" -" }\n" -"}\n" -"```" +#: src/bare-metal/aps/better-uart/bitflags.md:9 +#: src/exercises/bare-metal/rtc.md:238 +msgid "/// Flags from the UART flag register.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:13 +#: src/exercises/bare-metal/rtc.md:242 +msgid "/// Clear to send.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:15 +#: src/exercises/bare-metal/rtc.md:244 +msgid "/// Data set ready.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:17 +#: src/exercises/bare-metal/rtc.md:246 +msgid "/// Data carrier detect.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:19 +#: src/exercises/bare-metal/rtc.md:248 +msgid "/// UART busy transmitting data.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:21 +#: src/exercises/bare-metal/rtc.md:250 +msgid "/// Receive FIFO is empty.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:23 +#: src/exercises/bare-metal/rtc.md:252 +msgid "/// Transmit FIFO is full.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:25 +#: src/exercises/bare-metal/rtc.md:254 +msgid "/// Receive FIFO is full.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:27 +#: src/exercises/bare-metal/rtc.md:256 +msgid "/// Transmit FIFO is empty.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/bitflags.md:29 +#: src/exercises/bare-metal/rtc.md:258 +msgid "/// Ring indicator.\n" msgstr "" #: src/bare-metal/aps/better-uart/bitflags.md:37 @@ -16533,43 +14085,6 @@ msgstr "" "Podemos utilizar una estructura para representar la disposición de la " "memoria de los registros de UART." -#: src/bare-metal/aps/better-uart/registers.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"#[repr(C, align(4))]\n" -"struct Registers {\n" -" dr: u16,\n" -" _reserved0: [u8; 2],\n" -" rsr: ReceiveStatus,\n" -" _reserved1: [u8; 19],\n" -" fr: Flags,\n" -" _reserved2: [u8; 6],\n" -" ilpr: u8,\n" -" _reserved3: [u8; 3],\n" -" ibrd: u16,\n" -" _reserved4: [u8; 2],\n" -" fbrd: u8,\n" -" _reserved5: [u8; 3],\n" -" lcr_h: u8,\n" -" _reserved6: [u8; 3],\n" -" cr: u16,\n" -" _reserved7: [u8; 3],\n" -" ifls: u8,\n" -" _reserved8: [u8; 3],\n" -" imsc: u16,\n" -" _reserved9: [u8; 2],\n" -" ris: u16,\n" -" _reserved10: [u8; 2],\n" -" mis: u16,\n" -" _reserved11: [u8; 2],\n" -" icr: u16,\n" -" _reserved12: [u8; 2],\n" -" dmacr: u8,\n" -" _reserved13: [u8; 3],\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/aps/better-uart/registers.md:41 msgid "" "[`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#the-c-" @@ -16591,69 +14106,28 @@ msgstr "" "Ahora vamos a utilizar la nueva estructura de `Registers` en nuestro " "controlador." -#: src/bare-metal/aps/better-uart/driver.md:5 +#: src/bare-metal/aps/better-uart/driver.md:6 +msgid "/// Driver for a PL011 UART.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:32 +#: src/bare-metal/aps/better-uart/driver.md:55 +#: src/exercises/bare-metal/rtc.md:341 src/exercises/bare-metal/rtc.md:364 msgid "" -"```rust,editable,compile_fail\n" -"/// Driver for a PL011 UART.\n" -"#[derive(Debug)]\n" -"pub struct Uart {\n" -" registers: *mut Registers,\n" -"}\n" -"\n" -"impl Uart {\n" -" /// Constructs a new instance of the UART driver for a PL011 device at " -"the\n" -" /// given base address.\n" -" ///\n" -" /// # Safety\n" -" ///\n" -" /// The given base address must point to the 8 MMIO control registers of " -"a\n" -" /// PL011 device, which must be mapped into the address space of the " -"process\n" -" /// as device memory and not have any other aliases.\n" -" pub unsafe fn new(base_address: *mut u32) -> Self {\n" -" Self {\n" -" registers: base_address as *mut Registers,\n" -" }\n" -" }\n" -"\n" -" /// Writes a single byte to the UART.\n" -" pub fn write_byte(&self, byte: u8) {\n" -" // Wait until there is room in the TX buffer.\n" -" while self.read_flag_register().contains(Flags::TXFF) {}\n" -"\n" -" // Safe because we know that self.registers points to the control\n" +"// Safe because we know that self.registers points to the control\n" " // registers of a PL011 device which is appropriately mapped.\n" -" unsafe {\n" -" // Write to the TX buffer.\n" -" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" -" }\n" -"\n" -" // Wait until the UART is no longer busy.\n" -" while self.read_flag_register().contains(Flags::BUSY) {}\n" -" }\n" -"\n" -" /// Reads and returns a pending byte, or `None` if nothing has been " +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:43 +#: src/exercises/bare-metal/rtc.md:352 +msgid "" +"/// Reads and returns a pending byte, or `None` if nothing has been " "received.\n" -" pub fn read_byte(&self) -> Option {\n" -" if self.read_flag_register().contains(Flags::RXFE) {\n" -" None\n" -" } else {\n" -" let data = unsafe { addr_of!((*self.registers).dr)." -"read_volatile() };\n" -" // TODO: Check for error conditions in bits 8-11.\n" -" Some(data as u8)\n" -" }\n" -" }\n" -"\n" -" fn read_flag_register(&self) -> Flags {\n" -" // Safe because we know that self.registers points to the control\n" -" // registers of a PL011 device which is appropriately mapped.\n" -" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" -" }\n" -"}\n" -"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/driver.md:49 +#: src/exercises/bare-metal/rtc.md:358 +msgid "// TODO: Check for error conditions in bits 8-11.\n" msgstr "" #: src/bare-metal/aps/better-uart/driver.md:64 @@ -16678,51 +14152,40 @@ msgstr "" "Vamos a crear un pequeño programa con nuestro controlador para escribir en " "la consola serie y compartir los bytes entrantes." -#: src/bare-metal/aps/better-uart/using.md:6 +#: src/bare-metal/aps/better-uart/using.md:19 +#: src/bare-metal/aps/logging/using.md:18 src/exercises/bare-metal/rtc.md:41 +#: src/exercises/bare-metal/solutions-afternoon.md:33 +msgid "/// Base address of the primary PL011 UART.\n" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:25 +#: src/bare-metal/aps/logging/using.md:24 src/exercises/bare-metal/rtc.md:47 +#: src/exercises/bare-metal/solutions-afternoon.md:44 msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"mod exceptions;\n" -"mod pl011;\n" -"\n" -"use crate::pl011::Uart;\n" -"use core::fmt::Write;\n" -"use core::panic::PanicInfo;\n" -"use log::error;\n" -"use smccc::psci::system_off;\n" -"use smccc::Hvc;\n" -"\n" -"/// Base address of the primary PL011 UART.\n" -"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" -" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " -"device,\n" +"// Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,\n" " // and nothing else accesses that address range.\n" -" let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" -"\n" -" writeln!(uart, \"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\").unwrap();\n" -"\n" -" loop {\n" -" if let Some(byte) = uart.read_byte() {\n" -" uart.write_byte(byte);\n" -" match byte {\n" -" b'\\r' => {\n" -" uart.write_byte(b'\\n');\n" -" }\n" -" b'q' => break,\n" -" _ => {}\n" -" }\n" -" }\n" -" }\n" -"\n" -" writeln!(uart, \"Bye!\").unwrap();\n" -" system_off::().unwrap();\n" -"}\n" -"```" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:29 +#: src/bare-metal/aps/logging/using.md:29 +msgid "\"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\"" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:35 +msgid "b'\\r'" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:36 +#: src/async/pitfalls/cancellation.md:27 +msgid "b'\\n'" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:38 +msgid "b'q'" +msgstr "" + +#: src/bare-metal/aps/better-uart/using.md:44 +msgid "\"Bye!\"" msgstr "" #: src/bare-metal/aps/better-uart/using.md:51 @@ -16750,50 +14213,12 @@ msgstr "" "Estaría bien poder utilizar las macros de registro del crate [`log`](https://" "crates.io/crates/log). Podemos hacerlo implementando el trait `Log`." -#: src/bare-metal/aps/logging.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"use crate::pl011::Uart;\n" -"use core::fmt::Write;\n" -"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" -"use spin::mutex::SpinMutex;\n" -"\n" -"static LOGGER: Logger = Logger {\n" -" uart: SpinMutex::new(None),\n" -"};\n" -"\n" -"struct Logger {\n" -" uart: SpinMutex>,\n" -"}\n" -"\n" -"impl Log for Logger {\n" -" fn enabled(&self, _metadata: &Metadata) -> bool {\n" -" true\n" -" }\n" -"\n" -" fn log(&self, record: &Record) {\n" -" writeln!(\n" -" self.uart.lock().as_mut().unwrap(),\n" -" \"[{}] {}\",\n" -" record.level(),\n" -" record.args()\n" -" )\n" -" .unwrap();\n" -" }\n" -"\n" -" fn flush(&self) {}\n" -"}\n" -"\n" -"/// Initialises UART logger.\n" -"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), " -"SetLoggerError> {\n" -" LOGGER.uart.lock().replace(uart);\n" -"\n" -" log::set_logger(&LOGGER)?;\n" -" log::set_max_level(max_level);\n" -" Ok(())\n" -"}\n" -"```" +#: src/bare-metal/aps/logging.md:28 src/exercises/bare-metal/rtc.md:190 +msgid "\"[{}] {}\"" +msgstr "" + +#: src/bare-metal/aps/logging.md:37 src/exercises/bare-metal/rtc.md:199 +msgid "/// Initialises UART logger.\n" msgstr "" #: src/bare-metal/aps/logging.md:50 @@ -16808,47 +14233,9 @@ msgstr "" msgid "We need to initialise the logger before we use it." msgstr "Debemos inicializar el registrador antes de utilizarlo." -#: src/bare-metal/aps/logging/using.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"mod exceptions;\n" -"mod logger;\n" -"mod pl011;\n" -"\n" -"use crate::pl011::Uart;\n" -"use core::panic::PanicInfo;\n" -"use log::{error, info, LevelFilter};\n" -"use smccc::psci::system_off;\n" -"use smccc::Hvc;\n" -"\n" -"/// Base address of the primary PL011 UART.\n" -"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" -" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " -"device,\n" -" // and nothing else accesses that address range.\n" -" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" -" logger::init(uart, LevelFilter::Trace).unwrap();\n" -"\n" -" info!(\"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\");\n" -"\n" -" assert_eq!(x1, 42);\n" -"\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[panic_handler]\n" -"fn panic(info: &PanicInfo) -> ! {\n" -" error!(\"{info}\");\n" -" system_off::().unwrap();\n" -" loop {}\n" -"}\n" -"```" +#: src/bare-metal/aps/logging/using.md:38 src/exercises/bare-metal/rtc.md:69 +#: src/exercises/bare-metal/solutions-afternoon.md:121 +msgid "\"{info}\"" msgstr "" #: src/bare-metal/aps/logging/using.md:46 @@ -16879,63 +14266,6 @@ msgstr "" "AArch32). Implementamos esto en el ensamblaje para guardar los registros " "volátiles en la _stack_ antes de llamar al código de Rust:" -#: src/bare-metal/aps/exceptions.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"use log::error;\n" -"use smccc::psci::system_off;\n" -"use smccc::Hvc;\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" -" error!(\"sync_exception_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" -" error!(\"irq_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" -" error!(\"fiq_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" -" error!(\"serr_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"sync_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"irq_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"fiq_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"serr_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/aps/exceptions.md:64 msgid "EL is exception level; all our examples this afternoon run in EL1." msgstr "" @@ -17087,43 +14417,6 @@ msgstr "" "traits y macros para realizar conversiones seguras entre secuencias de bytes " "y otros tipos." -#: src/bare-metal/useful-crates/zerocopy.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"use zerocopy::AsBytes;\n" -"\n" -"#[repr(u32)]\n" -"#[derive(AsBytes, Debug, Default)]\n" -"enum RequestType {\n" -" #[default]\n" -" In = 0,\n" -" Out = 1,\n" -" Flush = 4,\n" -"}\n" -"\n" -"#[repr(C)]\n" -"#[derive(AsBytes, Debug, Default)]\n" -"struct VirtioBlockRequest {\n" -" request_type: RequestType,\n" -" reserved: u32,\n" -" sector: u64,\n" -"}\n" -"\n" -"fn main() {\n" -" let request = VirtioBlockRequest {\n" -" request_type: RequestType::Flush,\n" -" sector: 42,\n" -" ..Default::default()\n" -" };\n" -"\n" -" assert_eq!(\n" -" request.as_bytes(),\n" -" &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0]\n" -" );\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/useful-crates/zerocopy.md:40 msgid "" "This is not suitable for MMIO (as it doesn't use volatile reads and writes), " @@ -17185,27 +14478,16 @@ msgstr "" "crear tablas de páginas de acuerdo con la arquitectura del sistema de " "memoria virtual AArch64." -#: src/bare-metal/useful-crates/aarch64-paging.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"use aarch64_paging::{\n" -" idmap::IdMap,\n" -" paging::{Attributes, MemoryRegion},\n" -"};\n" -"\n" -"const ASID: usize = 1;\n" -"const ROOT_LEVEL: usize = 1;\n" -"\n" -"// Create a new page table with identity mapping.\n" -"let mut idmap = IdMap::new(ASID, ROOT_LEVEL);\n" -"// Map a 2 MiB region of memory as read-only.\n" -"idmap.map_range(\n" -" &MemoryRegion::new(0x80200000, 0x80400000),\n" -" Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,\n" -").unwrap();\n" -"// Set `TTBR0_EL1` to activate the page table.\n" -"idmap.activate();\n" -"```" +#: src/bare-metal/useful-crates/aarch64-paging.md:14 +msgid "// Create a new page table with identity mapping.\n" +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:16 +msgid "// Map a 2 MiB region of memory as read-only.\n" +msgstr "" + +#: src/bare-metal/useful-crates/aarch64-paging.md:21 +msgid "// Set `TTBR0_EL1` to activate the page table.\n" msgstr "" #: src/bare-metal/useful-crates/aarch64-paging.md:28 @@ -17259,25 +14541,6 @@ msgstr "" "direcciones. Por ejemplo, podríamos querer asignar espacio MMIO para los " "registros de dirección base (BAR) de PCI:" -#: src/bare-metal/useful-crates/buddy_system_allocator.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"use buddy_system_allocator::FrameAllocator;\n" -"use core::alloc::Layout;\n" -"\n" -"fn main() {\n" -" let mut allocator = FrameAllocator::<32>::new();\n" -" allocator.add_frame(0x200_0000, 0x400_0000);\n" -"\n" -" let layout = Layout::from_size_align(0x100, 0x100).unwrap();\n" -" let bar = allocator\n" -" .alloc_aligned(layout)\n" -" .expect(\"Failed to allocate 0x100 byte MMIO region\");\n" -" println!(\"Allocated 0x100 byte MMIO region at {:#x}\", bar);\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/useful-crates/buddy_system_allocator.md:26 msgid "PCI BARs always have alignment equal to their size." msgstr "Los BAR de PCI siempre tienen una alineación igual a su tamaño." @@ -17311,22 +14574,6 @@ msgstr "" "elementos se usan, entrando en _panic_ si intentas utilizar más elementos de " "los asignados." -#: src/bare-metal/useful-crates/tinyvec.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"use tinyvec::{array_vec, ArrayVec};\n" -"\n" -"fn main() {\n" -" let mut numbers: ArrayVec<[u32; 5]> = array_vec!(42, 66);\n" -" println!(\"{numbers:?}\");\n" -" numbers.push(7);\n" -" println!(\"{numbers:?}\");\n" -" numbers.remove(1);\n" -" println!(\"{numbers:?}\");\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/useful-crates/tinyvec.md:23 msgid "" "`tinyvec` requires that the element type implement `Default` for " @@ -17365,21 +14612,6 @@ msgstr "" "El crate [`spin`](https://crates.io/crates/spin) proporciona equivalentes " "basados en spinlocks de muchos de estos primitivos." -#: src/bare-metal/useful-crates/spin.md:9 -msgid "" -"```rust,editable,compile_fail\n" -"use spin::mutex::SpinMutex;\n" -"\n" -"static counter: SpinMutex = SpinMutex::new(0);\n" -"\n" -"fn main() {\n" -" println!(\"count: {}\", counter.lock());\n" -" *counter.lock() += 2;\n" -" println!(\"count: {}\", counter.lock());\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/useful-crates/spin.md:23 msgid "Be careful to avoid deadlock if you take locks in interrupt handlers." msgstr "" @@ -17425,48 +14657,6 @@ msgstr "" "binario en sí. Por último, un `raw_binary` para convertir el ELF en un " "binario sin formato que pueda ejecutarse." -#: src/bare-metal/android.md:7 -msgid "" -"```soong\n" -"rust_ffi_static {\n" -" name: \"libvmbase_example\",\n" -" defaults: [\"vmbase_ffi_defaults\"],\n" -" crate_name: \"vmbase_example\",\n" -" srcs: [\"src/main.rs\"],\n" -" rustlibs: [\n" -" \"libvmbase\",\n" -" ],\n" -"}\n" -"\n" -"cc_binary {\n" -" name: \"vmbase_example\",\n" -" defaults: [\"vmbase_elf_defaults\"],\n" -" srcs: [\n" -" \"idmap.S\",\n" -" ],\n" -" static_libs: [\n" -" \"libvmbase_example\",\n" -" ],\n" -" linker_scripts: [\n" -" \"image.ld\",\n" -" \":vmbase_sections\",\n" -" ],\n" -"}\n" -"\n" -"raw_binary {\n" -" name: \"vmbase_example_bin\",\n" -" stem: \"vmbase_example.bin\",\n" -" src: \":vmbase_example\",\n" -" enabled: false,\n" -" target: {\n" -" android_arm64: {\n" -" enabled: true,\n" -" },\n" -" },\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/android/vmbase.md:3 msgid "" "For VMs running under crosvm on aarch64, the [vmbase](https://android." @@ -17481,22 +14671,6 @@ msgstr "" "reglas de compilación, además de un punto de entrada, registro de la consola " "UART y mucho más." -#: src/bare-metal/android/vmbase.md:6 -msgid "" -"```rust,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"use vmbase::{main, println};\n" -"\n" -"main!(main);\n" -"\n" -"pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {\n" -" println!(\"Hello world\");\n" -"}\n" -"```" -msgstr "" - #: src/bare-metal/android/vmbase.md:21 msgid "" "The `main!` macro marks your main function, to be called from the `vmbase` " @@ -17589,75 +14763,47 @@ msgstr "" "Descarga la [plantilla de ejercicio](../../comprehensive-rust-exercises.zip) " "y busca en el directorio `rtc` los siguientes archivos." -#: src/exercises/bare-metal/rtc.md:23 +#: src/exercises/bare-metal/rtc.md:37 +#: src/exercises/bare-metal/solutions-afternoon.md:29 +msgid "/// Base addresses of the GICv3.\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:52 +#: src/exercises/bare-metal/solutions-afternoon.md:49 +msgid "\"main({:#x}, {:#x}, {:#x}, {:#x})\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:54 +#: src/exercises/bare-metal/solutions-afternoon.md:51 msgid "" -"```rust,compile_fail\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"mod exceptions;\n" -"mod logger;\n" -"mod pl011;\n" -"\n" -"use crate::pl011::Uart;\n" -"use arm_gic::gicv3::GicV3;\n" -"use core::panic::PanicInfo;\n" -"use log::{error, info, trace, LevelFilter};\n" -"use smccc::psci::system_off;\n" -"use smccc::Hvc;\n" -"\n" -"/// Base addresses of the GICv3.\n" -"const GICD_BASE_ADDRESS: *mut u64 = 0x800_0000 as _;\n" -"const GICR_BASE_ADDRESS: *mut u64 = 0x80A_0000 as _;\n" -"\n" -"/// Base address of the primary PL011 UART.\n" -"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" -" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " -"device,\n" -" // and nothing else accesses that address range.\n" -" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" -" logger::init(uart, LevelFilter::Trace).unwrap();\n" -"\n" -" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" -"\n" -" // Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the " -"base\n" +"// Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base\n" " // addresses of a GICv3 distributor and redistributor respectively, and\n" " // nothing else accesses those address ranges.\n" -" let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, " -"GICR_BASE_ADDRESS) };\n" -" gic.setup();\n" -"\n" -" // TODO: Create instance of RTC driver and print current time.\n" -"\n" -" // TODO: Wait for 3 seconds.\n" -"\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[panic_handler]\n" -"fn panic(info: &PanicInfo) -> ! {\n" -" error!(\"{info}\");\n" -" system_off::().unwrap();\n" -" loop {}\n" -"}\n" -"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:60 +msgid "// TODO: Create instance of RTC driver and print current time.\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:62 +msgid "// TODO: Wait for 3 seconds.\n" msgstr "" #: src/exercises/bare-metal/rtc.md:75 +#, fuzzy +#| msgid "" +#| "`src/exceptions.rs` (you should only need to change this for the 3rd part " +#| "of the exercise):" msgid "" -"`src/exceptions.rs` (you should only need to change this for the 3rd part of " +"_src/exceptions.rs_ (you should only need to change this for the 3rd part of " "the exercise):" msgstr "" "`src/exceptions.rs` (solo se debería cambiar esto en la tercera parte del " "ejercicio):" -#: src/exercises/bare-metal/rtc.md:79 +#: src/exercises/bare-metal/rtc.md:80 src/exercises/bare-metal/rtc.md:154 +#: src/exercises/bare-metal/rtc.md:215 src/exercises/bare-metal/rtc.md:415 msgid "" -"```rust,compile_fail\n" "// Copyright 2023 Google LLC\n" "//\n" "// Licensed under the Apache License, Version 2.0 (the \"License\");\n" @@ -17671,245 +14817,110 @@ msgid "" "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" "// See the License for the specific language governing permissions and\n" "// limitations under the License.\n" -"\n" -"use arm_gic::gicv3::GicV3;\n" -"use log::{error, info, trace};\n" -"use smccc::psci::system_off;\n" -"use smccc::Hvc;\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" -" error!(\"sync_exception_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" -" trace!(\"irq_current\");\n" -" let intid = GicV3::get_and_acknowledge_interrupt().expect(\"No pending " -"interrupt\");\n" -" info!(\"IRQ {intid:?}\");\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" -" error!(\"fiq_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" -" error!(\"serr_current\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"sync_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"irq_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"fiq_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[no_mangle]\n" -"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" -" error!(\"serr_lower\");\n" -" system_off::().unwrap();\n" -"}\n" -"```" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:101 +msgid "\"sync_exception_current\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:107 +msgid "\"irq_current\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:108 +msgid "\"No pending interrupt\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:109 +msgid "\"IRQ {intid:?}\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:114 +msgid "\"fiq_current\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:120 +msgid "\"serr_current\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:126 +msgid "\"sync_lower\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:132 +msgid "\"irq_lower\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:138 +msgid "\"fiq_lower\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:144 +msgid "\"serr_lower\"" msgstr "" #: src/exercises/bare-metal/rtc.md:149 -msgid "`src/logger.rs` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`src/logger.rs` (you shouldn't need to change this):" +msgid "_src/logger.rs_ (you shouldn't need to change this):" msgstr "`src/logger.rs` (no debería ser necesario cambiarlo):" -#: src/exercises/bare-metal/rtc.md:153 -msgid "" -"```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: main\n" -"use crate::pl011::Uart;\n" -"use core::fmt::Write;\n" -"use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};\n" -"use spin::mutex::SpinMutex;\n" -"\n" -"static LOGGER: Logger = Logger {\n" -" uart: SpinMutex::new(None),\n" -"};\n" -"\n" -"struct Logger {\n" -" uart: SpinMutex>,\n" -"}\n" -"\n" -"impl Log for Logger {\n" -" fn enabled(&self, _metadata: &Metadata) -> bool {\n" -" true\n" -" }\n" -"\n" -" fn log(&self, record: &Record) {\n" -" writeln!(\n" -" self.uart.lock().as_mut().unwrap(),\n" -" \"[{}] {}\",\n" -" record.level(),\n" -" record.args()\n" -" )\n" -" .unwrap();\n" -" }\n" -"\n" -" fn flush(&self) {}\n" -"}\n" -"\n" -"/// Initialises UART logger.\n" -"pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), " -"SetLoggerError> {\n" -" LOGGER.uart.lock().replace(uart);\n" -"\n" -" log::set_logger(&LOGGER)?;\n" -" log::set_max_level(max_level);\n" -" Ok(())\n" -"}\n" -"```" +#: src/exercises/bare-metal/rtc.md:167 +msgid "// ANCHOR: main\n" msgstr "" #: src/exercises/bare-metal/rtc.md:210 -msgid "`src/pl011.rs` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`src/pl011.rs` (you shouldn't need to change this):" +msgid "_src/pl011.rs_ (you shouldn't need to change this):" msgstr "`src/pl011.rs` (no debería ser necesario cambiarlo):" -#: src/exercises/bare-metal/rtc.md:214 +#: src/exercises/bare-metal/rtc.md:233 +msgid "// ANCHOR: Flags\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:261 +msgid "// ANCHOR_END: Flags\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:265 +msgid "" +"/// Flags from the UART Receive Status Register / Error Clear Register.\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:269 +msgid "/// Framing error.\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:271 +msgid "/// Parity error.\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:273 +msgid "/// Break error.\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:275 +msgid "/// Overrun error.\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:279 +msgid "// ANCHOR: Registers\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:311 +msgid "// ANCHOR_END: Registers\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:313 msgid "" -"```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"#![allow(unused)]\n" -"\n" -"use core::fmt::{self, Write};\n" -"use core::ptr::{addr_of, addr_of_mut};\n" -"\n" -"// ANCHOR: Flags\n" -"use bitflags::bitflags;\n" -"\n" -"bitflags! {\n" -" /// Flags from the UART flag register.\n" -" #[repr(transparent)]\n" -" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" -" struct Flags: u16 {\n" -" /// Clear to send.\n" -" const CTS = 1 << 0;\n" -" /// Data set ready.\n" -" const DSR = 1 << 1;\n" -" /// Data carrier detect.\n" -" const DCD = 1 << 2;\n" -" /// UART busy transmitting data.\n" -" const BUSY = 1 << 3;\n" -" /// Receive FIFO is empty.\n" -" const RXFE = 1 << 4;\n" -" /// Transmit FIFO is full.\n" -" const TXFF = 1 << 5;\n" -" /// Receive FIFO is full.\n" -" const RXFF = 1 << 6;\n" -" /// Transmit FIFO is empty.\n" -" const TXFE = 1 << 7;\n" -" /// Ring indicator.\n" -" const RI = 1 << 8;\n" -" }\n" -"}\n" -"// ANCHOR_END: Flags\n" -"\n" -"bitflags! {\n" -" /// Flags from the UART Receive Status Register / Error Clear Register.\n" -" #[repr(transparent)]\n" -" #[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" -" struct ReceiveStatus: u16 {\n" -" /// Framing error.\n" -" const FE = 1 << 0;\n" -" /// Parity error.\n" -" const PE = 1 << 1;\n" -" /// Break error.\n" -" const BE = 1 << 2;\n" -" /// Overrun error.\n" -" const OE = 1 << 3;\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: Registers\n" -"#[repr(C, align(4))]\n" -"struct Registers {\n" -" dr: u16,\n" -" _reserved0: [u8; 2],\n" -" rsr: ReceiveStatus,\n" -" _reserved1: [u8; 19],\n" -" fr: Flags,\n" -" _reserved2: [u8; 6],\n" -" ilpr: u8,\n" -" _reserved3: [u8; 3],\n" -" ibrd: u16,\n" -" _reserved4: [u8; 2],\n" -" fbrd: u8,\n" -" _reserved5: [u8; 3],\n" -" lcr_h: u8,\n" -" _reserved6: [u8; 3],\n" -" cr: u16,\n" -" _reserved7: [u8; 3],\n" -" ifls: u8,\n" -" _reserved8: [u8; 3],\n" -" imsc: u16,\n" -" _reserved9: [u8; 2],\n" -" ris: u16,\n" -" _reserved10: [u8; 2],\n" -" mis: u16,\n" -" _reserved11: [u8; 2],\n" -" icr: u16,\n" -" _reserved12: [u8; 2],\n" -" dmacr: u8,\n" -" _reserved13: [u8; 3],\n" -"}\n" -"// ANCHOR_END: Registers\n" -"\n" "// ANCHOR: Uart\n" "/// Driver for a PL011 UART.\n" -"#[derive(Debug)]\n" -"pub struct Uart {\n" -" registers: *mut Registers,\n" -"}\n" -"\n" -"impl Uart {\n" -" /// Constructs a new instance of the UART driver for a PL011 device at " -"the\n" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:322 +msgid "" +"/// Constructs a new instance of the UART driver for a PL011 device at the\n" " /// given base address.\n" " ///\n" " /// # Safety\n" @@ -17919,129 +14930,58 @@ msgid "" " /// PL011 device, which must be mapped into the address space of the " "process\n" " /// as device memory and not have any other aliases.\n" -" pub unsafe fn new(base_address: *mut u32) -> Self {\n" -" Self {\n" -" registers: base_address as *mut Registers,\n" -" }\n" -" }\n" -"\n" -" /// Writes a single byte to the UART.\n" -" pub fn write_byte(&self, byte: u8) {\n" -" // Wait until there is room in the TX buffer.\n" -" while self.read_flag_register().contains(Flags::TXFF) {}\n" -"\n" -" // Safe because we know that self.registers points to the control\n" -" // registers of a PL011 device which is appropriately mapped.\n" -" unsafe {\n" -" // Write to the TX buffer.\n" -" addr_of_mut!((*self.registers).dr).write_volatile(byte.into());\n" -" }\n" -"\n" -" // Wait until the UART is no longer busy.\n" -" while self.read_flag_register().contains(Flags::BUSY) {}\n" -" }\n" -"\n" -" /// Reads and returns a pending byte, or `None` if nothing has been " -"received.\n" -" pub fn read_byte(&self) -> Option {\n" -" if self.read_flag_register().contains(Flags::RXFE) {\n" -" None\n" -" } else {\n" -" let data = unsafe { addr_of!((*self.registers).dr)." -"read_volatile() };\n" -" // TODO: Check for error conditions in bits 8-11.\n" -" Some(data as u8)\n" -" }\n" -" }\n" -"\n" -" fn read_flag_register(&self) -> Flags {\n" -" // Safe because we know that self.registers points to the control\n" -" // registers of a PL011 device which is appropriately mapped.\n" -" unsafe { addr_of!((*self.registers).fr).read_volatile() }\n" -" }\n" -"}\n" -"// ANCHOR_END: Uart\n" -"\n" -"impl Write for Uart {\n" -" fn write_str(&mut self, s: &str) -> fmt::Result {\n" -" for c in s.as_bytes() {\n" -" self.write_byte(*c);\n" -" }\n" -" Ok(())\n" -" }\n" -"}\n" -"\n" -"// Safe because it just contains a pointer to device memory, which can be\n" -"// accessed from any context.\n" -"unsafe impl Send for Uart {}\n" -"```" msgstr "" -#: src/exercises/bare-metal/rtc.md:389 -msgid "" -"```toml\n" -"[workspace]\n" -"\n" -"[package]\n" -"name = \"rtc\"\n" -"version = \"0.1.0\"\n" -"edition = \"2021\"\n" -"publish = false\n" -"\n" -"[dependencies]\n" -"arm-gic = \"0.1.0\"\n" -"bitflags = \"2.0.0\"\n" -"chrono = { version = \"0.4.24\", default-features = false }\n" -"log = \"0.4.17\"\n" -"smccc = \"0.1.1\"\n" -"spin = \"0.9.8\"\n" -"\n" -"[build-dependencies]\n" -"cc = \"1.0.73\"\n" -"```" +#: src/exercises/bare-metal/rtc.md:368 +msgid "// ANCHOR_END: Uart\n" msgstr "" #: src/exercises/bare-metal/rtc.md:410 -msgid "`build.rs` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`build.rs` (you shouldn't need to change this):" +msgid "_build.rs_ (you shouldn't need to change this):" msgstr "`build.rs` (no debería ser necesario cambiarlo):" -#: src/exercises/bare-metal/rtc.md:414 -msgid "" -"```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"use cc::Build;\n" -"use std::env;\n" -"\n" -"fn main() {\n" -" #[cfg(target_os = \"linux\")]\n" -" env::set_var(\"CROSS_COMPILE\", \"aarch64-linux-gnu\");\n" -" #[cfg(not(target_os = \"linux\"))]\n" -" env::set_var(\"CROSS_COMPILE\", \"aarch64-none-elf\");\n" -"\n" -" Build::new()\n" -" .file(\"entry.S\")\n" -" .file(\"exceptions.S\")\n" -" .file(\"idmap.S\")\n" -" .compile(\"empty\")\n" -"}\n" -"```" +#: src/exercises/bare-metal/rtc.md:433 src/exercises/bare-metal/rtc.md:435 +msgid "\"linux\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:434 src/exercises/bare-metal/rtc.md:436 +msgid "\"CROSS_COMPILE\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:434 +#, fuzzy +#| msgid "aarch64-paging" +msgid "\"aarch64-linux-gnu\"" +msgstr "aarch64-paging" + +#: src/exercises/bare-metal/rtc.md:436 +msgid "\"aarch64-none-elf\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:439 +msgid "\"entry.S\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:440 +#, fuzzy +#| msgid "Exceptions" +msgid "\"exceptions.S\"" +msgstr "Excepciones" + +#: src/exercises/bare-metal/rtc.md:441 +msgid "\"idmap.S\"" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:442 +msgid "\"empty\"" msgstr "" #: src/exercises/bare-metal/rtc.md:446 -msgid "`entry.S` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`entry.S` (you shouldn't need to change this):" +msgid "_entry.S_ (you shouldn't need to change this):" msgstr "`entry.S` (no debería ser necesario cambiarlo):" #: src/exercises/bare-metal/rtc.md:450 @@ -18207,7 +15147,9 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:595 -msgid "`exceptions.S` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`exceptions.S` (you shouldn't need to change this):" +msgid "_exceptions.S_ (you shouldn't need to change this):" msgstr "`exceptions.S` (no debería ser necesario cambiarlo):" #: src/exercises/bare-metal/rtc.md:599 @@ -18405,7 +15347,9 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:780 -msgid "`idmap.S` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`idmap.S` (you shouldn't need to change this):" +msgid "_idmap.S_ (you shouldn't need to change this):" msgstr "`idmap.S` (no debería ser necesario cambiarlo):" #: src/exercises/bare-metal/rtc.md:784 @@ -18458,7 +15402,9 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:829 -msgid "`image.ld` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`image.ld` (you shouldn't need to change this):" +msgid "_image.ld_ (you shouldn't need to change this):" msgstr "`image.ld` (no debería ser necesario cambiarlo):" #: src/exercises/bare-metal/rtc.md:833 @@ -18573,61 +15519,31 @@ msgid "" msgstr "" #: src/exercises/bare-metal/rtc.md:940 -msgid "`Makefile` (you shouldn't need to change this):" +#, fuzzy +#| msgid "`Makefile` (you shouldn't need to change this):" +msgid "_Makefile_ (you shouldn't need to change this):" msgstr "`Makefile` (no debería ser necesario cambiarlo):" -#: src/exercises/bare-metal/rtc.md:944 -msgid "" -"```makefile\n" -"# Copyright 2023 Google LLC\n" -"#\n" -"# Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"# you may not use this file except in compliance with the License.\n" -"# You may obtain a copy of the License at\n" -"#\n" -"# http://www.apache.org/licenses/LICENSE-2.0\n" -"#\n" -"# Unless required by applicable law or agreed to in writing, software\n" -"# distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"# See the License for the specific language governing permissions and\n" -"# limitations under the License.\n" -"\n" -"UNAME := $(shell uname -s)\n" -"ifeq ($(UNAME),Linux)\n" -"\tTARGET = aarch64-linux-gnu\n" -"else\n" -"\tTARGET = aarch64-none-elf\n" -"endif\n" -"OBJCOPY = $(TARGET)-objcopy\n" -"\n" -".PHONY: build qemu_minimal qemu qemu_logger\n" -"\n" -"all: rtc.bin\n" -"\n" -"build:\n" -"\tcargo build\n" -"\n" -"rtc.bin: build\n" -"\t$(OBJCOPY) -O binary target/aarch64-unknown-none/debug/rtc $@\n" -"\n" -"qemu: rtc.bin\n" -"\tqemu-system-aarch64 -machine virt,gic-version=3 -cpu max -serial mon:stdio " -"-display none -kernel $< -s\n" -"\n" -"clean:\n" -"\tcargo clean\n" -"\trm -f *.bin\n" -"```" +#: src/exercises/bare-metal/rtc.md:945 +msgid "# Copyright 2023 Google LLC" msgstr "" -#: src/exercises/bare-metal/rtc.md:989 -msgid "" -"```toml\n" -"[build]\n" -"target = \"aarch64-unknown-none\"\n" -"rustflags = [\"-C\", \"link-arg=-Timage.ld\"]\n" -"```" +#: src/exercises/bare-metal/rtc.md:959 +msgid "$(shell uname -s)" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:961 +#, fuzzy +#| msgid "aarch64-paging" +msgid "aarch64-linux-gnu" +msgstr "aarch64-paging" + +#: src/exercises/bare-metal/rtc.md:978 +msgid "stdio -display none -kernel $< -s" +msgstr "" + +#: src/exercises/bare-metal/rtc.md:981 +msgid "cargo clean" msgstr "" #: src/exercises/bare-metal/rtc.md:995 @@ -18661,26 +15577,12 @@ msgstr "" msgid "Rust threads work similarly to threads in other languages:" msgstr "Los hilos de Rust funcionan de forma similar a los de otros lenguajes:" -#: src/concurrency/threads.md:5 -msgid "" -"```rust,editable\n" -"use std::thread;\n" -"use std::time::Duration;\n" -"\n" -"fn main() {\n" -" thread::spawn(|| {\n" -" for i in 1..10 {\n" -" println!(\"Count in thread: {i}!\");\n" -" thread::sleep(Duration::from_millis(5));\n" -" }\n" -" });\n" -"\n" -" for i in 1..5 {\n" -" println!(\"Main thread: {i}\");\n" -" thread::sleep(Duration::from_millis(5));\n" -" }\n" -"}\n" -"```" +#: src/concurrency/threads.md:12 +msgid "\"Count in thread: {i}!\"" +msgstr "" + +#: src/concurrency/threads.md:18 +msgid "\"Main thread: {i}\"" msgstr "" #: src/concurrency/threads.md:24 @@ -18732,22 +15634,8 @@ msgstr "" msgid "Normal threads cannot borrow from their environment:" msgstr "Los hilos normales no pueden tomar nada prestado de su entorno:" -#: src/concurrency/scoped-threads.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"use std::thread;\n" -"\n" -"fn foo() {\n" -" let s = String::from(\"Hello\");\n" -" thread::spawn(|| {\n" -" println!(\"Length: {}\", s.len());\n" -" });\n" -"}\n" -"\n" -"fn main() {\n" -" foo();\n" -"}\n" -"```" +#: src/concurrency/scoped-threads.md:11 src/concurrency/scoped-threads.md:30 +msgid "\"Length: {}\"" msgstr "" #: src/concurrency/scoped-threads.md:20 @@ -18758,23 +15646,6 @@ msgstr "" "Sin embargo, puedes usar un [hilo con ámbito](https://doc.rust-lang.org/std/" "thread/fn.scope.html) para lo siguiente:" -#: src/concurrency/scoped-threads.md:22 -msgid "" -"```rust,editable\n" -"use std::thread;\n" -"\n" -"fn main() {\n" -" let s = String::from(\"Hello\");\n" -"\n" -" thread::scope(|scope| {\n" -" scope.spawn(|| {\n" -" println!(\"Length: {}\", s.len());\n" -" });\n" -" });\n" -"}\n" -"```" -msgstr "" - #: src/concurrency/scoped-threads.md:40 msgid "" "The reason for that is that when the `thread::scope` function completes, all " @@ -18801,29 +15672,12 @@ msgstr "" "partes están conectadas a través del canal, pero solo se ven los puntos " "finales." -#: src/concurrency/channels.md:6 -msgid "" -"```rust,editable\n" -"use std::sync::mpsc;\n" -"use std::thread;\n" -"\n" -"fn main() {\n" -" let (tx, rx) = mpsc::channel();\n" -"\n" -" tx.send(10).unwrap();\n" -" tx.send(20).unwrap();\n" -"\n" -" println!(\"Received: {:?}\", rx.recv());\n" -" println!(\"Received: {:?}\", rx.recv());\n" -"\n" -" let tx2 = tx.clone();\n" -" tx2.send(30).unwrap();\n" -" println!(\"Received: {:?}\", rx.recv());\n" -"}\n" -"```" +#: src/concurrency/channels.md:15 src/concurrency/channels.md:16 +#: src/concurrency/channels.md:20 +msgid "\"Received: {:?}\"" msgstr "" -#: src/concurrency/channels.md:27 +#: src/concurrency/channels.md:26 msgid "" "`mpsc` stands for Multi-Producer, Single-Consumer. `Sender` and `SyncSender` " "implement `Clone` (so you can make multiple producers) but `Receiver` does " @@ -18833,7 +15687,7 @@ msgstr "" "consumidor único.) `Sender` y `SyncSender` implementan `Clone` (es decir, " "puedes crear varios productores), pero `Receiver` no." -#: src/concurrency/channels.md:29 +#: src/concurrency/channels.md:28 msgid "" "`send()` and `recv()` return `Result`. If they return `Err`, it means the " "counterpart `Sender` or `Receiver` is dropped and the channel is closed." @@ -18845,31 +15699,24 @@ msgstr "" msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:" msgstr "Se obtiene un canal asíncrono y sin límites con `mpsc::channel()`:" -#: src/concurrency/channels/unbounded.md:5 -msgid "" -"```rust,editable\n" -"use std::sync::mpsc;\n" -"use std::thread;\n" -"use std::time::Duration;\n" -"\n" -"fn main() {\n" -" let (tx, rx) = mpsc::channel();\n" -"\n" -" thread::spawn(move || {\n" -" let thread_id = thread::current().id();\n" -" for i in 1..10 {\n" -" tx.send(format!(\"Message {i}\")).unwrap();\n" -" println!(\"{thread_id:?}: sent Message {i}\");\n" -" }\n" -" println!(\"{thread_id:?}: done\");\n" -" });\n" -" thread::sleep(Duration::from_millis(100));\n" -"\n" -" for msg in rx.iter() {\n" -" println!(\"Main: got {msg}\");\n" -" }\n" -"}\n" -"```" +#: src/concurrency/channels/unbounded.md:16 +#: src/concurrency/channels/bounded.md:16 +msgid "\"Message {i}\"" +msgstr "" + +#: src/concurrency/channels/unbounded.md:17 +#: src/concurrency/channels/bounded.md:17 +msgid "\"{thread_id:?}: sent Message {i}\"" +msgstr "" + +#: src/concurrency/channels/unbounded.md:19 +#: src/concurrency/channels/bounded.md:19 +msgid "\"{thread_id:?}: done\"" +msgstr "" + +#: src/concurrency/channels/unbounded.md:24 +#: src/concurrency/channels/bounded.md:24 +msgid "\"Main: got {msg}\"" msgstr "" #: src/concurrency/channels/bounded.md:3 @@ -18877,33 +15724,6 @@ msgid "" "With bounded (synchronous) channels, `send` can block the current thread:" msgstr "Con canales limitados (síncronos), `send` puede bloquear el hilo:" -#: src/concurrency/channels/bounded.md:5 -msgid "" -"```rust,editable\n" -"use std::sync::mpsc;\n" -"use std::thread;\n" -"use std::time::Duration;\n" -"\n" -"fn main() {\n" -" let (tx, rx) = mpsc::sync_channel(3);\n" -"\n" -" thread::spawn(move || {\n" -" let thread_id = thread::current().id();\n" -" for i in 1..10 {\n" -" tx.send(format!(\"Message {i}\")).unwrap();\n" -" println!(\"{thread_id:?}: sent Message {i}\");\n" -" }\n" -" println!(\"{thread_id:?}: done\");\n" -" });\n" -" thread::sleep(Duration::from_millis(100));\n" -"\n" -" for msg in rx.iter() {\n" -" println!(\"Main: got {msg}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/concurrency/channels/bounded.md:31 msgid "" "Calling `send` will block the current thread until there is space in the " @@ -18936,8 +15756,12 @@ msgid "`Send` and `Sync`" msgstr "`Send` y `Sync`" #: src/concurrency/send-sync.md:3 +#, fuzzy +#| msgid "" +#| "How does Rust know to forbid shared access across thread? The answer is " +#| "in two traits:" msgid "" -"How does Rust know to forbid shared access across thread? The answer is in " +"How does Rust know to forbid shared access across threads? The answer is in " "two traits:" msgstr "" "¿Cómo sabe Rust que debe prohibir el acceso compartido entre hilos? La " @@ -19143,9 +15967,13 @@ msgstr "" "mover a otro hilo:" #: src/concurrency/send-sync/examples.md:31 +#, fuzzy +#| msgid "" +#| "`MutexGuard`: Uses OS level primitives which must be deallocated on " +#| "the thread which created them." msgid "" -"`MutexGuard`: Uses OS level primitives which must be deallocated on the " -"thread which created them." +"`MutexGuard`: Uses OS level primitives which must be deallocated on " +"the thread which created them." msgstr "" "`MutexGuard`: utiliza primitivos de nivel SO que se deben desasignar en " "el hilo que los creó." @@ -19213,27 +16041,14 @@ msgstr "" "[`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) permite el " "acceso compartido de solo lectura a través de `Arc::clone`:" -#: src/concurrency/shared_state/arc.md:5 -msgid "" -"```rust,editable\n" -"use std::thread;\n" -"use std::sync::Arc;\n" -"\n" -"fn main() {\n" -" let v = Arc::new(vec![10, 20, 30]);\n" -" let mut handles = Vec::new();\n" -" for _ in 1..5 {\n" -" let v = Arc::clone(&v);\n" -" handles.push(thread::spawn(move || {\n" -" let thread_id = thread::current().id();\n" -" println!(\"{thread_id:?}: {v:?}\");\n" -" }));\n" -" }\n" -"\n" -" handles.into_iter().for_each(|h| h.join().unwrap());\n" -" println!(\"v: {v:?}\");\n" -"}\n" -"```" +#: src/concurrency/shared_state/arc.md:16 +msgid "\"{thread_id:?}: {v:?}\"" +msgstr "" + +#: src/concurrency/shared_state/arc.md:21 +#: src/concurrency/shared_state/example.md:17 +#: src/concurrency/shared_state/example.md:45 +msgid "\"v: {v:?}\"" msgstr "" #: src/concurrency/shared_state/arc.md:29 @@ -19287,23 +16102,9 @@ msgstr "" "la exclusión mutua _y_ permite un acceso mutable a `T` a través de una " "interfaz de solo lectura:" -#: src/concurrency/shared_state/mutex.md:6 -msgid "" -"```rust,editable\n" -"use std::sync::Mutex;\n" -"\n" -"fn main() {\n" -" let v = Mutex::new(vec![10, 20, 30]);\n" -" println!(\"v: {:?}\", v.lock().unwrap());\n" -"\n" -" {\n" -" let mut guard = v.lock().unwrap();\n" -" guard.push(40);\n" -" }\n" -"\n" -" println!(\"v: {:?}\", v.lock().unwrap());\n" -"}\n" -"```" +#: src/concurrency/shared_state/mutex.md:11 +#: src/concurrency/shared_state/mutex.md:18 +msgid "\"v: {:?}\"" msgstr "" #: src/concurrency/shared_state/mutex.md:22 @@ -19376,56 +16177,14 @@ msgstr "" msgid "Let us see `Arc` and `Mutex` in action:" msgstr "Veamos cómo funcionan `Arc` y `Mutex`:" -#: src/concurrency/shared_state/example.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"use std::thread;\n" -"// use std::sync::{Arc, Mutex};\n" -"\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" let handle = thread::spawn(|| {\n" -" v.push(10);\n" -" });\n" -" v.push(1000);\n" -"\n" -" handle.join().unwrap();\n" -" println!(\"v: {v:?}\");\n" -"}\n" -"```" +#: src/concurrency/shared_state/example.md:6 +msgid "// use std::sync::{Arc, Mutex};\n" msgstr "" #: src/concurrency/shared_state/example.md:23 msgid "Possible solution:" msgstr "Solución posible:" -#: src/concurrency/shared_state/example.md:25 -msgid "" -"```rust,editable\n" -"use std::sync::{Arc, Mutex};\n" -"use std::thread;\n" -"\n" -"fn main() {\n" -" let v = Arc::new(Mutex::new(vec![10, 20, 30]));\n" -"\n" -" let v2 = Arc::clone(&v);\n" -" let handle = thread::spawn(move || {\n" -" let mut v2 = v2.lock().unwrap();\n" -" v2.push(10);\n" -" });\n" -"\n" -" {\n" -" let mut v = v.lock().unwrap();\n" -" v.push(1000);\n" -" }\n" -"\n" -" handle.join().unwrap();\n" -"\n" -" println!(\"v: {v:?}\");\n" -"}\n" -"```" -msgstr "" - #: src/concurrency/shared_state/example.md:49 msgid "Notable parts:" msgstr "Puntos a destacar:" @@ -19514,49 +16273,91 @@ msgstr "" "aparece más abajo en un archivo denominado `src/main.rs`, rellena los " "espacios en blanco y comprueba que `cargo run` no presenta interbloqueos:" -#: src/exercises/concurrency/dining-philosophers.md:19 +#: src/exercises/concurrency/dining-philosophers.md:28 +#: src/exercises/concurrency/dining-philosophers-async.md:23 msgid "" -"```rust,compile_fail\n" -"use std::sync::{mpsc, Arc, Mutex};\n" -"use std::thread;\n" -"use std::time::Duration;\n" -"\n" -"struct Fork;\n" -"\n" -"struct Philosopher {\n" -" name: String,\n" -" // left_fork: ...\n" +"// left_fork: ...\n" " // right_fork: ...\n" " // thoughts: ...\n" -"}\n" -"\n" -"impl Philosopher {\n" -" fn think(&self) {\n" -" self.thoughts\n" -" .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" -" .unwrap();\n" -" }\n" -"\n" -" fn eat(&self) {\n" -" // Pick up forks...\n" -" println!(\"{} is eating...\", &self.name);\n" -" thread::sleep(Duration::from_millis(10));\n" -" }\n" -"}\n" -"\n" -"static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" -"\n" -"fn main() {\n" -" // Create forks\n" -"\n" -" // Create philosophers\n" -"\n" -" // Make each of them think and eat 100 times\n" -"\n" -" // Output their thoughts\n" -"}\n" -"```" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:36 +#: src/exercises/concurrency/dining-philosophers-async.md:31 +#: src/exercises/concurrency/solutions-morning.md:24 +#: src/exercises/concurrency/solutions-afternoon.md:25 +msgid "\"Eureka! {} has a new idea!\"" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:41 +#: src/exercises/concurrency/dining-philosophers-async.md:36 +#: src/exercises/concurrency/solutions-afternoon.md:30 +msgid "// Pick up forks...\n" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:42 +#: src/exercises/concurrency/dining-philosophers-async.md:37 +#: src/exercises/concurrency/solutions-morning.md:33 +#: src/exercises/concurrency/solutions-afternoon.md:37 +msgid "\"{} is eating...\"" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:48 +#: src/exercises/concurrency/dining-philosophers-async.md:43 +#: src/exercises/concurrency/solutions-morning.md:39 +#: src/exercises/concurrency/solutions-afternoon.md:45 +#, fuzzy +#| msgid "HAL crates" +msgid "\"Socrates\"" +msgstr "Crates HAL" + +#: src/exercises/concurrency/dining-philosophers.md:48 +#: src/exercises/concurrency/dining-philosophers-async.md:43 +#: src/exercises/concurrency/solutions-morning.md:39 +#: src/exercises/concurrency/solutions-afternoon.md:45 +msgid "\"Hypatia\"" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:48 +#: src/exercises/concurrency/dining-philosophers-async.md:43 +#: src/exercises/concurrency/solutions-morning.md:39 +#: src/exercises/concurrency/solutions-afternoon.md:45 +msgid "\"Plato\"" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:48 +#: src/exercises/concurrency/dining-philosophers-async.md:43 +#: src/exercises/concurrency/solutions-morning.md:39 +#: src/exercises/concurrency/solutions-afternoon.md:45 +msgid "\"Aristotle\"" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:48 +#: src/exercises/concurrency/dining-philosophers-async.md:43 +#: src/exercises/concurrency/solutions-morning.md:39 +#: src/exercises/concurrency/solutions-afternoon.md:45 +msgid "\"Pythagoras\"" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:51 +#: src/exercises/concurrency/dining-philosophers-async.md:47 +#: src/exercises/concurrency/solutions-afternoon.md:49 +msgid "// Create forks\n" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:53 +#: src/exercises/concurrency/dining-philosophers-async.md:49 +#: src/exercises/concurrency/solutions-afternoon.md:53 +msgid "// Create philosophers\n" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:55 +msgid "// Make each of them think and eat 100 times\n" +msgstr "" + +#: src/exercises/concurrency/dining-philosophers.md:57 +#: src/exercises/concurrency/dining-philosophers-async.md:53 +#: src/exercises/concurrency/solutions-afternoon.md:88 +msgid "// Output their thoughts\n" msgstr "" #: src/exercises/concurrency/dining-philosophers.md:61 @@ -19594,15 +16395,6 @@ msgstr "" "reqwest/). Crea un proyecto de Cargo y aplica `reqwest` como una dependencia " "con:" -#: src/exercises/concurrency/link-checker.md:11 -msgid "" -"```shell\n" -"cargo new link-checker\n" -"cd link-checker\n" -"cargo add --features blocking,rustls-tls reqwest\n" -"```" -msgstr "" - #: src/exercises/concurrency/link-checker.md:17 msgid "" "If `cargo add` fails with `error: no such subcommand`, then please edit the " @@ -19619,13 +16411,6 @@ msgstr "" "También necesitarás una forma de encontrar enlaces. Podemos usar [`scraper`]" "(https://docs.rs/scraper/) para eso:" -#: src/exercises/concurrency/link-checker.md:22 -msgid "" -"```shell\n" -"cargo add scraper\n" -"```" -msgstr "" - #: src/exercises/concurrency/link-checker.md:26 msgid "" "Finally, we'll need some way of handling errors. We use [`thiserror`]" @@ -19634,16 +16419,6 @@ msgstr "" "Por último, necesitaremos algún método para gestionar los errores. Para " "ello, usaremos [`thiserror`](https://docs.rs/thiserror/):" -#: src/exercises/concurrency/link-checker.md:29 -msgid "" -"```shell\n" -"cargo add thiserror\n" -"```" -msgstr "" -"```shell\n" -"cargo add thiserror\n" -"```" - #: src/exercises/concurrency/link-checker.md:33 msgid "" "The `cargo add` calls will update the `Cargo.toml` file to look like this:" @@ -19693,154 +16468,48 @@ msgstr "" msgid "Your `src/main.rs` file should look something like this:" msgstr "El archivo `src/main.rs` debería tener un aspecto similar a este:" -#: src/exercises/concurrency/link-checker.md:57 -msgid "" -"```rust,compile_fail\n" -"use reqwest::{blocking::Client, Url};\n" -"use scraper::{Html, Selector};\n" -"use thiserror::Error;\n" -"\n" -"#[derive(Error, Debug)]\n" -"enum Error {\n" -" #[error(\"request error: {0}\")]\n" -" ReqwestError(#[from] reqwest::Error),\n" -" #[error(\"bad http response: {0}\")]\n" -" BadResponse(String),\n" -"}\n" -"\n" -"#[derive(Debug)]\n" -"struct CrawlCommand {\n" -" url: Url,\n" -" extract_links: bool,\n" -"}\n" -"\n" -"fn visit_page(client: &Client, command: &CrawlCommand) -> Result, " -"Error> {\n" -" println!(\"Checking {:#}\", command.url);\n" -" let response = client.get(command.url.clone()).send()?;\n" -" if !response.status().is_success() {\n" -" return Err(Error::BadResponse(response.status().to_string()));\n" -" }\n" -"\n" -" let mut link_urls = Vec::new();\n" -" if !command.extract_links {\n" -" return Ok(link_urls);\n" -" }\n" -"\n" -" let base_url = response.url().to_owned();\n" -" let body_text = response.text()?;\n" -" let document = Html::parse_document(&body_text);\n" -"\n" -" let selector = Selector::parse(\"a\").unwrap();\n" -" let href_values = document\n" -" .select(&selector)\n" -" .filter_map(|element| element.value().attr(\"href\"));\n" -" for href in href_values {\n" -" match base_url.join(href) {\n" -" Ok(link_url) => {\n" -" link_urls.push(link_url);\n" -" }\n" -" Err(err) => {\n" -" println!(\"On {base_url:#}: ignored unparsable {href:?}: " -"{err}\");\n" -" }\n" -" }\n" -" }\n" -" Ok(link_urls)\n" -"}\n" -"\n" -"fn main() {\n" -" let client = Client::new();\n" -" let start_url = Url::parse(\"https://www.google.org\").unwrap();\n" -" let crawl_command = CrawlCommand{ url: start_url, extract_links: " -"true };\n" -" match visit_page(&client, &crawl_command) {\n" -" Ok(links) => println!(\"Links: {links:#?}\"),\n" -" Err(err) => println!(\"Could not extract links: {err:#}\"),\n" -" }\n" -"}\n" -"```" +#: src/exercises/concurrency/link-checker.md:64 +#: src/exercises/concurrency/solutions-morning.md:95 +msgid "\"request error: {0}\"" +msgstr "" + +#: src/exercises/concurrency/link-checker.md:66 +#: src/exercises/concurrency/solutions-morning.md:97 +msgid "\"bad http response: {0}\"" +msgstr "" + +#: src/exercises/concurrency/link-checker.md:77 +#: src/exercises/concurrency/solutions-morning.md:108 +msgid "\"Checking {:#}\"" +msgstr "" + +#: src/exercises/concurrency/link-checker.md:95 +#: src/exercises/concurrency/solutions-morning.md:126 +msgid "\"href\"" +msgstr "" + +#: src/exercises/concurrency/link-checker.md:102 +#: src/exercises/concurrency/solutions-morning.md:133 +msgid "\"On {base_url:#}: ignored unparsable {href:?}: {err}\"" +msgstr "" + +#: src/exercises/concurrency/link-checker.md:111 +#: src/exercises/concurrency/solutions-morning.md:246 +msgid "\"https://www.google.org\"" +msgstr "" + +#: src/exercises/concurrency/link-checker.md:114 +msgid "\"Links: {links:#?}\"" +msgstr "" + +#: src/exercises/concurrency/link-checker.md:115 +msgid "\"Could not extract links: {err:#}\"" msgstr "" -"```rust,compile_fail\n" -"use reqwest::{blocking::Client, Url};\n" -"use scraper::{Html, Selector};\n" -"use thiserror::Error;\n" -"\n" -"#[derive(Error, Debug)]\n" -"enum Error {\n" -" #[error(\"request error: {0}\")]\n" -" ReqwestError(#[from] reqwest::Error),\n" -" #[error(\"bad http response: {0}\")]\n" -" BadResponse(String),\n" -"}\n" -"\n" -"#[derive(Debug)]\n" -"struct CrawlCommand {\n" -" url: Url,\n" -" extract_links: bool,\n" -"}\n" -"\n" -"fn visit_page(client: &Client, command: &CrawlCommand) -> Result, " -"Error> {\n" -" println!(\"Checking {:#}\", command.url);\n" -" let response = client.get(command.url.clone()).send()?;\n" -" if !response.status().is_success() {\n" -" return Err(Error::BadResponse(response.status().to_string()));\n" -" }\n" -"\n" -" let mut link_urls = Vec::new();\n" -" if !command.extract_links {\n" -" return Ok(link_urls);\n" -" }\n" -"\n" -" let base_url = response.url().to_owned();\n" -" let body_text = response.text()?;\n" -" let document = Html::parse_document(&body_text);\n" -"\n" -" let selector = Selector::parse(\"a\").unwrap();\n" -" let href_values = document\n" -" .select(&selector)\n" -" .filter_map(|element| element.value().attr(\"href\"));\n" -" for href in href_values {\n" -" match base_url.join(href) {\n" -" Ok(link_url) => {\n" -" link_urls.push(link_url);\n" -" }\n" -" Err(err) => {\n" -" println!(\"On {base_url:#}: ignored unparsable {href:?}: " -"{err}\");\n" -" }\n" -" }\n" -" }\n" -" Ok(link_urls)\n" -"}\n" -"\n" -"fn main() {\n" -" let client = Client::new();\n" -" let start_url = Url::parse(\"https://www.google.org\").unwrap();\n" -" let crawl_command = CrawlCommand{ url: start_url, extract_links: " -"true };\n" -" match visit_page(&client, &crawl_command) {\n" -" Ok(links) => println!(\"Links: {links:#?}\"),\n" -" Err(err) => println!(\"Could not extract links: {err:#}\"),\n" -" }\n" -"}\n" -"```" #: src/exercises/concurrency/link-checker.md:120 msgid "Run the code in `src/main.rs` with" msgstr "Ejecuta el código en `src/main.rs` con" -#: src/exercises/concurrency/link-checker.md:122 -msgid "" -"```shell\n" -"cargo run\n" -"```" -msgstr "" -"```shell\n" -"cargo run\n" -"```" - #: src/exercises/concurrency/link-checker.md:128 msgid "" "Use threads to check the links in parallel: send the URLs to be checked to a " @@ -19935,43 +16604,9 @@ msgstr "" "En general, el código asíncrono de Rust se parece mucho al código secuencial " "\"normal\":" -#: src/async/async-await.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"use futures::executor::block_on;\n" -"\n" -"async fn count_to(count: i32) {\n" -" for i in 1..=count {\n" -" println!(\"Count is: {i}!\");\n" -" }\n" -"}\n" -"\n" -"async fn async_main(count: i32) {\n" -" count_to(count).await;\n" -"}\n" -"\n" -"fn main() {\n" -" block_on(async_main(10));\n" -"}\n" -"```" +#: src/async/async-await.md:10 +msgid "\"Count is: {i}!\"" msgstr "" -"```rust,editable,compile_fail\n" -"use futures::executor::block_on;\n" -"\n" -"async fn count_to(count: i32) {\n" -" for i in 1..=count {\n" -" println!(\"Count is: {i}!\");\n" -" }\n" -"}\n" -"\n" -"async fn async_main(count: i32) {\n" -" count_to(count).await;\n" -"}\n" -"\n" -"fn main() {\n" -" block_on(async_main(10));\n" -"}\n" -"```" #: src/async/async-await.md:27 msgid "" @@ -20041,25 +16676,6 @@ msgstr "" "aún no se haya completado. Se puede sondear un futuro y `poll` devuelve un " "[`Poll`](https://doc.rust-lang.org/std/task/enum.Poll.html)." -#: src/async/futures.md:8 -msgid "" -"```rust\n" -"use std::pin::Pin;\n" -"use std::task::Context;\n" -"\n" -"pub trait Future {\n" -" type Output;\n" -" fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll;\n" -"}\n" -"\n" -"pub enum Poll {\n" -" Ready(T),\n" -" Pending,\n" -"}\n" -"```" -msgstr "" - #: src/async/futures.md:23 msgid "" "An async function returns an `impl Future`. It's also possible (but " @@ -20197,28 +16813,12 @@ msgstr "Una versión asíncrona de la biblioteca estándar." msgid "A large ecosystem of libraries." msgstr "Un amplio ecosistema de bibliotecas." -#: src/async/runtimes/tokio.md:10 -msgid "" -"```rust,editable,compile_fail\n" -"use tokio::time;\n" -"\n" -"async fn count_to(count: i32) {\n" -" for i in 1..=count {\n" -" println!(\"Count in task: {i}!\");\n" -" time::sleep(time::Duration::from_millis(5)).await;\n" -" }\n" -"}\n" -"\n" -"#[tokio::main]\n" -"async fn main() {\n" -" tokio::spawn(count_to(10));\n" -"\n" -" for i in 1..5 {\n" -" println!(\"Main task: {i}\");\n" -" time::sleep(time::Duration::from_millis(5)).await;\n" -" }\n" -"}\n" -"```" +#: src/async/runtimes/tokio.md:15 +msgid "\"Count in task: {i}!\"" +msgstr "" + +#: src/async/runtimes/tokio.md:25 +msgid "\"Main task: {i}\"" msgstr "" #: src/async/runtimes/tokio.md:33 @@ -20275,48 +16875,28 @@ msgstr "" "futuros secundarios , como una carrera de un temporizador y una operación de " "E/S." -#: src/async/tasks.md:10 -msgid "" -"```rust,compile_fail\n" -"use tokio::io::{self, AsyncReadExt, AsyncWriteExt};\n" -"use tokio::net::TcpListener;\n" -"\n" -"#[tokio::main]\n" -"async fn main() -> io::Result<()> {\n" -" let listener = TcpListener::bind(\"127.0.0.1:6142\").await?;\n" -"\tprintln!(\"listening on port 6142\");\n" -"\n" -" loop {\n" -" let (mut socket, addr) = listener.accept().await?;\n" -"\n" -" println!(\"connection from {addr:?}\");\n" -"\n" -" tokio::spawn(async move {\n" -" if let Err(e) = socket.write_all(b\"Who are you?\\n\").await {\n" -" println!(\"socket error: {e:?}\");\n" -" return;\n" -" }\n" -"\n" -" let mut buf = vec![0; 1024];\n" -" let reply = match socket.read(&mut buf).await {\n" -" Ok(n) => {\n" -" let name = std::str::from_utf8(&buf[..n]).unwrap()." -"trim();\n" -" format!(\"Thanks for dialing in, {name}!\\n\")\n" -" }\n" -" Err(e) => {\n" -" println!(\"socket error: {e:?}\");\n" -" return;\n" -" }\n" -" };\n" -"\n" -" if let Err(e) = socket.write_all(reply.as_bytes()).await {\n" -" println!(\"socket error: {e:?}\");\n" -" }\n" -" });\n" -" }\n" -"}\n" -"```" +#: src/async/tasks.md:16 +msgid "\"127.0.0.1:6142\"" +msgstr "" + +#: src/async/tasks.md:17 +msgid "\"listening on port 6142\"" +msgstr "" + +#: src/async/tasks.md:22 +msgid "\"connection from {addr:?}\"" +msgstr "" + +#: src/async/tasks.md:25 +msgid "b\"Who are you?\\n\"" +msgstr "" + +#: src/async/tasks.md:26 src/async/tasks.md:37 src/async/tasks.md:43 +msgid "\"socket error: {e:?}\"" +msgstr "" + +#: src/async/tasks.md:34 +msgid "\"Thanks for dialing in, {name}!\\n\"" msgstr "" #: src/async/tasks.md:52 src/async/control-flow/join.md:36 @@ -20357,36 +16937,24 @@ msgid "" "Several crates have support for asynchronous channels. For instance `tokio`:" msgstr "Varios crates admiten canales asíncronos. Por ejemplo, `tokio`:" -#: src/async/channels.md:5 -msgid "" -"```rust,editable,compile_fail\n" -"use tokio::sync::mpsc::{self, Receiver};\n" -"\n" -"async fn ping_handler(mut input: Receiver<()>) {\n" -" let mut count: usize = 0;\n" -"\n" -" while let Some(_) = input.recv().await {\n" -" count += 1;\n" -" println!(\"Received {count} pings so far.\");\n" -" }\n" -"\n" -" println!(\"ping_handler complete\");\n" -"}\n" -"\n" -"#[tokio::main]\n" -"async fn main() {\n" -" let (sender, receiver) = mpsc::channel(32);\n" -" let ping_handler_task = tokio::spawn(ping_handler(receiver));\n" -" for i in 0..10 {\n" -" sender.send(()).await.expect(\"Failed to send ping.\");\n" -" println!(\"Sent {} pings so far.\", i + 1);\n" -" }\n" -"\n" -" drop(sender);\n" -" ping_handler_task.await.expect(\"Something went wrong in ping handler " -"task.\");\n" -"}\n" -"```" +#: src/async/channels.md:13 +msgid "\"Received {count} pings so far.\"" +msgstr "" + +#: src/async/channels.md:16 +msgid "\"ping_handler complete\"" +msgstr "" + +#: src/async/channels.md:24 +msgid "\"Failed to send ping.\"" +msgstr "" + +#: src/async/channels.md:25 +msgid "\"Sent {} pings so far.\"" +msgstr "" + +#: src/async/channels.md:29 +msgid "\"Something went wrong in ping handler task.\"" msgstr "" #: src/async/channels.md:35 @@ -20458,34 +17026,25 @@ msgstr "" "devuelve una colección de sus resultados. Es similar a `Promise.all` en " "JavaScript o `asyncio.gather` en Python." -#: src/async/control-flow/join.md:7 -msgid "" -"```rust,editable,compile_fail\n" -"use anyhow::Result;\n" -"use futures::future;\n" -"use reqwest;\n" -"use std::collections::HashMap;\n" -"\n" -"async fn size_of_page(url: &str) -> Result {\n" -" let resp = reqwest::get(url).await?;\n" -" Ok(resp.text().await?.len())\n" -"}\n" -"\n" -"#[tokio::main]\n" -"async fn main() {\n" -" let urls: [&str; 4] = [\n" -" \"https://google.com\",\n" -" \"https://httpbin.org/ip\",\n" -" \"https://play.rust-lang.org/\",\n" -" \"BAD_URL\",\n" -" ];\n" -" let futures_iter = urls.into_iter().map(size_of_page);\n" -" let results = future::join_all(futures_iter).await;\n" -" let page_sizes_dict: HashMap<&str, Result> =\n" -" urls.into_iter().zip(results.into_iter()).collect();\n" -" println!(\"{:?}\", page_sizes_dict);\n" -"}\n" -"```" +#: src/async/control-flow/join.md:21 +msgid "\"https://google.com\"" +msgstr "" + +#: src/async/control-flow/join.md:22 +msgid "\"https://httpbin.org/ip\"" +msgstr "" + +#: src/async/control-flow/join.md:23 +msgid "\"https://play.rust-lang.org/\"" +msgstr "" + +#: src/async/control-flow/join.md:24 +msgid "\"BAD_URL\"" +msgstr "" + +#: src/async/control-flow/join.md:30 +#: src/exercises/day-1/solutions-morning.md:78 +msgid "\"{:?}\"" msgstr "" #: src/async/control-flow/join.md:38 @@ -20545,54 +17104,28 @@ msgstr "" "future => statement`. Cuando `future` está listo, la instrucción se ejecuta " "con las variables de `pattern` vinculadas al resultado de `future`." -#: src/async/control-flow/select.md:13 -msgid "" -"```rust,editable,compile_fail\n" -"use tokio::sync::mpsc::{self, Receiver};\n" -"use tokio::time::{sleep, Duration};\n" -"\n" -"#[derive(Debug, PartialEq)]\n" -"enum Animal {\n" -" Cat { name: String },\n" -" Dog { name: String },\n" -"}\n" -"\n" -"async fn first_animal_to_finish_race(\n" -" mut cat_rcv: Receiver,\n" -" mut dog_rcv: Receiver,\n" -") -> Option {\n" -" tokio::select! {\n" -" cat_name = cat_rcv.recv() => Some(Animal::Cat { name: cat_name? }),\n" -" dog_name = dog_rcv.recv() => Some(Animal::Dog { name: dog_name? })\n" -" }\n" -"}\n" -"\n" -"#[tokio::main]\n" -"async fn main() {\n" -" let (cat_sender, cat_receiver) = mpsc::channel(32);\n" -" let (dog_sender, dog_receiver) = mpsc::channel(32);\n" -" tokio::spawn(async move {\n" -" sleep(Duration::from_millis(500)).await;\n" -" cat_sender\n" -" .send(String::from(\"Felix\"))\n" -" .await\n" -" .expect(\"Failed to send cat.\");\n" -" });\n" -" tokio::spawn(async move {\n" -" sleep(Duration::from_millis(50)).await;\n" -" dog_sender\n" -" .send(String::from(\"Rex\"))\n" -" .await\n" -" .expect(\"Failed to send dog.\");\n" -" });\n" -"\n" -" let winner = first_animal_to_finish_race(cat_receiver, dog_receiver)\n" -" .await\n" -" .expect(\"Failed to receive winner\");\n" -"\n" -" println!(\"Winner is {winner:?}\");\n" -"}\n" -"```" +#: src/async/control-flow/select.md:40 +msgid "\"Felix\"" +msgstr "" + +#: src/async/control-flow/select.md:42 +msgid "\"Failed to send cat.\"" +msgstr "" + +#: src/async/control-flow/select.md:47 +msgid "\"Rex\"" +msgstr "" + +#: src/async/control-flow/select.md:49 +msgid "\"Failed to send dog.\"" +msgstr "" + +#: src/async/control-flow/select.md:54 +msgid "\"Failed to receive winner\"" +msgstr "" + +#: src/async/control-flow/select.md:56 +msgid "\"Winner is {winner:?}\"" msgstr "" #: src/async/control-flow/select.md:62 @@ -20689,27 +17222,12 @@ msgstr "" "tareas. Una solución alternativa y sencilla es utilizar métodos asíncronos " "equivalentes siempre que sea posible." -#: src/async/pitfalls/blocking-executor.md:7 -msgid "" -"```rust,editable,compile_fail\n" -"use futures::future::join_all;\n" -"use std::time::Instant;\n" -"\n" -"async fn sleep_ms(start: &Instant, id: u64, duration_ms: u64) {\n" -" std::thread::sleep(std::time::Duration::from_millis(duration_ms));\n" -" println!(\n" -" \"future {id} slept for {duration_ms}ms, finished after {}ms\",\n" -" start.elapsed().as_millis()\n" -" );\n" -"}\n" -"\n" -"#[tokio::main(flavor = \"current_thread\")]\n" -"async fn main() {\n" -" let start = Instant::now();\n" -" let sleep_futures = (1..=10).map(|t| sleep_ms(&start, t, t * 10));\n" -" join_all(sleep_futures).await;\n" -"}\n" -"```" +#: src/async/pitfalls/blocking-executor.md:14 +msgid "\"future {id} slept for {duration_ms}ms, finished after {}ms\"" +msgstr "" + +#: src/async/pitfalls/blocking-executor.md:19 +msgid "\"current_thread\"" msgstr "" #: src/async/pitfalls/blocking-executor.md:29 @@ -20794,61 +17312,42 @@ msgstr "" "usa el mismo futuro varias veces en un `select!`, se suelen producir " "problemas en los valores fijados." -#: src/async/pitfalls/pin.md:12 +#: src/async/pitfalls/pin.md:16 msgid "" -"```rust,editable,compile_fail\n" -"use tokio::sync::{mpsc, oneshot};\n" -"use tokio::task::spawn;\n" -"use tokio::time::{sleep, Duration};\n" -"\n" "// A work item. In this case, just sleep for the given time and respond\n" "// with a message on the `respond_on` channel.\n" -"#[derive(Debug)]\n" -"struct Work {\n" -" input: u32,\n" -" respond_on: oneshot::Sender,\n" -"}\n" -"\n" -"// A worker which listens for work on a queue and performs it.\n" -"async fn worker(mut work_queue: mpsc::Receiver) {\n" -" let mut iterations = 0;\n" -" loop {\n" -" tokio::select! {\n" -" Some(work) = work_queue.recv() => {\n" -" sleep(Duration::from_millis(10)).await; // Pretend to work.\n" -" work.respond_on\n" -" .send(work.input * 1000)\n" -" .expect(\"failed to send response\");\n" -" iterations += 1;\n" -" }\n" -" // TODO: report number of iterations every 100ms\n" -" }\n" -" }\n" -"}\n" -"\n" -"// A requester which requests work and waits for it to complete.\n" -"async fn do_work(work_queue: &mpsc::Sender, input: u32) -> u32 {\n" -" let (tx, rx) = oneshot::channel();\n" -" work_queue\n" -" .send(Work {\n" -" input,\n" -" respond_on: tx,\n" -" })\n" -" .await\n" -" .expect(\"failed to send on work queue\");\n" -" rx.await.expect(\"failed waiting for response\")\n" -"}\n" -"\n" -"#[tokio::main]\n" -"async fn main() {\n" -" let (tx, rx) = mpsc::channel(10);\n" -" spawn(worker(rx));\n" -" for i in 0..100 {\n" -" let resp = do_work(&tx, i).await;\n" -" println!(\"work result for iteration {i}: {resp}\");\n" -" }\n" -"}\n" -"```" +msgstr "" + +#: src/async/pitfalls/pin.md:24 +msgid "// A worker which listens for work on a queue and performs it.\n" +msgstr "" + +#: src/async/pitfalls/pin.md:31 +msgid "// Pretend to work.\n" +msgstr "" + +#: src/async/pitfalls/pin.md:34 +msgid "\"failed to send response\"" +msgstr "" + +#: src/async/pitfalls/pin.md:37 +msgid "// TODO: report number of iterations every 100ms\n" +msgstr "" + +#: src/async/pitfalls/pin.md:41 +msgid "// A requester which requests work and waits for it to complete.\n" +msgstr "" + +#: src/async/pitfalls/pin.md:51 +msgid "\"failed to send on work queue\"" +msgstr "" + +#: src/async/pitfalls/pin.md:52 +msgid "\"failed waiting for response\"" +msgstr "" + +#: src/async/pitfalls/pin.md:61 +msgid "\"work result for iteration {i}: {resp}\"" msgstr "" #: src/async/pitfalls/pin.md:68 @@ -20881,19 +17380,6 @@ msgid "" msgstr "" "En su lugar, añade un `timeout_fut` que contenga ese futuro fuera de `loop`:" -#: src/async/pitfalls/pin.md:79 -msgid "" -"```rust,compile_fail\n" -"let mut timeout_fut = sleep(Duration::from_millis(100));\n" -"loop {\n" -" select! {\n" -" ..,\n" -" _ = timeout_fut => { println!(..); },\n" -" }\n" -"}\n" -"```" -msgstr "" - #: src/async/pitfalls/pin.md:88 msgid "" "This still doesn't work. Follow the compiler errors, adding `&mut` to the " @@ -20904,20 +17390,7 @@ msgstr "" "`timeout_fut` en `select!` para ir despejando el problema. A continuación, " "usa `Box::pin`:" -#: src/async/pitfalls/pin.md:92 -msgid "" -"```rust,compile_fail\n" -"let mut timeout_fut = Box::pin(sleep(Duration::from_millis(100)));\n" -"loop {\n" -" select! {\n" -" ..,\n" -" _ = &mut timeout_fut => { println!(..); },\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/async/pitfalls/pin.md:102 +#: src/async/pitfalls/pin.md:102 msgid "" "This compiles, but once the timeout expires it is `Poll::Ready` on every " "iteration (a fused future would help with this). Update to reset " @@ -20966,50 +17439,12 @@ msgstr "" "El crate [async_trait](https://docs.rs/async-trait/latest/async_trait/) " "proporciona una solución mediante una macro:" -#: src/async/pitfalls/async-traits.md:7 -msgid "" -"```rust,editable,compile_fail\n" -"use async_trait::async_trait;\n" -"use std::time::Instant;\n" -"use tokio::time::{sleep, Duration};\n" -"\n" -"#[async_trait]\n" -"trait Sleeper {\n" -" async fn sleep(&self);\n" -"}\n" -"\n" -"struct FixedSleeper {\n" -" sleep_ms: u64,\n" -"}\n" -"\n" -"#[async_trait]\n" -"impl Sleeper for FixedSleeper {\n" -" async fn sleep(&self) {\n" -" sleep(Duration::from_millis(self.sleep_ms)).await;\n" -" }\n" -"}\n" -"\n" -"async fn run_all_sleepers_multiple_times(sleepers: Vec>, " -"n_times: usize) {\n" -" for _ in 0..n_times {\n" -" println!(\"running all sleepers..\");\n" -" for sleeper in &sleepers {\n" -" let start = Instant::now();\n" -" sleeper.sleep().await;\n" -" println!(\"slept for {}ms\", start.elapsed().as_millis());\n" -" }\n" -" }\n" -"}\n" -"\n" -"#[tokio::main]\n" -"async fn main() {\n" -" let sleepers: Vec> = vec![\n" -" Box::new(FixedSleeper { sleep_ms: 50 }),\n" -" Box::new(FixedSleeper { sleep_ms: 100 }),\n" -" ];\n" -" run_all_sleepers_multiple_times(sleepers, 5).await;\n" -"}\n" -"```" +#: src/async/pitfalls/async-traits.md:30 +msgid "\"running all sleepers..\"" +msgstr "" + +#: src/async/pitfalls/async-traits.md:34 +msgid "\"slept for {}ms\"" msgstr "" #: src/async/pitfalls/async-traits.md:51 @@ -21056,72 +17491,18 @@ msgstr "" "incluso cuando se cancelen los futuros. Por ejemplo, no debería sufrir " "interbloqueos o perder datos." -#: src/async/pitfalls/cancellation.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"use std::io::{self, ErrorKind};\n" -"use std::time::Duration;\n" -"use tokio::io::{AsyncReadExt, AsyncWriteExt, DuplexStream};\n" -"\n" -"struct LinesReader {\n" -" stream: DuplexStream,\n" -"}\n" -"\n" -"impl LinesReader {\n" -" fn new(stream: DuplexStream) -> Self {\n" -" Self { stream }\n" -" }\n" -"\n" -" async fn next(&mut self) -> io::Result> {\n" -" let mut bytes = Vec::new();\n" -" let mut buf = [0];\n" -" while self.stream.read(&mut buf[..]).await? != 0 {\n" -" bytes.push(buf[0]);\n" -" if buf[0] == b'\\n' {\n" -" break;\n" -" }\n" -" }\n" -" if bytes.is_empty() {\n" -" return Ok(None)\n" -" }\n" -" let s = String::from_utf8(bytes)\n" -" .map_err(|_| io::Error::new(ErrorKind::InvalidData, \"not " -"UTF-8\"))?;\n" -" Ok(Some(s))\n" -" }\n" -"}\n" -"\n" -"async fn slow_copy(source: String, mut dest: DuplexStream) -> std::io::" -"Result<()> {\n" -" for b in source.bytes() {\n" -" dest.write_u8(b).await?;\n" -" tokio::time::sleep(Duration::from_millis(10)).await\n" -" }\n" -" Ok(())\n" -"}\n" -"\n" -"#[tokio::main]\n" -"async fn main() -> std::io::Result<()> {\n" -" let (client, server) = tokio::io::duplex(5);\n" -" let handle = tokio::spawn(slow_copy(\"hi\\nthere\\n\".to_owned(), " -"client));\n" -"\n" -" let mut lines = LinesReader::new(server);\n" -" let mut interval = tokio::time::interval(Duration::from_millis(60));\n" -" loop {\n" -" tokio::select! {\n" -" _ = interval.tick() => println!(\"tick!\"),\n" -" line = lines.next() => if let Some(l) = line? {\n" -" print!(\"{}\", l)\n" -" } else {\n" -" break\n" -" },\n" -" }\n" -" }\n" -" handle.await.unwrap()?;\n" -" Ok(())\n" -"}\n" -"```" +#: src/async/pitfalls/cancellation.md:35 +#, fuzzy +#| msgid "UTF-8" +msgid "\"not UTF-8\"" +msgstr "UTF-8" + +#: src/async/pitfalls/cancellation.md:51 +msgid "\"hi\\nthere\\n\"" +msgstr "" + +#: src/async/pitfalls/cancellation.md:57 +msgid "\"tick!\"" msgstr "" #: src/async/pitfalls/cancellation.md:72 @@ -21159,28 +17540,8 @@ msgstr "" "`LinesReader` se puede configurar para que no se cancele marcando `buf` como " "parte del _struct_:" -#: src/async/pitfalls/cancellation.md:83 -msgid "" -"```rust,compile_fail\n" -"struct LinesReader {\n" -" stream: DuplexStream,\n" -" bytes: Vec,\n" -" buf: [u8; 1],\n" -"}\n" -"\n" -"impl LinesReader {\n" -" fn new(stream: DuplexStream) -> Self {\n" -" Self { stream, bytes: Vec::new(), buf: [0] }\n" -" }\n" -" async fn next(&mut self) -> io::Result> {\n" -" // prefix buf and bytes with self.\n" -" // ...\n" -" let raw = std::mem::take(&mut self.bytes);\n" -" let s = String::from_utf8(raw)\n" -" // ...\n" -" }\n" -"}\n" -"```" +#: src/async/pitfalls/cancellation.md:95 +msgid "// prefix buf and bytes with self.\n" msgstr "" #: src/async/pitfalls/cancellation.md:104 @@ -21261,52 +17622,9 @@ msgstr "" "aparece más abajo en un archivo denominado `src/main.rs`, rellena los " "espacios en blanco y comprueba que `cargo run` no presenta interbloqueos:" -#: src/exercises/concurrency/dining-philosophers-async.md:13 -msgid "" -"```rust,compile_fail\n" -"use std::sync::Arc;\n" -"use tokio::time;\n" -"use tokio::sync::mpsc::{self, Sender};\n" -"use tokio::sync::Mutex;\n" -"\n" -"struct Fork;\n" -"\n" -"struct Philosopher {\n" -" name: String,\n" -" // left_fork: ...\n" -" // right_fork: ...\n" -" // thoughts: ...\n" -"}\n" -"\n" -"impl Philosopher {\n" -" async fn think(&self) {\n" -" self.thoughts\n" -" .send(format!(\"Eureka! {} has a new idea!\", &self.name))." -"await\n" -" .unwrap();\n" -" }\n" -"\n" -" async fn eat(&self) {\n" -" // Pick up forks...\n" -" println!(\"{} is eating...\", &self.name);\n" -" time::sleep(time::Duration::from_millis(5)).await;\n" -" }\n" -"}\n" -"\n" -"static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" -"\n" -"#[tokio::main]\n" -"async fn main() {\n" -" // Create forks\n" -"\n" -" // Create philosophers\n" -"\n" -" // Make them think and eat\n" -"\n" -" // Output their thoughts\n" -"}\n" -"```" +#: src/exercises/concurrency/dining-philosophers-async.md:51 +#: src/exercises/concurrency/solutions-afternoon.md:77 +msgid "// Make them think and eat\n" msgstr "" #: src/exercises/concurrency/dining-philosophers-async.md:57 @@ -21375,7 +17693,9 @@ msgid "Create a new Cargo project and add the following dependencies:" msgstr "Crea un proyecto de Cargo y añade las siguientes dependencias:" #: src/exercises/concurrency/chat-app.md:15 -msgid "`Cargo.toml`:" +#, fuzzy +#| msgid "`Cargo.toml`:" +msgid "_Cargo.toml_:" msgstr "`Cargo.toml`:" #: src/exercises/concurrency/chat-app.md:19 @@ -21497,82 +17817,47 @@ msgstr "" "tarea es completar estos archivos como se describe a continuación. " #: src/exercises/concurrency/chat-app.md:59 -#: src/exercises/concurrency/solutions-afternoon.md:123 -msgid "`src/bin/server.rs`:" +#: src/exercises/concurrency/solutions-afternoon.md:99 +#, fuzzy +#| msgid "`src/bin/server.rs`:" +msgid "_src/bin/server.rs_:" msgstr "`src/bin/server.rs`:" -#: src/exercises/concurrency/chat-app.md:63 -msgid "" -"```rust,compile_fail\n" -"use futures_util::sink::SinkExt;\n" -"use futures_util::stream::StreamExt;\n" -"use std::error::Error;\n" -"use std::net::SocketAddr;\n" -"use tokio::net::{TcpListener, TcpStream};\n" -"use tokio::sync::broadcast::{channel, Sender};\n" -"use tokio_websockets::{Message, ServerBuilder, WebsocketStream};\n" -"\n" -"async fn handle_connection(\n" -" addr: SocketAddr,\n" -" mut ws_stream: WebsocketStream,\n" -" bcast_tx: Sender,\n" -") -> Result<(), Box> {\n" -"\n" -" // TODO: For a hint, see the description of the task below.\n" -"\n" -"}\n" -"\n" -"#[tokio::main]\n" -"async fn main() -> Result<(), Box> {\n" -" let (bcast_tx, _) = channel(16);\n" -"\n" -" let listener = TcpListener::bind(\"127.0.0.1:2000\").await?;\n" -" println!(\"listening on port 2000\");\n" -"\n" -" loop {\n" -" let (socket, addr) = listener.accept().await?;\n" -" println!(\"New connection from {addr:?}\");\n" -" let bcast_tx = bcast_tx.clone();\n" -" tokio::spawn(async move {\n" -" // Wrap the raw TCP stream into a websocket.\n" -" let ws_stream = ServerBuilder::new().accept(socket).await?;\n" -"\n" -" handle_connection(addr, ws_stream, bcast_tx).await\n" -" });\n" -" }\n" -"}\n" -"```" +#: src/exercises/concurrency/chat-app.md:78 +#: src/exercises/concurrency/chat-app.md:125 +msgid "// TODO: For a hint, see the description of the task below.\n" +msgstr "" + +#: src/exercises/concurrency/chat-app.md:86 +#: src/exercises/concurrency/solutions-afternoon.md:149 +msgid "\"127.0.0.1:2000\"" +msgstr "" + +#: src/exercises/concurrency/chat-app.md:87 +#: src/exercises/concurrency/solutions-afternoon.md:150 +msgid "\"listening on port 2000\"" +msgstr "" + +#: src/exercises/concurrency/chat-app.md:91 +#: src/exercises/concurrency/solutions-afternoon.md:154 +msgid "\"New connection from {addr:?}\"" +msgstr "" + +#: src/exercises/concurrency/chat-app.md:94 +#: src/exercises/concurrency/solutions-afternoon.md:157 +msgid "// Wrap the raw TCP stream into a websocket.\n" msgstr "" #: src/exercises/concurrency/chat-app.md:103 -#: src/exercises/concurrency/solutions-afternoon.md:210 -msgid "`src/bin/client.rs`:" +#: src/exercises/concurrency/solutions-afternoon.md:166 +#, fuzzy +#| msgid "`src/bin/client.rs`:" +msgid "_src/bin/client.rs_:" msgstr "`src/bin/client.rs`:" -#: src/exercises/concurrency/chat-app.md:107 -msgid "" -"```rust,compile_fail\n" -"use futures_util::stream::StreamExt;\n" -"use futures_util::SinkExt;\n" -"use http::Uri;\n" -"use tokio::io::{AsyncBufReadExt, BufReader};\n" -"use tokio_websockets::{ClientBuilder, Message};\n" -"\n" -"#[tokio::main]\n" -"async fn main() -> Result<(), tokio_websockets::Error> {\n" -" let (mut ws_stream, _) =\n" -" ClientBuilder::from_uri(Uri::from_static(\"ws://127.0.0.1:2000\"))\n" -" .connect()\n" -" .await?;\n" -"\n" -" let stdin = tokio::io::stdin();\n" -" let mut stdin = BufReader::new(stdin).lines();\n" -"\n" -"\n" -" // TODO: For a hint, see the description of the task below.\n" -"\n" -"}\n" -"```" +#: src/exercises/concurrency/chat-app.md:117 +#: src/exercises/concurrency/solutions-afternoon.md:178 +msgid "\"ws://127.0.0.1:2000\"" msgstr "" #: src/exercises/concurrency/chat-app.md:130 @@ -21583,24 +17868,10 @@ msgstr "Ejecutar los binarios" msgid "Run the server with:" msgstr "Ejecuta el servidor con:" -#: src/exercises/concurrency/chat-app.md:133 -msgid "" -"```shell\n" -"cargo run --bin server\n" -"```" -msgstr "" - #: src/exercises/concurrency/chat-app.md:137 msgid "and the client with:" msgstr "y el cliente con:" -#: src/exercises/concurrency/chat-app.md:139 -msgid "" -"```shell\n" -"cargo run --bin client\n" -"```" -msgstr "" - #: src/exercises/concurrency/chat-app.md:145 msgid "Implement the `handle_connection` function in `src/bin/server.rs`." msgstr "Implementa la función `handle_connection` en `src/bin/server.rs`." @@ -21659,161 +17930,515 @@ msgstr "" "mejorarlo, [ponte en contacto con nosotros en GitHub](https://github.com/" "google/comprehensive-rust/discussions). Nos encantaría saber tu opinión." -#: src/other-resources.md:1 -msgid "Other Rust Resources" -msgstr "Otros recursos de Rust" +#: src/glossary.md:3 +msgid "" +"The following is a glossary which aims to give a short definition of many " +"Rust terms. For translations, this also serves to connect the term back to " +"the English original." +msgstr "" -#: src/other-resources.md:3 +#: src/glossary.md:30 msgid "" -"The Rust community has created a wealth of high-quality and free resources " -"online." +"allocate: \n" +"Dynamic memory allocation on [the heap](memory-management/stack-vs-heap.md)." msgstr "" -"La comunidad de Rust ha creado una gran cantidad de recursos online sin " -"coste y de gran calidad." -#: src/other-resources.md:6 -msgid "Official Documentation" -msgstr "Documentación oficial" +#: src/glossary.md:32 +msgid "argument:" +msgstr "" -#: src/other-resources.md:8 -msgid "The Rust project hosts many resources. These cover Rust in general:" +#: src/glossary.md:33 +msgid "" +"Bare-metal Rust: \n" +"Low-level Rust development, often deployed to a system without an operating " +"system. See [Bare-metal Rust](bare-metal.md)." msgstr "" -"El proyecto Rust cuenta con muchos recursos. Estos tratan sobre Rust en " -"general:" -#: src/other-resources.md:10 +#: src/glossary.md:36 msgid "" -"[The Rust Programming Language](https://doc.rust-lang.org/book/): the " -"canonical free book about Rust. Covers the language in detail and includes a " -"few projects for people to build." +"block: \n" +"See [Blocks](control-flow/blocks.md) and _scope_." msgstr "" -"[The Rust Programming Language](https://doc.rust-lang.org/book/): el libro " -"canónico sobre Rust sin coste alguno. Trata el lenguaje de forma detallada e " -"incluye algunos proyectos que los usuarios pueden compilar." -#: src/other-resources.md:13 +#: src/glossary.md:38 msgid "" -"[Rust By Example](https://doc.rust-lang.org/rust-by-example/): covers the " -"Rust syntax via a series of examples which showcase different constructs. " -"Sometimes includes small exercises where you are asked to expand on the code " -"in the examples." +"borrow: \n" +"See [Borrowing](ownership/borrowing.md)." msgstr "" -"[Rust by Example](https://doc.rust-lang.org/rust-by-example/): trata la " -"sintaxis de Rust a través de una serie de ejemplos que muestran distintas " -"construcciones. A veces incluye pequeños ejercicios en los que se te pide " -"que amplíes el código de los ejemplos." -#: src/other-resources.md:17 +#: src/glossary.md:40 msgid "" -"[Rust Standard Library](https://doc.rust-lang.org/std/): full documentation " -"of the standard library for Rust." +"borrow checker: \n" +"The part of the Rust compiler which checks that all borrows are valid." msgstr "" -"[La biblioteca estándar de Rust](https://doc.rust-lang.org/std/): " -"documentación completa de la biblioteca estándar de Rust." -#: src/other-resources.md:19 +#: src/glossary.md:42 msgid "" -"[The Rust Reference](https://doc.rust-lang.org/reference/): an incomplete " -"book which describes the Rust grammar and memory model." +"brace: \n" +"`{` and `}`. Also called _curly brace_, they delimit _blocks_." msgstr "" -"[The Rust Reference](https://doc.rust-lang.org/reference/): un libro " -"incompleto que describe la gramática y el modelo de memoria de Rust." -#: src/other-resources.md:22 -msgid "More specialized guides hosted on the official Rust site:" -msgstr "Consulta guías más especializadas en el sitio oficial de Rust:" +#: src/glossary.md:44 +msgid "build:" +msgstr "" -#: src/other-resources.md:24 +#: src/glossary.md:45 +msgid "call:" +msgstr "" + +#: src/glossary.md:46 msgid "" -"[The Rustonomicon](https://doc.rust-lang.org/nomicon/): covers unsafe Rust, " -"including working with raw pointers and interfacing with other languages " -"(FFI)." +"channel: \n" +"Used to safely pass messages [between threads](concurrency/channels.md)." msgstr "" -"[The Rustonomicon](https://doc.rust-lang.org/nomicon/): trata de Rust " -"inseguro, incluido cómo trabajar con punteros sin formato e interactuar con " -"otros lenguajes (FFI)." -#: src/other-resources.md:27 +#: src/glossary.md:48 msgid "" -"[Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/): " -"covers the new asynchronous programming model which was introduced after the " -"Rust Book was written." +"Comprehensive Rust 🦀: \n" +"The courses here are jointly called Comprehensive Rust 🦀." msgstr "" -"[Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/): " -"incluye el nuevo modelo de programación asíncrona que se introdujo después " -"de que se escribiera el libro de Rust." -#: src/other-resources.md:30 +#: src/glossary.md:50 +#, fuzzy +#| msgid "Concurrency: Morning" +msgid "concurrency:" +msgstr "Concurrencia: mañana" + +#: src/glossary.md:51 msgid "" -"[The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/): " -"an introduction to using Rust on embedded devices without an operating " -"system." +"Concurrency in Rust: \n" +"See [Concurrency in Rust](concurrency.md)." msgstr "" -"[The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/): " -"una introducción sobre el uso de Rust en dispositivos integrados sin sistema " -"operativo." -#: src/other-resources.md:33 -msgid "Unofficial Learning Material" -msgstr "Material de formación no oficial" +#: src/glossary.md:53 +#, fuzzy +#| msgid "Constant" +msgid "constant:" +msgstr "Constante" -#: src/other-resources.md:35 -msgid "A small selection of other guides and tutorial for Rust:" -msgstr "Una pequeña selección de otras guías y tutoriales sobre Rust:" +#: src/glossary.md:54 +#, fuzzy +#| msgid "Control Flow" +msgid "control flow:" +msgstr "Control de Flujo" -#: src/other-resources.md:37 -msgid "" -"[Learn Rust the Dangerous Way](http://cliffle.com/p/dangerust/): covers Rust " -"from the perspective of low-level C programmers." +#: src/glossary.md:55 +msgid "crash:" msgstr "" -"[Learn Rust the Dangerous Way](http://cliffle.com/p/dangerust/): trata Rust " -"desde la perspectiva de los programadores de C de bajo nivel." -#: src/other-resources.md:39 -msgid "" -"[Rust for Embedded C Programmers](https://docs.opentitan.org/doc/ug/" -"rust_for_c/): covers Rust from the perspective of developers who write " -"firmware in C." +#: src/glossary.md:56 +#, fuzzy +#| msgid "`Duration`" +msgid "enumeration:" +msgstr "`Duration`" + +#: src/glossary.md:57 +#, fuzzy +#| msgid "`Error`" +msgid "error:" +msgstr "`Error`" + +#: src/glossary.md:58 +#, fuzzy +#| msgid "Error Handling" +msgid "error handling:" +msgstr "Manejo de Errores" + +#: src/glossary.md:59 +#, fuzzy +#| msgid "Exercises" +msgid "exercise:" +msgstr "Ejercicios" + +#: src/glossary.md:60 +#, fuzzy +#| msgid "Functions" +msgid "function:" +msgstr "Funciones" + +#: src/glossary.md:61 +#, fuzzy +#| msgid "Garbage Collection" +msgid "garbage collector:" +msgstr "Recolección de memoria residual" + +#: src/glossary.md:62 +#, fuzzy +#| msgid "Generics" +msgid "generics:" +msgstr "Genéricos" + +#: src/glossary.md:63 +msgid "immutable:" msgstr "" -"[Rust for Embedded C Programmers](https://docs.opentitan.org/doc/ug/" -"rust_for_c/): explica Rust desde la perspectiva de los desarrolladores que " -"escriben _firmware_ en C." -#: src/other-resources.md:42 -msgid "" -"[Rust for professionals](https://overexact.com/rust-for-professionals/): " -"covers the syntax of Rust using side-by-side comparisons with other " -"languages such as C, C++, Java, JavaScript, and Python." +#: src/glossary.md:64 +#, fuzzy +#| msgid "Integration Tests" +msgid "integration test:" +msgstr "Pruebas de Integración" + +#: src/glossary.md:65 +msgid "keyword:" msgstr "" -"[Rust for professonals](https://overexact.com/rust-for-professionals/): " -"trata la sintaxis de Rust comparándola con otros lenguajes, como C, C++, " -"Java, JavaScript y Python." -#: src/other-resources.md:45 -msgid "" -"[Rust on Exercism](https://exercism.org/tracks/rust): 100+ exercises to help " -"you learn Rust." +#: src/glossary.md:66 +#, fuzzy +#| msgid "Library" +msgid "library:" +msgstr "Biblioteca" + +#: src/glossary.md:67 +msgid "macro:" msgstr "" -"[Rust on Exercism](https://exercism.org/tracks/rust): más de 100 ejercicios " -"para aprender Rust." -#: src/other-resources.md:47 -msgid "" -"[Ferrous Teaching Material](https://ferrous-systems.github.io/teaching-" -"material/index.html): a series of small presentations covering both basic " -"and advanced part of the Rust language. Other topics such as WebAssembly, " -"and async/await are also covered." +#: src/glossary.md:68 +#, fuzzy +#| msgid "Calling Unsafe Functions" +msgid "main function:" +msgstr "Llamar Funciones Unsafe (Inseguras)" + +#: src/glossary.md:69 +msgid "match:" msgstr "" -"[Ferrous Teaching Material](https://ferrous-systems.github.io/teaching-" -"material/index.html): una serie de pequeñas presentaciones que cubren tanto " -"la parte básica como la parte más avanzada del lenguaje Rust. También se " -"tratan otros temas como WebAssembly y async/await." -#: src/other-resources.md:52 -msgid "" -"[Beginner's Series to Rust](https://docs.microsoft.com/en-us/shows/beginners-" -"series-to-rust/) and [Take your first steps with Rust](https://docs." -"microsoft.com/en-us/learn/paths/rust-first-steps/): two Rust guides aimed at " +#: src/glossary.md:70 +#, fuzzy +#| msgid "Memory leaks." +msgid "memory leak:" +msgstr "Pérdidas de memoria." + +#: src/glossary.md:71 +#, fuzzy +#| msgid "Methods" +msgid "method:" +msgstr "Métodos" + +#: src/glossary.md:72 +#, fuzzy +#| msgid "Modules" +msgid "module:" +msgstr "Módulos" + +#: src/glossary.md:73 +msgid "move:" +msgstr "" + +#: src/glossary.md:74 +#, fuzzy +#| msgid "Can be mutable" +msgid "mutable:" +msgstr "Puede ser mutable" + +#: src/glossary.md:75 +#, fuzzy +#| msgid "Ownership" +msgid "ownership:" +msgstr "Ownership" + +#: src/glossary.md:76 +msgid "panic:" +msgstr "" + +#: src/glossary.md:77 +msgid "parameter:" +msgstr "" + +#: src/glossary.md:78 +msgid "pattern:" +msgstr "" + +#: src/glossary.md:79 +msgid "payload:" +msgstr "" + +#: src/glossary.md:80 +msgid "program:" +msgstr "" + +#: src/glossary.md:81 +msgid "programming language:" +msgstr "" + +#: src/glossary.md:82 +#, fuzzy +#| msgid "Driver" +msgid "receiver:" +msgstr "Conductor" + +#: src/glossary.md:83 +msgid "reference counting:" +msgstr "" + +#: src/glossary.md:84 +msgid "return:" +msgstr "" + +#: src/glossary.md:85 +#, fuzzy +#| msgid "Rustdoc" +msgid "Rust:" +msgstr "Rustdoc" + +#: src/glossary.md:86 +msgid "" +"Rust Fundamentals: \n" +"Days 1 to 3 of this course." +msgstr "" + +#: src/glossary.md:88 +msgid "" +"Rust in Android: \n" +"See [Rust in Android](android.md)." +msgstr "" + +#: src/glossary.md:90 +msgid "safe:" +msgstr "" + +#: src/glossary.md:91 +msgid "scope:" +msgstr "" + +#: src/glossary.md:92 +#, fuzzy +#| msgid "Standard Library" +msgid "standard library:" +msgstr "Biblioteca estándar" + +#: src/glossary.md:93 +#, fuzzy +#| msgid "`static`" +msgid "static:" +msgstr "`static`" + +#: src/glossary.md:94 +#, fuzzy +#| msgid "String" +msgid "string:" +msgstr "String" + +#: src/glossary.md:95 +#, fuzzy +#| msgid "Structs" +msgid "struct:" +msgstr "Structs" + +#: src/glossary.md:96 +msgid "test:" +msgstr "" + +#: src/glossary.md:97 +#, fuzzy +#| msgid "Threads" +msgid "thread:" +msgstr "Hilos" + +#: src/glossary.md:98 +msgid "thread safety:" +msgstr "" + +#: src/glossary.md:99 +#, fuzzy +#| msgid "Traits" +msgid "trait:" +msgstr "Traits" + +#: src/glossary.md:100 +msgid "type:" +msgstr "" + +#: src/glossary.md:101 +#, fuzzy +#| msgid "Type Inference" +msgid "type inference:" +msgstr "Inferencia de tipos" + +#: src/glossary.md:102 +#, fuzzy +#| msgid "No undefined behavior at runtime:" +msgid "undefined behavior:" +msgstr "No hay comportamientos indefinidos en _runtime_:" + +#: src/glossary.md:103 +#, fuzzy +#| msgid "Unions" +msgid "union:" +msgstr "Uniones" + +#: src/glossary.md:104 +#, fuzzy +#| msgid "Unit Tests" +msgid "unit test:" +msgstr "Pruebas Unitarias" + +#: src/glossary.md:105 +#, fuzzy +#| msgid "Yes (unsafe)" +msgid "unsafe:" +msgstr "Sí (inseguro)" + +#: src/glossary.md:106 +#, fuzzy +#| msgid "Variables" +msgid "variable:\\" +msgstr "Variables" + +#: src/other-resources.md:1 +msgid "Other Rust Resources" +msgstr "Otros recursos de Rust" + +#: src/other-resources.md:3 +msgid "" +"The Rust community has created a wealth of high-quality and free resources " +"online." +msgstr "" +"La comunidad de Rust ha creado una gran cantidad de recursos online sin " +"coste y de gran calidad." + +#: src/other-resources.md:6 +msgid "Official Documentation" +msgstr "Documentación oficial" + +#: src/other-resources.md:8 +msgid "The Rust project hosts many resources. These cover Rust in general:" +msgstr "" +"El proyecto Rust cuenta con muchos recursos. Estos tratan sobre Rust en " +"general:" + +#: src/other-resources.md:10 +msgid "" +"[The Rust Programming Language](https://doc.rust-lang.org/book/): the " +"canonical free book about Rust. Covers the language in detail and includes a " +"few projects for people to build." +msgstr "" +"[The Rust Programming Language](https://doc.rust-lang.org/book/): el libro " +"canónico sobre Rust sin coste alguno. Trata el lenguaje de forma detallada e " +"incluye algunos proyectos que los usuarios pueden compilar." + +#: src/other-resources.md:13 +msgid "" +"[Rust By Example](https://doc.rust-lang.org/rust-by-example/): covers the " +"Rust syntax via a series of examples which showcase different constructs. " +"Sometimes includes small exercises where you are asked to expand on the code " +"in the examples." +msgstr "" +"[Rust by Example](https://doc.rust-lang.org/rust-by-example/): trata la " +"sintaxis de Rust a través de una serie de ejemplos que muestran distintas " +"construcciones. A veces incluye pequeños ejercicios en los que se te pide " +"que amplíes el código de los ejemplos." + +#: src/other-resources.md:17 +msgid "" +"[Rust Standard Library](https://doc.rust-lang.org/std/): full documentation " +"of the standard library for Rust." +msgstr "" +"[La biblioteca estándar de Rust](https://doc.rust-lang.org/std/): " +"documentación completa de la biblioteca estándar de Rust." + +#: src/other-resources.md:19 +msgid "" +"[The Rust Reference](https://doc.rust-lang.org/reference/): an incomplete " +"book which describes the Rust grammar and memory model." +msgstr "" +"[The Rust Reference](https://doc.rust-lang.org/reference/): un libro " +"incompleto que describe la gramática y el modelo de memoria de Rust." + +#: src/other-resources.md:22 +msgid "More specialized guides hosted on the official Rust site:" +msgstr "Consulta guías más especializadas en el sitio oficial de Rust:" + +#: src/other-resources.md:24 +msgid "" +"[The Rustonomicon](https://doc.rust-lang.org/nomicon/): covers unsafe Rust, " +"including working with raw pointers and interfacing with other languages " +"(FFI)." +msgstr "" +"[The Rustonomicon](https://doc.rust-lang.org/nomicon/): trata de Rust " +"inseguro, incluido cómo trabajar con punteros sin formato e interactuar con " +"otros lenguajes (FFI)." + +#: src/other-resources.md:27 +msgid "" +"[Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/): " +"covers the new asynchronous programming model which was introduced after the " +"Rust Book was written." +msgstr "" +"[Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/): " +"incluye el nuevo modelo de programación asíncrona que se introdujo después " +"de que se escribiera el libro de Rust." + +#: src/other-resources.md:30 +msgid "" +"[The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/): " +"an introduction to using Rust on embedded devices without an operating " +"system." +msgstr "" +"[The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/): " +"una introducción sobre el uso de Rust en dispositivos integrados sin sistema " +"operativo." + +#: src/other-resources.md:33 +msgid "Unofficial Learning Material" +msgstr "Material de formación no oficial" + +#: src/other-resources.md:35 +msgid "A small selection of other guides and tutorial for Rust:" +msgstr "Una pequeña selección de otras guías y tutoriales sobre Rust:" + +#: src/other-resources.md:37 +msgid "" +"[Learn Rust the Dangerous Way](http://cliffle.com/p/dangerust/): covers Rust " +"from the perspective of low-level C programmers." +msgstr "" +"[Learn Rust the Dangerous Way](http://cliffle.com/p/dangerust/): trata Rust " +"desde la perspectiva de los programadores de C de bajo nivel." + +#: src/other-resources.md:39 +msgid "" +"[Rust for Embedded C Programmers](https://docs.opentitan.org/doc/ug/" +"rust_for_c/): covers Rust from the perspective of developers who write " +"firmware in C." +msgstr "" +"[Rust for Embedded C Programmers](https://docs.opentitan.org/doc/ug/" +"rust_for_c/): explica Rust desde la perspectiva de los desarrolladores que " +"escriben _firmware_ en C." + +#: src/other-resources.md:42 +msgid "" +"[Rust for professionals](https://overexact.com/rust-for-professionals/): " +"covers the syntax of Rust using side-by-side comparisons with other " +"languages such as C, C++, Java, JavaScript, and Python." +msgstr "" +"[Rust for professonals](https://overexact.com/rust-for-professionals/): " +"trata la sintaxis de Rust comparándola con otros lenguajes, como C, C++, " +"Java, JavaScript y Python." + +#: src/other-resources.md:45 +msgid "" +"[Rust on Exercism](https://exercism.org/tracks/rust): 100+ exercises to help " +"you learn Rust." +msgstr "" +"[Rust on Exercism](https://exercism.org/tracks/rust): más de 100 ejercicios " +"para aprender Rust." + +#: src/other-resources.md:47 +msgid "" +"[Ferrous Teaching Material](https://ferrous-systems.github.io/teaching-" +"material/index.html): a series of small presentations covering both basic " +"and advanced part of the Rust language. Other topics such as WebAssembly, " +"and async/await are also covered." +msgstr "" +"[Ferrous Teaching Material](https://ferrous-systems.github.io/teaching-" +"material/index.html): una serie de pequeñas presentaciones que cubren tanto " +"la parte básica como la parte más avanzada del lenguaje Rust. También se " +"tratan otros temas como WebAssembly y async/await." + +#: src/other-resources.md:52 +msgid "" +"[Beginner's Series to Rust](https://docs.microsoft.com/en-us/shows/beginners-" +"series-to-rust/) and [Take your first steps with Rust](https://docs." +"microsoft.com/en-us/learn/paths/rust-first-steps/): two Rust guides aimed at " "new developers. The first is a set of 35 videos and the second is a set of " "11 modules which covers Rust syntax and basic constructs." msgstr "" @@ -21908,6 +18533,15 @@ msgstr "" "imagen de [CXX](https://cxx.rs/). Consulta el directorio `third_party/cxx/` " "para obtener más información, incluidos los términos de la licencia." +#: src/credits.md:34 +msgid "" +"The [Why Rust? - An Example in C](why-rust/an-example-in-c.md) section has " +"been taken from the presentation slides of [Colin Finck's Master Thesis]" +"(https://colinfinck.de/Master_Thesis_Colin_Finck.pdf). It has been " +"relicensed under the terms of the Apache 2.0 license for this course by the " +"author." +msgstr "" + #: src/exercises/solutions.md:3 msgid "You will find solutions to the exercises on the following pages." msgstr "En las páginas siguientes encontrarás las soluciones a los ejercicios." @@ -21922,16 +18556,6 @@ msgstr "" "com/google/comprehensive-rust/discussions). Ponte en contacto con nosotros " "si tienes una solución distinta o mejor de la que se presenta aquí." -#: src/exercises/solutions.md:10 -msgid "" -"**Note:** Please ignore the `// ANCHOR: label` and `// ANCHOR_END: label` " -"comments you see in the solutions. They are there to make it possible to re-" -"use parts of the solutions as the exercises." -msgstr "" -"**Nota:** Ignora los comentarios `// ANCHOR: label` y `// ANCHOR_END: label` " -"que aparecen en las soluciones. Están ahí para que sea posible reutilizar " -"algunas partes de las soluciones de los ejercicios." - #: src/exercises/day-1/solutions-morning.md:1 msgid "Day 1 Morning Exercises" msgstr "Día 1: Ejercicios de la Mañana" @@ -21940,86 +18564,20 @@ msgstr "Día 1: Ejercicios de la Mañana" msgid "([back to exercise](for-loops.md))" msgstr "([Volver al ejercicio](for-loops.md))" -#: src/exercises/day-1/solutions-morning.md:7 -msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: transpose\n" -"fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {\n" -" // ANCHOR_END: transpose\n" -" let mut result = [[0; 3]; 3];\n" -" for i in 0..3 {\n" -" for j in 0..3 {\n" -" result[j][i] = matrix[i][j];\n" -" }\n" -" }\n" -" return result;\n" -"}\n" -"\n" -"// ANCHOR: pretty_print\n" -"fn pretty_print(matrix: &[[i32; 3]; 3]) {\n" -" // ANCHOR_END: pretty_print\n" -" for row in matrix {\n" -" println!(\"{row:?}\");\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: tests\n" -"#[test]\n" -"fn test_transpose() {\n" -" let matrix = [\n" -" [101, 102, 103], //\n" -" [201, 202, 203],\n" -" [301, 302, 303],\n" -" ];\n" -" let transposed = transpose(matrix);\n" -" assert_eq!(\n" -" transposed,\n" -" [\n" -" [101, 201, 301], //\n" -" [102, 202, 302],\n" -" [103, 203, 303],\n" -" ]\n" -" );\n" -"}\n" -"// ANCHOR_END: tests\n" -"\n" -"// ANCHOR: main\n" -"fn main() {\n" -" let matrix = [\n" -" [101, 102, 103], // <-- the comment makes rustfmt add a newline\n" -" [201, 202, 203],\n" -" [301, 302, 303],\n" -" ];\n" -"\n" -" println!(\"matrix:\");\n" -" pretty_print(&matrix);\n" -"\n" -" let transposed = transpose(matrix);\n" -" println!(\"transposed:\");\n" -" pretty_print(&transposed);\n" -"}\n" -"```" +#: src/exercises/day-1/solutions-morning.md:20 +msgid "\"{row:?}\"" msgstr "" -#: src/exercises/day-1/solutions-morning.md:78 +#: src/exercises/day-1/solutions-morning.md:27 +#: src/exercises/day-1/solutions-morning.md:35 +msgid "//\n" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:57 msgid "Bonus question" msgstr "Pregunta extra" -#: src/exercises/day-1/solutions-morning.md:80 +#: src/exercises/day-1/solutions-morning.md:59 msgid "" "It requires more advanced concepts. It might seem that we could use a slice-" "of-slices (`&[&[i32]]`) as the input type to transpose and thus make our " @@ -22033,7 +18591,7 @@ msgstr "" "resultado devuelto no puede ser `&[&[i32]]`, ya que necesita ser el " "propietario de los datos que devuelve." -#: src/exercises/day-1/solutions-morning.md:82 +#: src/exercises/day-1/solutions-morning.md:61 msgid "" "You can attempt to use something like `Vec>`, but this doesn't work " "out-of-the-box either: it's hard to convert from `Vec>` to " @@ -22043,7 +18601,7 @@ msgstr "" "funciona desde el principio: es difícil cambiar de `Vec>` a " "`&[&[i32]]`, por lo que tampoco puedes usar `pretty_print` de forma sencilla." -#: src/exercises/day-1/solutions-morning.md:84 +#: src/exercises/day-1/solutions-morning.md:63 msgid "" "Once we get to traits and generics, we'll be able to use the [`std::convert::" "AsRef`](https://doc.rust-lang.org/std/convert/trait.AsRef.html) trait to " @@ -22053,37 +18611,27 @@ msgstr "" "convert::AsRef`](https://doc.rust-lang.org/std/convert/trait.AsRef.html) " "para abstraer cualquier elemento que se pueda referenciar, como un slice." -#: src/exercises/day-1/solutions-morning.md:86 -msgid "" -"```rust\n" -"use std::convert::AsRef;\n" -"use std::fmt::Debug;\n" -"\n" -"fn pretty_print(matrix: Matrix)\n" -"where\n" -" T: Debug,\n" -" // A line references a slice of items\n" -" Line: AsRef<[T]>,\n" -" // A matrix references a slice of lines\n" -" Matrix: AsRef<[Line]>\n" -"{\n" -" for row in matrix.as_ref() {\n" -" println!(\"{:?}\", row.as_ref());\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" // &[&[i32]]\n" -" pretty_print(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]);\n" -" // [[&str; 2]; 2]\n" -" pretty_print([[\"a\", \"b\"], [\"c\", \"d\"]]);\n" -" // Vec>\n" -" pretty_print(vec![vec![1, 2], vec![3, 4]]);\n" -"}\n" -"```" +#: src/exercises/day-1/solutions-morning.md:72 +msgid "// A line references a slice of items\n" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:74 +msgid "// A matrix references a slice of lines\n" msgstr "" -#: src/exercises/day-1/solutions-morning.md:113 +#: src/exercises/day-1/solutions-morning.md:83 +msgid "// &[&[i32]]\n" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:85 +msgid "// [[&str; 2]; 2]\n" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:87 +msgid "// Vec>\n" +msgstr "" + +#: src/exercises/day-1/solutions-morning.md:92 msgid "" "In addition, the type itself would not enforce that the child slices are of " "the same length, so such variable could contain an invalid matrix." @@ -22100,107 +18648,24 @@ msgstr "Día 1: Ejercicios de la Tarde" msgid "([back to exercise](luhn.md))" msgstr "([volver al ejercicio](luhn.md))" -#: src/exercises/day-1/solutions-afternoon.md:7 -msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: luhn\n" -"pub fn luhn(cc_number: &str) -> bool {\n" -" // ANCHOR_END: luhn\n" -" let mut digits_seen = 0;\n" -" let mut sum = 0;\n" -" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ')." -"enumerate() {\n" -" match ch.to_digit(10) {\n" -" Some(d) => {\n" -" sum += if i % 2 == 1 {\n" -" let dd = d * 2;\n" -" dd / 10 + dd % 10\n" -" } else {\n" -" d\n" -" };\n" -" digits_seen += 1;\n" -" }\n" -" None => return false,\n" -" }\n" -" }\n" -"\n" -" if digits_seen < 2 {\n" -" return false;\n" -" }\n" -"\n" -" sum % 10 == 0\n" -"}\n" -"\n" -"fn main() {\n" -" let cc_number = \"1234 5678 1234 5670\";\n" -" println!(\n" -" \"Is {cc_number} a valid credit card number? {}\",\n" -" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" -" );\n" -"}\n" -"\n" -"// ANCHOR: unit-tests\n" -"#[test]\n" -"fn test_non_digit_cc_number() {\n" -" assert!(!luhn(\"foo\"));\n" -" assert!(!luhn(\"foo 0 0\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_empty_cc_number() {\n" -" assert!(!luhn(\"\"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_single_digit_cc_number() {\n" -" assert!(!luhn(\"0\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_two_digit_cc_number() {\n" -" assert!(luhn(\" 0 0 \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_valid_cc_number() {\n" -" assert!(luhn(\"4263 9826 4026 9299\"));\n" -" assert!(luhn(\"4539 3195 0343 6467\"));\n" -" assert!(luhn(\"7992 7398 713\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_invalid_cc_number() {\n" -" assert!(!luhn(\"4223 9826 4026 9299\"));\n" -" assert!(!luhn(\"4539 3195 0343 6476\"));\n" -" assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}\n" -"// ANCHOR_END: unit-tests\n" -"```" +#: src/exercises/day-1/solutions-afternoon.md:40 +msgid "\"1234 5678 1234 5670\"" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:42 +msgid "\"Is {cc_number} a valid credit card number? {}\"" msgstr "" -#: src/exercises/day-1/solutions-afternoon.md:98 +#: src/exercises/day-1/solutions-afternoon.md:86 msgid "Pattern matching" msgstr "Correspondencia de Patrones" -#: src/exercises/day-1/solutions-afternoon.md:100 -msgid "TBD." +#: src/exercises/day-1/solutions-afternoon.md:211 +msgid "\"expr: {:?}\"" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:212 +msgid "\"result: {:?}\"" msgstr "" #: src/exercises/day-2/solutions-morning.md:1 @@ -22215,203 +18680,32 @@ msgstr "Diseñando una Librería" msgid "([back to exercise](book-library.md))" msgstr "([volver al ejercicio](book-library.md))" -#: src/exercises/day-2/solutions-morning.md:7 +#: src/exercises/day-2/solutions-morning.md:54 +msgid "\"{}, published in {}\"" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:59 msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: setup\n" -"struct Library {\n" -" books: Vec,\n" -"}\n" -"\n" -"struct Book {\n" -" title: String,\n" -" year: u16,\n" -"}\n" -"\n" -"impl Book {\n" -" // This is a constructor, used below.\n" -" fn new(title: &str, year: u16) -> Book {\n" -" Book {\n" -" title: String::from(title),\n" -" year,\n" -" }\n" -" }\n" -"}\n" -"\n" -"// Implement the methods below. Update the `self` parameter to\n" -"// indicate the method's required level of ownership over the object:\n" -"//\n" -"// - `&self` for shared read-only access,\n" -"// - `&mut self` for unique and mutable access,\n" -"// - `self` for unique access by value.\n" -"impl Library {\n" -" // ANCHOR_END: setup\n" -"\n" -" // ANCHOR: Library_new\n" -" fn new() -> Library {\n" -" // ANCHOR_END: Library_new\n" -" Library { books: Vec::new() }\n" -" }\n" -"\n" -" // ANCHOR: Library_len\n" -" //fn len(self) -> usize {\n" -" // todo!(\"Return the length of `self.books`\")\n" -" //}\n" -" // ANCHOR_END: Library_len\n" -" fn len(&self) -> usize {\n" -" self.books.len()\n" -" }\n" -"\n" -" // ANCHOR: Library_is_empty\n" -" //fn is_empty(self) -> bool {\n" -" // todo!(\"Return `true` if `self.books` is empty\")\n" -" //}\n" -" // ANCHOR_END: Library_is_empty\n" -" fn is_empty(&self) -> bool {\n" -" self.books.is_empty()\n" -" }\n" -"\n" -" // ANCHOR: Library_add_book\n" -" //fn add_book(self, book: Book) {\n" -" // todo!(\"Add a new book to `self.books`\")\n" -" //}\n" -" // ANCHOR_END: Library_add_book\n" -" fn add_book(&mut self, book: Book) {\n" -" self.books.push(book)\n" -" }\n" -"\n" -" // ANCHOR: Library_print_books\n" -" //fn print_books(self) {\n" -" // todo!(\"Iterate over `self.books` and each book's title and " -"year\")\n" -" //}\n" -" // ANCHOR_END: Library_print_books\n" -" fn print_books(&self) {\n" -" for book in &self.books {\n" -" println!(\"{}, published in {}\", book.title, book.year);\n" -" }\n" -" }\n" -"\n" -" // ANCHOR: Library_oldest_book\n" -" //fn oldest_book(self) -> Option<&Book> {\n" -" // todo!(\"Return a reference to the oldest book (if any)\")\n" -" //}\n" -" // ANCHOR_END: Library_oldest_book\n" -" fn oldest_book(&self) -> Option<&Book> {\n" -" // Using a closure and a built-in method:\n" +"// Using a closure and a built-in method:\n" " // self.books.iter().min_by_key(|book| book.year)\n" -"\n" -" // Longer hand-written solution:\n" -" let mut oldest: Option<&Book> = None;\n" -" for book in self.books.iter() {\n" -" if oldest.is_none() || book.year < oldest.unwrap().year {\n" -" oldest = Some(book);\n" -" }\n" -" }\n" -"\n" -" oldest\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: main\n" -"// This shows the desired behavior. Uncomment the code below and\n" -"// implement the missing methods. You will need to update the\n" -"// method signatures, including the \"self\" parameter! You may\n" -"// also need to update the variable bindings within main.\n" -"fn main() {\n" -" let library = Library::new();\n" -"\n" -" //println!(\"The library is empty: library.is_empty() -> {}\", library." -"is_empty());\n" -" //\n" -" //library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " -"1865));\n" -" //\n" -" //println!(\"The library is no longer empty: library.is_empty() -> {}\", " -"library.is_empty());\n" -" //\n" -" //\n" -" //library.print_books();\n" -" //\n" -" //match library.oldest_book() {\n" -" // Some(book) => println!(\"The oldest book is {}\", book.title),\n" -" // None => println!(\"The library is empty!\"),\n" -" //}\n" -" //\n" -" //println!(\"The library has {} books\", library.len());\n" -" //library.print_books();\n" -"}\n" -"// ANCHOR_END: main\n" -"\n" -"#[test]\n" -"fn test_library_len() {\n" -" let mut library = Library::new();\n" -" assert_eq!(library.len(), 0);\n" -" assert!(library.is_empty());\n" -"\n" -" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " -"1865));\n" -" assert_eq!(library.len(), 2);\n" -" assert!(!library.is_empty());\n" -"}\n" -"\n" -"#[test]\n" -"fn test_library_is_empty() {\n" -" let mut library = Library::new();\n" -" assert!(library.is_empty());\n" -"\n" -" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" assert!(!library.is_empty());\n" -"}\n" -"\n" -"#[test]\n" -"fn test_library_print_books() {\n" -" let mut library = Library::new();\n" -" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " -"1865));\n" -" // We could try and capture stdout, but let us just call the\n" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:62 +msgid "// Longer hand-written solution:\n" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:127 +msgid "" +"// We could try and capture stdout, but let us just call the\n" " // method to start with.\n" -" library.print_books();\n" -"}\n" -"\n" -"#[test]\n" -"fn test_library_oldest_book() {\n" -" let mut library = Library::new();\n" -" assert!(library.oldest_book().is_none());\n" -"\n" -" library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" assert_eq!(\n" -" library.oldest_book().map(|b| b.title.as_str()),\n" -" Some(\"Lord of the Rings\")\n" -" );\n" -"\n" -" library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " -"1865));\n" -" assert_eq!(\n" -" library.oldest_book().map(|b| b.title.as_str()),\n" -" Some(\"Alice's Adventures in Wonderland\")\n" -" );\n" -"}\n" -"```" msgstr "" +#: src/exercises/day-2/solutions-morning.md:153 +#, fuzzy +#| msgid "([back to exercise](chat-app.md))" +msgid "([back to exercise](health-statistics.md))" +msgstr "([volver al ejercicio](chat-app.md))" + #: src/exercises/day-2/solutions-afternoon.md:1 msgid "Day 2 Afternoon Exercises" msgstr "Día 2: Ejercicios de la tarde" @@ -22420,40 +18714,18 @@ msgstr "Día 2: Ejercicios de la tarde" msgid "([back to exercise](strings-iterators.md))" msgstr "([volver al ejercicio](strings-iterators.md))" -#: src/exercises/day-2/solutions-afternoon.md:7 +#: src/exercises/day-2/solutions-afternoon.md:10 +#: src/exercises/day-2/solutions-afternoon.md:12 +msgid "'/'" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:16 +msgid "\"*\"" +msgstr "" + +#: src/exercises/day-2/solutions-afternoon.md:22 msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: prefix_matches\n" -"pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" -" // ANCHOR_END: prefix_matches\n" -"\n" -" let mut request_segments = request_path.split('/');\n" -"\n" -" for prefix_segment in prefix.split('/') {\n" -" let Some(request_segment) = request_segments.next() else {\n" -" return false;\n" -" };\n" -" if request_segment != prefix_segment && prefix_segment != \"*\" {\n" -" return false;\n" -" }\n" -" }\n" -" true\n" -"\n" -" // Alternatively, Iterator::zip() lets us iterate simultaneously over " +"// Alternatively, Iterator::zip() lets us iterate simultaneously over " "prefix\n" " // and request segments. The zip() iterator is finished as soon as one " "of\n" @@ -22464,49 +18736,6 @@ msgid "" " // to produce an iterator that returns Some(str) for each pattern " "segments,\n" " // and then returns None indefinitely.\n" -"}\n" -"\n" -"// ANCHOR: unit-tests\n" -"#[test]\n" -"fn test_matches_without_wildcard() {\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/" -"abc-123\"));\n" -" assert!(prefix_matches(\"/v1/publishers\", \"/v1/publishers/abc/" -"books\"));\n" -"\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/publishersBooks\"));\n" -" assert!(!prefix_matches(\"/v1/publishers\", \"/v1/parent/" -"publishers\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_matches_with_wildcard() {\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books\"\n" -" ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/bar/books\"\n" -" ));\n" -" assert!(prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/books/book1\"\n" -" ));\n" -"\n" -" assert!(!prefix_matches(\"/v1/publishers/*/books\", \"/v1/" -"publishers\"));\n" -" assert!(!prefix_matches(\n" -" \"/v1/publishers/*/books\",\n" -" \"/v1/publishers/foo/booksByAuthor\"\n" -" ));\n" -"}\n" -"// ANCHOR_END: unit-tests\n" -"\n" -"fn main() {}\n" -"```" msgstr "" #: src/exercises/day-3/solutions-morning.md:1 @@ -22517,285 +18746,54 @@ msgstr "Día 3: Ejercicios de la mañana" msgid "([back to exercise](simple-gui.md))" msgstr "([volver al ejercicio](simple-gui.md))" -#: src/exercises/day-3/solutions-morning.md:7 +#: src/exercises/day-3/solutions-morning.md:75 +msgid "// Add 4 paddings for borders\n" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:87 msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: setup\n" -"pub trait Widget {\n" -" /// Natural width of `self`.\n" -" fn width(&self) -> usize;\n" -"\n" -" /// Draw the widget into a buffer.\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write);\n" -"\n" -" /// Draw the widget on standard output.\n" -" fn draw(&self) {\n" -" let mut buffer = String::new();\n" -" self.draw_into(&mut buffer);\n" -" println!(\"{buffer}\");\n" -" }\n" -"}\n" -"\n" -"pub struct Label {\n" -" label: String,\n" -"}\n" -"\n" -"impl Label {\n" -" fn new(label: &str) -> Label {\n" -" Label {\n" -" label: label.to_owned(),\n" -" }\n" -" }\n" -"}\n" -"\n" -"pub struct Button {\n" -" label: Label,\n" -" callback: Box,\n" -"}\n" -"\n" -"impl Button {\n" -" fn new(label: &str, callback: Box) -> Button {\n" -" Button {\n" -" label: Label::new(label),\n" -" callback,\n" -" }\n" -" }\n" -"}\n" -"\n" -"pub struct Window {\n" -" title: String,\n" -" widgets: Vec>,\n" -"}\n" -"\n" -"impl Window {\n" -" fn new(title: &str) -> Window {\n" -" Window {\n" -" title: title.to_owned(),\n" -" widgets: Vec::new(),\n" -" }\n" -" }\n" -"\n" -" fn add_widget(&mut self, widget: Box) {\n" -" self.widgets.push(widget);\n" -" }\n" -"\n" -" fn inner_width(&self) -> usize {\n" -" std::cmp::max(\n" -" self.title.chars().count(),\n" -" self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),\n" -" )\n" -" }\n" -"}\n" -"\n" -"// ANCHOR_END: setup\n" -"\n" -"// ANCHOR: Window-width\n" -"impl Widget for Window {\n" -" fn width(&self) -> usize {\n" -" // ANCHOR_END: Window-width\n" -" // Add 4 paddings for borders\n" -" self.inner_width() + 4\n" -" }\n" -"\n" -" // ANCHOR: Window-draw_into\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" // ANCHOR_END: Window-draw_into\n" -" let mut inner = String::new();\n" -" for widget in &self.widgets {\n" -" widget.draw_into(&mut inner);\n" -" }\n" -"\n" -" let inner_width = self.inner_width();\n" -"\n" -" // TODO: after learning about error handling, you can change\n" +"// TODO: after learning about error handling, you can change\n" " // draw_into to return Result<(), std::fmt::Error>. Then use\n" " // the ?-operator here instead of .unwrap().\n" -" writeln!(buffer, \"+-{:- usize {\n" -" // ANCHOR_END: Button-width\n" -" self.label.width() + 8 // add a bit of padding\n" -" }\n" -"\n" -" // ANCHOR: Button-draw_into\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" // ANCHOR_END: Button-draw_into\n" -" let width = self.width();\n" -" let mut label = String::new();\n" -" self.label.draw_into(&mut label);\n" -"\n" -" writeln!(buffer, \"+{:- usize {\n" -" // ANCHOR_END: Label-width\n" -" self.label\n" -" .lines()\n" -" .map(|line| line.chars().count())\n" -" .max()\n" -" .unwrap_or(0)\n" -" }\n" -"\n" -" // ANCHOR: Label-draw_into\n" -" fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {\n" -" // ANCHOR_END: Label-draw_into\n" -" writeln!(buffer, \"{}\", &self.label).unwrap();\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: main\n" -"fn main() {\n" -" let mut window = Window::new(\"Rust GUI Demo 1.23\");\n" -" window.add_widget(Box::new(Label::new(\"This is a small text GUI demo." -"\")));\n" -" window.add_widget(Box::new(Button::new(\n" -" \"Click me!\",\n" -" Box::new(|| println!(\"You clicked the button!\")),\n" -" )));\n" -" window.draw();\n" -"}\n" -"// ANCHOR_END: main\n" -"```" msgstr "" -#: src/exercises/day-3/solutions-morning.md:177 +#: src/exercises/day-3/solutions-morning.md:90 +#: src/exercises/day-3/solutions-morning.md:96 +msgid "\"+-{:- Point {\n" -" Point { x, y }\n" -" }\n" -"\n" -" pub fn magnitude(self) -> f64 {\n" -" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" -" }\n" -"\n" -" pub fn dist(self, other: Point) -> f64 {\n" -" (self - other).magnitude()\n" -" }\n" -"}\n" -"\n" -"impl std::ops::Add for Point {\n" -" type Output = Self;\n" -"\n" -" fn add(self, other: Self) -> Self::Output {\n" -" Self {\n" -" x: self.x + other.x,\n" -" y: self.y + other.y,\n" -" }\n" -" }\n" -"}\n" -"\n" -"impl std::ops::Sub for Point {\n" -" type Output = Self;\n" -"\n" -" fn sub(self, other: Self) -> Self::Output {\n" -" Self {\n" -" x: self.x - other.x,\n" -" y: self.y - other.y,\n" -" }\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: Polygon\n" -"pub struct Polygon {\n" -" // ANCHOR_END: Polygon\n" -" points: Vec,\n" -"}\n" -"\n" -"// ANCHOR: Polygon-impl\n" -"impl Polygon {\n" -" // ANCHOR_END: Polygon-impl\n" -" pub fn new() -> Polygon {\n" -" Polygon { points: Vec::new() }\n" -" }\n" -"\n" -" pub fn add_point(&mut self, point: Point) {\n" -" self.points.push(point);\n" -" }\n" -"\n" -" pub fn left_most_point(&self) -> Option {\n" -" self.points.iter().min_by_key(|p| p.x).copied()\n" -" }\n" -"\n" -" pub fn iter(&self) -> impl Iterator {\n" -" self.points.iter()\n" -" }\n" -"\n" -" pub fn length(&self) -> f64 {\n" -" if self.points.is_empty() {\n" -" return 0.0;\n" -" }\n" -"\n" -" let mut result = 0.0;\n" -" let mut last_point = self.points[0];\n" -" for point in &self.points[1..] {\n" -" result += last_point.dist(*point);\n" -" last_point = *point;\n" -" }\n" -" result += last_point.dist(self.points[0]);\n" -" result\n" -" // Alternatively, Iterator::zip() lets us iterate over the points as " -"pairs\n" +"// Alternatively, Iterator::zip() lets us iterate over the points as pairs\n" " // but we need to pair each point with the next one, and the last " "point\n" " // with the first point. The zip() iterator is finished as soon as " @@ -22805,135 +18803,6 @@ msgid "" " // with Iterator::skip to create the second iterator for the zip and " "using map \n" " // and sum to calculate the total length.\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: Circle\n" -"pub struct Circle {\n" -" // ANCHOR_END: Circle\n" -" center: Point,\n" -" radius: i32,\n" -"}\n" -"\n" -"// ANCHOR: Circle-impl\n" -"impl Circle {\n" -" // ANCHOR_END: Circle-impl\n" -" pub fn new(center: Point, radius: i32) -> Circle {\n" -" Circle { center, radius }\n" -" }\n" -"\n" -" pub fn circumference(&self) -> f64 {\n" -" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" -" }\n" -"\n" -" pub fn dist(&self, other: &Self) -> f64 {\n" -" self.center.dist(other.center)\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: Shape\n" -"pub enum Shape {\n" -" Polygon(Polygon),\n" -" Circle(Circle),\n" -"}\n" -"// ANCHOR_END: Shape\n" -"\n" -"impl From for Shape {\n" -" fn from(poly: Polygon) -> Self {\n" -" Shape::Polygon(poly)\n" -" }\n" -"}\n" -"\n" -"impl From for Shape {\n" -" fn from(circle: Circle) -> Self {\n" -" Shape::Circle(circle)\n" -" }\n" -"}\n" -"\n" -"impl Shape {\n" -" pub fn perimeter(&self) -> f64 {\n" -" match self {\n" -" Shape::Polygon(poly) => poly.length(),\n" -" Shape::Circle(circle) => circle.circumference(),\n" -" }\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: unit-tests\n" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;\n" -"\n" -" fn round_two_digits(x: f64) -> f64 {\n" -" (x * 100.0).round() / 100.0\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_magnitude() {\n" -" let p1 = Point::new(12, 13);\n" -" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_dist() {\n" -" let p1 = Point::new(10, 10);\n" -" let p2 = Point::new(14, 13);\n" -" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_add() {\n" -" let p1 = Point::new(16, 16);\n" -" let p2 = p1 + Point::new(-4, 3);\n" -" assert_eq!(p2, Point::new(12, 19));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_left_most_point() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -" assert_eq!(poly.left_most_point(), Some(p1));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_iter() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -"\n" -" let points = poly.iter().cloned().collect::>();\n" -" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_shape_perimeters() {\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(Point::new(12, 13));\n" -" poly.add_point(Point::new(17, 11));\n" -" poly.add_point(Point::new(16, 16));\n" -" let shapes = vec![\n" -" Shape::from(poly),\n" -" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" -" ];\n" -" let perimeters = shapes\n" -" .iter()\n" -" .map(Shape::perimeter)\n" -" .map(round_two_digits)\n" -" .collect::>();\n" -" assert_eq!(perimeters, vec![15.48, 31.42]);\n" -" }\n" -"}\n" -"// ANCHOR_END: unit-tests\n" -"\n" -"fn main() {}\n" -"```" msgstr "" #: src/exercises/day-3/solutions-afternoon.md:1 @@ -22944,196 +18813,81 @@ msgstr "Día 3: Ejercicios de la Tarde" msgid "([back to exercise](safe-ffi-wrapper.md))" msgstr "([volver al ejercicio](safe-ffi-wrapper.md))" -#: src/exercises/day-3/solutions-afternoon.md:7 +#: src/exercises/day-3/solutions-afternoon.md:77 +msgid "\"Invalid path: {err}\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:78 +msgid "// SAFETY: path.as_ptr() cannot be NULL.\n" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:81 +msgid "\"Could not open {:?}\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:91 msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: ffi\n" -"mod ffi {\n" -" use std::os::raw::{c_char, c_int};\n" -" #[cfg(not(target_os = \"macos\"))]\n" -" use std::os::raw::{c_long, c_ulong, c_ushort, c_uchar};\n" -"\n" -" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" -" #[repr(C)]\n" -" pub struct DIR {\n" -" _data: [u8; 0],\n" -" _marker: core::marker::PhantomData<(*mut u8, core::marker::" -"PhantomPinned)>,\n" -" }\n" -"\n" -" // Layout according to the Linux man page for readdir(3), where ino_t " -"and\n" -" // off_t are resolved according to the definitions in\n" -" // /usr/include/x86_64-linux-gnu/{sys/types.h, bits/typesizes.h}.\n" -" #[cfg(not(target_os = \"macos\"))]\n" -" #[repr(C)]\n" -" pub struct dirent {\n" -" pub d_ino: c_ulong,\n" -" pub d_off: c_long,\n" -" pub d_reclen: c_ushort,\n" -" pub d_type: c_uchar,\n" -" pub d_name: [c_char; 256],\n" -" }\n" -"\n" -" // Layout according to the macOS man page for dir(5).\n" -" #[cfg(all(target_os = \"macos\"))]\n" -" #[repr(C)]\n" -" pub struct dirent {\n" -" pub d_fileno: u64,\n" -" pub d_seekoff: u64,\n" -" pub d_reclen: u16,\n" -" pub d_namlen: u16,\n" -" pub d_type: u8,\n" -" pub d_name: [c_char; 1024],\n" -" }\n" -"\n" -" extern \"C\" {\n" -" pub fn opendir(s: *const c_char) -> *mut DIR;\n" -"\n" -" #[cfg(not(all(target_os = \"macos\", target_arch = \"x86_64\")))]\n" -" pub fn readdir(s: *mut DIR) -> *const dirent;\n" -"\n" -" // See https://github.com/rust-lang/libc/issues/414 and the section " -"on\n" -" // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2).\n" -" //\n" -" // \"Platforms that existed before these updates were available\" " -"refers\n" -" // to macOS (as opposed to iOS / wearOS / etc.) on Intel and " -"PowerPC.\n" -" #[cfg(all(target_os = \"macos\", target_arch = \"x86_64\"))]\n" -" #[link_name = \"readdir$INODE64\"]\n" -" pub fn readdir(s: *mut DIR) -> *const dirent;\n" -"\n" -" pub fn closedir(s: *mut DIR) -> c_int;\n" -" }\n" -"}\n" -"\n" -"use std::ffi::{CStr, CString, OsStr, OsString};\n" -"use std::os::unix::ffi::OsStrExt;\n" -"\n" -"#[derive(Debug)]\n" -"struct DirectoryIterator {\n" -" path: CString,\n" -" dir: *mut ffi::DIR,\n" -"}\n" -"// ANCHOR_END: ffi\n" -"\n" -"// ANCHOR: DirectoryIterator\n" -"impl DirectoryIterator {\n" -" fn new(path: &str) -> Result {\n" -" // Call opendir and return a Ok value if that worked,\n" -" // otherwise return Err with a message.\n" -" // ANCHOR_END: DirectoryIterator\n" -" let path = CString::new(path).map_err(|err| format!(\"Invalid path: " -"{err}\"))?;\n" -" // SAFETY: path.as_ptr() cannot be NULL.\n" -" let dir = unsafe { ffi::opendir(path.as_ptr()) };\n" -" if dir.is_null() {\n" -" Err(format!(\"Could not open {:?}\", path))\n" -" } else {\n" -" Ok(DirectoryIterator { path, dir })\n" -" }\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: Iterator\n" -"impl Iterator for DirectoryIterator {\n" -" type Item = OsString;\n" -" fn next(&mut self) -> Option {\n" -" // Keep calling readdir until we get a NULL pointer back.\n" -" // ANCHOR_END: Iterator\n" +"// Keep calling readdir until we get a NULL pointer back.\n" " // SAFETY: self.dir is never NULL.\n" -" let dirent = unsafe { ffi::readdir(self.dir) };\n" -" if dirent.is_null() {\n" -" // We have reached the end of the directory.\n" -" return None;\n" -" }\n" -" // SAFETY: dirent is not NULL and dirent.d_name is NUL\n" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:95 +msgid "// We have reached the end of the directory.\n" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:98 +msgid "" +"// SAFETY: dirent is not NULL and dirent.d_name is NUL\n" " // terminated.\n" -" let d_name = unsafe { CStr::from_ptr((*dirent).d_name.as_ptr()) };\n" -" let os_str = OsStr::from_bytes(d_name.to_bytes());\n" -" Some(os_str.to_owned())\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: Drop\n" -"impl Drop for DirectoryIterator {\n" -" fn drop(&mut self) {\n" -" // Call closedir as needed.\n" -" // ANCHOR_END: Drop\n" -" if !self.dir.is_null() {\n" -" // SAFETY: self.dir is not NULL.\n" -" if unsafe { ffi::closedir(self.dir) } != 0 {\n" -" panic!(\"Could not close {:?}\", self.path);\n" -" }\n" -" }\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: main\n" -"fn main() -> Result<(), String> {\n" -" let iter = DirectoryIterator::new(\".\")?;\n" -" println!(\"files: {:#?}\", iter.collect::>());\n" -" Ok(())\n" -"}\n" -"// ANCHOR_END: main\n" -"\n" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;\n" -" use std::error::Error;\n" -"\n" -" #[test]\n" -" fn test_nonexisting_directory() {\n" -" let iter = DirectoryIterator::new(\"no-such-directory\");\n" -" assert!(iter.is_err());\n" -" }\n" -"\n" -" #[test]\n" -" fn test_empty_directory() -> Result<(), Box> {\n" -" let tmp = tempfile::TempDir::new()?;\n" -" let iter = DirectoryIterator::new(\n" -" tmp.path().to_str().ok_or(\"Non UTF-8 character in path\")?,\n" -" )?;\n" -" let mut entries = iter.collect::>();\n" -" entries.sort();\n" -" assert_eq!(entries, &[\".\", \"..\"]);\n" -" Ok(())\n" -" }\n" -"\n" -" #[test]\n" -" fn test_nonempty_directory() -> Result<(), Box> {\n" -" let tmp = tempfile::TempDir::new()?;\n" -" std::fs::write(tmp.path().join(\"foo.txt\"), \"The Foo " -"Diaries\\n\")?;\n" -" std::fs::write(tmp.path().join(\"bar.png\"), \"\\n\")?;\n" -" std::fs::write(tmp.path().join(\"crab.rs\"), \"//! Crab\\n\")?;\n" -" let iter = DirectoryIterator::new(\n" -" tmp.path().to_str().ok_or(\"Non UTF-8 character in path\")?,\n" -" )?;\n" -" let mut entries = iter.collect::>();\n" -" entries.sort();\n" -" assert_eq!(entries, &[\".\", \"..\", \"bar.png\", \"crab.rs\", \"foo." -"txt\"]);\n" -" Ok(())\n" -" }\n" -"}\n" -"```" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:110 +msgid "// SAFETY: self.dir is not NULL.\n" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:112 +msgid "\"Could not close {:?}\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:131 +msgid "\"no-such-directory\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:139 +#: src/exercises/day-3/solutions-afternoon.md:154 +msgid "\"Non UTF-8 character in path\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:143 +#: src/exercises/day-3/solutions-afternoon.md:158 +msgid "\"..\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:150 +#: src/exercises/day-3/solutions-afternoon.md:158 +msgid "\"foo.txt\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:150 +msgid "\"The Foo Diaries\\n\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:151 +#: src/exercises/day-3/solutions-afternoon.md:158 +msgid "\"bar.png\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:151 +msgid "\"\\n\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:152 +#: src/exercises/day-3/solutions-afternoon.md:158 +msgid "\"crab.rs\"" +msgstr "" + +#: src/exercises/day-3/solutions-afternoon.md:152 +msgid "\"//! Crab\\n\"" msgstr "" #: src/exercises/bare-metal/solutions-morning.md:1 @@ -23144,171 +18898,30 @@ msgstr "Rust Bare Metal: Ejercicio de la Mañana" msgid "([back to exercise](compass.md))" msgstr "([volver al ejercicio](compass.md))" -#: src/exercises/bare-metal/solutions-morning.md:7 +#: src/exercises/bare-metal/solutions-morning.md:40 +msgid "// Set up the I2C controller and Inertial Measurement Unit.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-morning.md:41 +msgid "\"Setting up IMU...\"" +msgstr "" + +#: src/exercises/bare-metal/solutions-morning.md:49 +msgid "// Set up display and timer.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-morning.md:59 +msgid "// Read compass data and log it to the serial port.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-morning.md:67 +msgid "\"{},{},{}\\t{},{},{}\"" +msgstr "" + +#: src/exercises/bare-metal/solutions-morning.md:103 msgid "" -"```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: top\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"extern crate panic_halt as _;\n" -"\n" -"use core::fmt::Write;\n" -"use cortex_m_rt::entry;\n" -"// ANCHOR_END: top\n" -"use core::cmp::{max, min};\n" -"use lsm303agr::{AccelOutputDataRate, Lsm303agr, MagOutputDataRate};\n" -"use microbit::display::blocking::Display;\n" -"use microbit::hal::prelude::*;\n" -"use microbit::hal::twim::Twim;\n" -"use microbit::hal::uarte::{Baudrate, Parity, Uarte};\n" -"use microbit::hal::Timer;\n" -"use microbit::pac::twim0::frequency::FREQUENCY_A;\n" -"use microbit::Board;\n" -"\n" -"const COMPASS_SCALE: i32 = 30000;\n" -"const ACCELEROMETER_SCALE: i32 = 700;\n" -"\n" -"// ANCHOR: main\n" -"#[entry]\n" -"fn main() -> ! {\n" -" let board = Board::take().unwrap();\n" -"\n" -" // Configure serial port.\n" -" let mut serial = Uarte::new(\n" -" board.UARTE0,\n" -" board.uart.into(),\n" -" Parity::EXCLUDED,\n" -" Baudrate::BAUD115200,\n" -" );\n" -"\n" -" // Set up the I2C controller and Inertial Measurement Unit.\n" -" // ANCHOR_END: main\n" -" writeln!(serial, \"Setting up IMU...\").unwrap();\n" -" let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::" -"K100);\n" -" let mut imu = Lsm303agr::new_with_i2c(i2c);\n" -" imu.init().unwrap();\n" -" imu.set_mag_odr(MagOutputDataRate::Hz50).unwrap();\n" -" imu.set_accel_odr(AccelOutputDataRate::Hz50).unwrap();\n" -" let mut imu = imu.into_mag_continuous().ok().unwrap();\n" -"\n" -" // Set up display and timer.\n" -" let mut timer = Timer::new(board.TIMER0);\n" -" let mut display = Display::new(board.display_pins);\n" -"\n" -" let mut mode = Mode::Compass;\n" -" let mut button_pressed = false;\n" -"\n" -" // ANCHOR: loop\n" -" writeln!(serial, \"Ready.\").unwrap();\n" -"\n" -" loop {\n" -" // Read compass data and log it to the serial port.\n" -" // ANCHOR_END: loop\n" -" while !(imu.mag_status().unwrap().xyz_new_data\n" -" && imu.accel_status().unwrap().xyz_new_data)\n" -" {}\n" -" let compass_reading = imu.mag_data().unwrap();\n" -" let accelerometer_reading = imu.accel_data().unwrap();\n" -" writeln!(\n" -" serial,\n" -" \"{},{},{}\\t{},{},{}\",\n" -" compass_reading.x,\n" -" compass_reading.y,\n" -" compass_reading.z,\n" -" accelerometer_reading.x,\n" -" accelerometer_reading.y,\n" -" accelerometer_reading.z,\n" -" )\n" -" .unwrap();\n" -"\n" -" let mut image = [[0; 5]; 5];\n" -" let (x, y) = match mode {\n" -" Mode::Compass => (\n" -" scale(-compass_reading.x, -COMPASS_SCALE, COMPASS_SCALE, 0, " -"4) as usize,\n" -" scale(compass_reading.y, -COMPASS_SCALE, COMPASS_SCALE, 0, " -"4) as usize,\n" -" ),\n" -" Mode::Accelerometer => (\n" -" scale(\n" -" accelerometer_reading.x,\n" -" -ACCELEROMETER_SCALE,\n" -" ACCELEROMETER_SCALE,\n" -" 0,\n" -" 4,\n" -" ) as usize,\n" -" scale(\n" -" -accelerometer_reading.y,\n" -" -ACCELEROMETER_SCALE,\n" -" ACCELEROMETER_SCALE,\n" -" 0,\n" -" 4,\n" -" ) as usize,\n" -" ),\n" -" };\n" -" image[y][x] = 255;\n" -" display.show(&mut timer, image, 100);\n" -"\n" -" // If button A is pressed, switch to the next mode and briefly blink " -"all LEDs on.\n" -" if board.buttons.button_a.is_low().unwrap() {\n" -" if !button_pressed {\n" -" mode = mode.next();\n" -" display.show(&mut timer, [[255; 5]; 5], 200);\n" -" }\n" -" button_pressed = true;\n" -" } else {\n" -" button_pressed = false;\n" -" }\n" -" }\n" -"}\n" -"\n" -"#[derive(Copy, Clone, Debug, Eq, PartialEq)]\n" -"enum Mode {\n" -" Compass,\n" -" Accelerometer,\n" -"}\n" -"\n" -"impl Mode {\n" -" fn next(self) -> Self {\n" -" match self {\n" -" Self::Compass => Self::Accelerometer,\n" -" Self::Accelerometer => Self::Compass,\n" -" }\n" -" }\n" -"}\n" -"\n" -"fn scale(value: i32, min_in: i32, max_in: i32, min_out: i32, max_out: i32) -" -"> i32 {\n" -" let range_in = max_in - min_in;\n" -" let range_out = max_out - min_out;\n" -" cap(\n" -" min_out + range_out * (value - min_in) / range_in,\n" -" min_out,\n" -" max_out,\n" -" )\n" -"}\n" -"\n" -"fn cap(value: i32, min_value: i32, max_value: i32) -> i32 {\n" -" max(min_value, min(value, max_value))\n" -"}\n" -"```" +"// If button A is pressed, switch to the next mode and briefly blink all " +"LEDs on.\n" msgstr "" #: src/exercises/bare-metal/solutions-afternoon.md:5 @@ -23316,213 +18929,103 @@ msgid "([back to exercise](rtc.md))" msgstr "([volver al ejercicio](rtc.md))" #: src/exercises/bare-metal/solutions-afternoon.md:7 -msgid "`main.rs`:" +#, fuzzy +#| msgid "`main.rs`:" +msgid "_main.rs_:" msgstr "`main.rs`:" -#: src/exercises/bare-metal/solutions-afternoon.md:9 +#: src/exercises/bare-metal/solutions-afternoon.md:36 +msgid "/// Base address of the PL031 RTC.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:38 +msgid "/// The IRQ used by the PL031 RTC.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:57 msgid "" -"```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: top\n" -"#![no_main]\n" -"#![no_std]\n" -"\n" -"mod exceptions;\n" -"mod logger;\n" -"mod pl011;\n" -"// ANCHOR_END: top\n" -"mod pl031;\n" -"\n" -"use crate::pl031::Rtc;\n" -"use arm_gic::gicv3::{IntId, Trigger};\n" -"use arm_gic::{irq_enable, wfi};\n" -"use chrono::{TimeZone, Utc};\n" -"use core::hint::spin_loop;\n" -"// ANCHOR: imports\n" -"use crate::pl011::Uart;\n" -"use arm_gic::gicv3::GicV3;\n" -"use core::panic::PanicInfo;\n" -"use log::{error, info, trace, LevelFilter};\n" -"use smccc::psci::system_off;\n" -"use smccc::Hvc;\n" -"\n" -"/// Base addresses of the GICv3.\n" -"const GICD_BASE_ADDRESS: *mut u64 = 0x800_0000 as _;\n" -"const GICR_BASE_ADDRESS: *mut u64 = 0x80A_0000 as _;\n" -"\n" -"/// Base address of the primary PL011 UART.\n" -"const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;\n" -"// ANCHOR_END: imports\n" -"\n" -"/// Base address of the PL031 RTC.\n" -"const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;\n" -"/// The IRQ used by the PL031 RTC.\n" -"const PL031_IRQ: IntId = IntId::spi(2);\n" -"\n" -"// ANCHOR: main\n" -"#[no_mangle]\n" -"extern \"C\" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {\n" -" // Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 " -"device,\n" -" // and nothing else accesses that address range.\n" -" let uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };\n" -" logger::init(uart, LevelFilter::Trace).unwrap();\n" -"\n" -" info!(\"main({:#x}, {:#x}, {:#x}, {:#x})\", x0, x1, x2, x3);\n" -"\n" -" // Safe because `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the " -"base\n" -" // addresses of a GICv3 distributor and redistributor respectively, and\n" -" // nothing else accesses those address ranges.\n" -" let mut gic = unsafe { GicV3::new(GICD_BASE_ADDRESS, " -"GICR_BASE_ADDRESS) };\n" -" gic.setup();\n" -" // ANCHOR_END: main\n" -"\n" -" // Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 " -"device,\n" +"// Safe because `PL031_BASE_ADDRESS` is the base address of a PL031 device,\n" " // and nothing else accesses that address range.\n" -" let mut rtc = unsafe { Rtc::new(PL031_BASE_ADDRESS) };\n" -" let timestamp = rtc.read();\n" -" let time = Utc.timestamp_opt(timestamp.into(), 0).unwrap();\n" -" info!(\"RTC: {time}\");\n" -"\n" -" GicV3::set_priority_mask(0xff);\n" -" gic.set_interrupt_priority(PL031_IRQ, 0x80);\n" -" gic.set_trigger(PL031_IRQ, Trigger::Level);\n" -" irq_enable();\n" -" gic.enable_interrupt(PL031_IRQ, true);\n" -"\n" -" // Wait for 3 seconds, without interrupts.\n" -" let target = timestamp + 3;\n" -" rtc.set_match(target);\n" -" info!(\n" -" \"Waiting for {}\",\n" -" Utc.timestamp_opt(target.into(), 0).unwrap()\n" -" );\n" -" trace!(\n" -" \"matched={}, interrupt_pending={}\",\n" -" rtc.matched(),\n" -" rtc.interrupt_pending()\n" -" );\n" -" while !rtc.matched() {\n" -" spin_loop();\n" -" }\n" -" trace!(\n" -" \"matched={}, interrupt_pending={}\",\n" -" rtc.matched(),\n" -" rtc.interrupt_pending()\n" -" );\n" -" info!(\"Finished waiting\");\n" -"\n" -" // Wait another 3 seconds for an interrupt.\n" -" let target = timestamp + 6;\n" -" info!(\n" -" \"Waiting for {}\",\n" -" Utc.timestamp_opt(target.into(), 0).unwrap()\n" -" );\n" -" rtc.set_match(target);\n" -" rtc.clear_interrupt();\n" -" rtc.enable_interrupt(true);\n" -" trace!(\n" -" \"matched={}, interrupt_pending={}\",\n" -" rtc.matched(),\n" -" rtc.interrupt_pending()\n" -" );\n" -" while !rtc.interrupt_pending() {\n" -" wfi();\n" -" }\n" -" trace!(\n" -" \"matched={}, interrupt_pending={}\",\n" -" rtc.matched(),\n" -" rtc.interrupt_pending()\n" -" );\n" -" info!(\"Finished waiting\");\n" -"\n" -" // ANCHOR: main_end\n" -" system_off::().unwrap();\n" -"}\n" -"\n" -"#[panic_handler]\n" -"fn panic(info: &PanicInfo) -> ! {\n" -" error!(\"{info}\");\n" -" system_off::().unwrap();\n" -" loop {}\n" -"}\n" -"// ANCHOR_END: main_end\n" -"```" msgstr "" -#: src/exercises/bare-metal/solutions-afternoon.md:149 -msgid "`pl031.rs`:" +#: src/exercises/bare-metal/solutions-afternoon.md:62 +msgid "\"RTC: {time}\"" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:70 +msgid "// Wait for 3 seconds, without interrupts.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:74 +#: src/exercises/bare-metal/solutions-afternoon.md:95 +msgid "\"Waiting for {}\"" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:78 +#: src/exercises/bare-metal/solutions-afternoon.md:86 +#: src/exercises/bare-metal/solutions-afternoon.md:102 +#: src/exercises/bare-metal/solutions-afternoon.md:110 +msgid "\"matched={}, interrupt_pending={}\"" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:90 +#: src/exercises/bare-metal/solutions-afternoon.md:114 +msgid "\"Finished waiting\"" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:92 +msgid "// Wait another 3 seconds for an interrupt.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:127 +#, fuzzy +#| msgid "`pl031.rs`:" +msgid "_pl031.rs_:" msgstr "`pl031.rs`:" -#: src/exercises/bare-metal/solutions-afternoon.md:151 +#: src/exercises/bare-metal/solutions-afternoon.md:134 +msgid "/// Data register\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:136 +msgid "/// Match register\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:138 +msgid "/// Load register\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:140 +msgid "/// Control register\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:143 +msgid "/// Interrupt Mask Set or Clear register\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:146 +msgid "/// Raw Interrupt Status\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:149 +msgid "/// Masked Interrupt Status\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:152 +msgid "/// Interrupt Clear Register\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:156 +#, fuzzy +#| msgid "We will write a driver for the PL031 real-time clock device." +msgid "/// Driver for a PL031 real-time clock.\n" +msgstr "" +"Escribiremos un controlador para el dispositivo de reloj en tiempo real " +"PL031." + +#: src/exercises/bare-metal/solutions-afternoon.md:164 msgid "" -"```rust\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"use core::ptr::{addr_of, addr_of_mut};\n" -"\n" -"#[repr(C, align(4))]\n" -"struct Registers {\n" -" /// Data register\n" -" dr: u32,\n" -" /// Match register\n" -" mr: u32,\n" -" /// Load register\n" -" lr: u32,\n" -" /// Control register\n" -" cr: u8,\n" -" _reserved0: [u8; 3],\n" -" /// Interrupt Mask Set or Clear register\n" -" imsc: u8,\n" -" _reserved1: [u8; 3],\n" -" /// Raw Interrupt Status\n" -" ris: u8,\n" -" _reserved2: [u8; 3],\n" -" /// Masked Interrupt Status\n" -" mis: u8,\n" -" _reserved3: [u8; 3],\n" -" /// Interrupt Clear Register\n" -" icr: u8,\n" -" _reserved4: [u8; 3],\n" -"}\n" -"\n" -"/// Driver for a PL031 real-time clock.\n" -"#[derive(Debug)]\n" -"pub struct Rtc {\n" -" registers: *mut Registers,\n" -"}\n" -"\n" -"impl Rtc {\n" -" /// Constructs a new instance of the RTC driver for a PL031 device at " -"the\n" +"/// Constructs a new instance of the RTC driver for a PL031 device at the\n" " /// given base address.\n" " ///\n" " /// # Safety\n" @@ -23532,672 +19035,1130 @@ msgid "" " /// PL031 device, which must be mapped into the address space of the " "process\n" " /// as device memory and not have any other aliases.\n" -" pub unsafe fn new(base_address: *mut u32) -> Self {\n" -" Self {\n" -" registers: base_address as *mut Registers,\n" -" }\n" -" }\n" -"\n" -" /// Reads the current RTC value.\n" -" pub fn read(&self) -> u32 {\n" -" // Safe because we know that self.registers points to the control\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:178 +msgid "/// Reads the current RTC value.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:180 +#: src/exercises/bare-metal/solutions-afternoon.md:188 +#: src/exercises/bare-metal/solutions-afternoon.md:196 +#: src/exercises/bare-metal/solutions-afternoon.md:207 +#: src/exercises/bare-metal/solutions-afternoon.md:219 +#: src/exercises/bare-metal/solutions-afternoon.md:226 +msgid "" +"// Safe because we know that self.registers points to the control\n" " // registers of a PL031 device which is appropriately mapped.\n" -" unsafe { addr_of!((*self.registers).dr).read_volatile() }\n" -" }\n" -"\n" -" /// Writes a match value. When the RTC value matches this then an " -"interrupt\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:185 +msgid "" +"/// Writes a match value. When the RTC value matches this then an interrupt\n" " /// will be generated (if it is enabled).\n" -" pub fn set_match(&mut self, value: u32) {\n" -" // Safe because we know that self.registers points to the control\n" -" // registers of a PL031 device which is appropriately mapped.\n" -" unsafe { addr_of_mut!((*self.registers).mr).write_volatile(value) }\n" -" }\n" -"\n" -" /// Returns whether the match register matches the RTC value, whether or " +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:193 +msgid "" +"/// Returns whether the match register matches the RTC value, whether or " "not\n" " /// the interrupt is enabled.\n" -" pub fn matched(&self) -> bool {\n" -" // Safe because we know that self.registers points to the control\n" -" // registers of a PL031 device which is appropriately mapped.\n" -" let ris = unsafe { addr_of!((*self.registers).ris)." -"read_volatile() };\n" -" (ris & 0x01) != 0\n" -" }\n" -"\n" -" /// Returns whether there is currently an interrupt pending.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:202 +msgid "" +"/// Returns whether there is currently an interrupt pending.\n" " ///\n" " /// This should be true if and only if `matched` returns true and the\n" " /// interrupt is masked.\n" -" pub fn interrupt_pending(&self) -> bool {\n" -" // Safe because we know that self.registers points to the control\n" -" // registers of a PL031 device which is appropriately mapped.\n" -" let ris = unsafe { addr_of!((*self.registers).mis)." -"read_volatile() };\n" -" (ris & 0x01) != 0\n" -" }\n" -"\n" -" /// Sets or clears the interrupt mask.\n" +msgstr "" + +#: src/exercises/bare-metal/solutions-afternoon.md:213 +msgid "" +"/// Sets or clears the interrupt mask.\n" " ///\n" " /// When the mask is true the interrupt is enabled; when it is false " "the\n" " /// interrupt is disabled.\n" -" pub fn enable_interrupt(&mut self, mask: bool) {\n" -" let imsc = if mask { 0x01 } else { 0x00 };\n" -" // Safe because we know that self.registers points to the control\n" -" // registers of a PL031 device which is appropriately mapped.\n" -" unsafe { addr_of_mut!((*self.registers).imsc)." -"write_volatile(imsc) }\n" -" }\n" -"\n" -" /// Clears a pending interrupt, if any.\n" -" pub fn clear_interrupt(&mut self) {\n" -" // Safe because we know that self.registers points to the control\n" -" // registers of a PL031 device which is appropriately mapped.\n" -" unsafe { addr_of_mut!((*self.registers).icr).write_volatile(0x01) }\n" -" }\n" -"}\n" -"\n" -"// Safe because it just contains a pointer to device memory, which can be\n" -"// accessed from any context.\n" -"unsafe impl Send for Rtc {}\n" -"```" msgstr "" -#: src/exercises/concurrency/solutions-morning.md:1 -msgid "Concurrency Morning Exercise" -msgstr "Concurrencia: Ejercicios de la Mañana" +#: src/exercises/bare-metal/solutions-afternoon.md:224 +msgid "/// Clears a pending interrupt, if any.\n" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:1 +msgid "Concurrency Morning Exercise" +msgstr "Concurrencia: Ejercicios de la Mañana" + +#: src/exercises/concurrency/solutions-morning.md:5 +msgid "([back to exercise](dining-philosophers.md))" +msgstr "([volver al ejercicio](dining-philosophers.md))" + +#: src/exercises/concurrency/solutions-morning.md:29 +msgid "\"{} is trying to eat\"" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:53 +msgid "" +"// To avoid a deadlock, we have to break the symmetry\n" +" // somewhere. This will swap the forks without deinitializing\n" +" // either of them.\n" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:77 +msgid "\"{thought}\"" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:82 +msgid "Link Checker" +msgstr "Comprobador de Enlaces" + +#: src/exercises/concurrency/solutions-morning.md:84 +msgid "([back to exercise](link-checker.md))" +msgstr "([volver al ejercicio](link-checker.md))" + +#: src/exercises/concurrency/solutions-morning.md:155 +msgid "" +"/// Determine whether links within the given page should be extracted.\n" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:163 +msgid "" +"/// Mark the given page as visited, returning false if it had already\n" +" /// been visited.\n" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:189 +msgid "// The sender got dropped. No more commands coming in.\n" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:230 +msgid "\"Got crawling error: {:#}\"" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:248 +msgid "\"Bad URLs: {:#?}\"" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:1 +msgid "Concurrency Afternoon Exercise" +msgstr "Concurrencia: Ejercicios de la Tarde" + +#: src/exercises/concurrency/solutions-afternoon.md:5 +msgid "([back to exercise](dining-philosophers-async.md))" +msgstr "([volver al ejercicio](dining-philosophers-async.md))" + +#: src/exercises/concurrency/solutions-afternoon.md:32 +msgid "" +"// Add a delay before picking the second fork to allow the execution\n" +" // to transfer to another task\n" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:40 +msgid "// The locks are dropped here\n" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:60 +msgid "" +"// To avoid a deadlock, we have to break the symmetry\n" +" // somewhere. This will swap the forks without deinitializing\n" +" // either of them.\n" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:74 +msgid "// tx is dropped here, so we don't need to explicitly drop it later\n" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:90 +msgid "\"Here is a thought: {thought}\"" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:97 +msgid "([back to exercise](chat-app.md))" +msgstr "([volver al ejercicio](chat-app.md))" + +#: src/exercises/concurrency/solutions-afternoon.md:117 +msgid "\"Welcome to chat! Type a message\"" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:121 +#, fuzzy +#| msgid "" +#| "Hint: As before, use `tokio::select!` in a continuous loop for " +#| "concurrently performing two tasks: (1) reading user messages from " +#| "standard input and sending them to the server, and (2) receiving messages " +#| "from the server, and displaying them for the user." +msgid "" +"// A continuous loop for concurrently performing two tasks: (1) receiving\n" +" // messages from `ws_stream` and broadcasting them, and (2) receiving\n" +" // messages on `bcast_rx` and sending them to the client.\n" +msgstr "" +"Sugerencia: al igual que antes, usa `tokio::select!` en un bucle continuo " +"para realizar dos tareas simultáneamente: (1) leer los mensajes del usuario " +"desde la entrada estándar y enviarlos al servidor, y (2) recibir mensajes " +"del servidor y mostrárselos al usuario." + +#: src/exercises/concurrency/solutions-afternoon.md:130 +msgid "\"From client {addr:?} {text:?}\"" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:185 +msgid "// Continuous loop for concurrently sending and receiving messages.\n" +msgstr "" + +#: src/exercises/concurrency/solutions-afternoon.md:192 +msgid "\"From server: {}\"" +msgstr "" + +#, fuzzy +#~ msgid "Pattern Matching (TBD)" +#~ msgstr "Correspondencia de Patrones" + +#~ msgid "" +#~ "```shell\n" +#~ "cargo init concurrency\n" +#~ "cd concurrency\n" +#~ "cargo add tokio --features full\n" +#~ "cargo run\n" +#~ "```" +#~ msgstr "" +#~ "```shell\n" +#~ "cargo init concurrency\n" +#~ "cd concurrency\n" +#~ "cargo add tokio --features full\n" +#~ "cargo run\n" +#~ "```" + +#~ msgid "" +#~ "```shell\n" +#~ "sudo apt install cargo rust-src rustfmt\n" +#~ "```" +#~ msgstr "" +#~ "```shell\n" +#~ "sudo apt install cargo rust-src rustfmt\n" +#~ "```" + +#, fuzzy +#~ msgid "" +#~ "We suggest using [VS Code](https://code.visualstudio.com/) to edit the " +#~ "code (but any LSP compatible editor works with rust-analyzer[3](https://" +#~ "rust-analyzer.github.io/))." +#~ msgstr "" +#~ "Recomendamos usar [VS Code](https://code.visualstudio.com/) para editar " +#~ "el código (aunque cualquier editor compatible con LSP funciona con [rust-" +#~ "analyzer](https://rust-analyzer.github.io/))." + +#~ msgid "" +#~ "Some folks also like to use the [JetBrains](https://www.jetbrains.com/" +#~ "clion/) family of IDEs, which do their own analysis but have their own " +#~ "tradeoffs. If you prefer them, you can install the [Rust Plugin](https://" +#~ "www.jetbrains.com/rust/). Please take note that as of January 2023 " +#~ "debugging only works on the CLion version of the JetBrains IDEA suite." +#~ msgstr "" +#~ "A algunos compañeros también les gusta usar la familia [JetBrains]" +#~ "(https://www.jetbrains.com/clion/) de IDEs, que hacen sus propios " +#~ "análisis, pero también tienen inconvenientes. Si lo prefieres, puedes " +#~ "instalar el [Rust Plugin](https://www.jetbrains.com/rust/). Ten en cuenta " +#~ "que, a partir de enero del 2023, la depuración solo funciona en la " +#~ "versión CLion del paquete de JetBrains IDEA." + +#~ msgid "" +#~ "```rust,editable\n" +#~ "fn main() {\n" +#~ " println!(\"Edit me!\");\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable\n" +#~ "fn main() {\n" +#~ " println!(\"Edit me!\");\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```shell\n" +#~ "% rustc --version\n" +#~ "rustc 1.69.0 (84c898d65 2023-04-16)\n" +#~ "% cargo --version\n" +#~ "cargo 1.69.0 (6e9a83356 2023-04-12)\n" +#~ "```" +#~ msgstr "" +#~ "```shell\n" +#~ "% rustc --version\n" +#~ "rustc 1.69.0 (84c898d65 2023-04-16)\n" +#~ "% cargo --version\n" +#~ "cargo 1.69.0 (6e9a83356 2023-04-12)\n" +#~ "```" + +#~ msgid "" +#~ "```shell\n" +#~ "$ cargo new exercise\n" +#~ " Created binary (application) `exercise` package\n" +#~ "```" +#~ msgstr "" +#~ "```shell\n" +#~ "$ cargo new exercise\n" +#~ " Created binary (application) `exercise` package\n" +#~ "```" + +#~ msgid "" +#~ "```shell\n" +#~ "$ cd exercise\n" +#~ "$ cargo run\n" +#~ " Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +#~ " Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +#~ " Running `target/debug/exercise`\n" +#~ "Hello, world!\n" +#~ "```" +#~ msgstr "" +#~ "```shell\n" +#~ "$ cd exercise\n" +#~ "$ cargo run\n" +#~ " Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +#~ " Finished dev [unoptimized + debuginfo] target(s) in 0.75s\n" +#~ " Running `target/debug/exercise`\n" +#~ "Hola Mundo!\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "fn main() {\n" +#~ " println!(\"Edit me!\");\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "fn main() {\n" +#~ " println!(\"Edit me!\");\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```shell\n" +#~ "$ cargo run\n" +#~ " Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +#~ " Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +#~ " Running `target/debug/exercise`\n" +#~ "Edit me!\n" +#~ "```" +#~ msgstr "" +#~ "```shell\n" +#~ "$ cargo run\n" +#~ " Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)\n" +#~ " Finished dev [unoptimized + debuginfo] target(s) in 0.24s\n" +#~ " Running `target/debug/ejercicio`\n" +#~ "Modifícame!\n" +#~ "```" + +#~ msgid "" +#~ "```rust,editable\n" +#~ "fn main() {\n" +#~ " println!(\"Hello 🌍!\");\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable\n" +#~ "fn main() {\n" +#~ " println!(\"Hola 🌍!\");\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust,editable\n" +#~ "fn main() { // Program entry point\n" +#~ " let mut x: i32 = 6; // Mutable variable binding\n" +#~ " print!(\"{x}\"); // Macro for printing, like printf\n" +#~ " while x != 1 { // No parenthesis around expression\n" +#~ " if x % 2 == 0 { // Math like in other languages\n" +#~ " x = x / 2;\n" +#~ " } else {\n" +#~ " x = 3 * x + 1;\n" +#~ " }\n" +#~ " print!(\" -> {x}\");\n" +#~ " }\n" +#~ " println!();\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable\n" +#~ "fn main() { // Punto de entrada del programa\n" +#~ " let mut x: i32 = 6; // Variable mutable vinculante\n" +#~ " print!(\"{x}\"); // Macro para printing, como printf\n" +#~ " while x != 1 { // Sin paréntesis alrededor de las expresiones\n" +#~ " if x % 2 == 0 { // Operaciones matemáticas como en otros " +#~ "lenguajes\n" +#~ " x = x / 2;\n" +#~ " } else {\n" +#~ " x = 3 * x + 1;\n" +#~ " }\n" +#~ " print!(\" -> {x}\");\n" +#~ " }\n" +#~ " println!();\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust,editable,compile_fail\n" +#~ "fn new(width: u32, height: u32) -> Rectangle {\n" +#~ " Rectangle { width, height }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable,compile_fail\n" +#~ "fn new(width: u32, height: u32) -> Rectangle {\n" +#~ " Rectangle { width, height }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust,editable\n" +#~ "fn generate_random_number() -> i32 {\n" +#~ " // Implementation based on https://xkcd.com/221/\n" +#~ " 4 // Chosen by fair dice roll. Guaranteed to be random.\n" +#~ "}\n" +#~ "\n" +#~ "#[derive(Debug)]\n" +#~ "enum CoinFlip {\n" +#~ " Heads,\n" +#~ " Tails,\n" +#~ "}\n" +#~ "\n" +#~ "fn flip_coin() -> CoinFlip {\n" +#~ " let random_number = generate_random_number();\n" +#~ " if random_number % 2 == 0 {\n" +#~ " return CoinFlip::Heads;\n" +#~ " } else {\n" +#~ " return CoinFlip::Tails;\n" +#~ " }\n" +#~ "}\n" +#~ "\n" +#~ "fn main() {\n" +#~ " println!(\"You got: {:?}\", flip_coin());\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable\n" +#~ "fn generate_random_number() -> i32 {\n" +#~ " // Implementation based on https://xkcd.com/221/\n" +#~ " 4 // Chosen by fair dice roll. Guaranteed to be random.\n" +#~ "}\n" +#~ "\n" +#~ "#[derive(Debug)]\n" +#~ "enum CoinFlip {\n" +#~ " Heads,\n" +#~ " Tails,\n" +#~ "}\n" +#~ "\n" +#~ "fn flip_coin() -> CoinFlip {\n" +#~ " let random_number = generate_random_number();\n" +#~ " if random_number % 2 == 0 {\n" +#~ " return CoinFlip::Heads;\n" +#~ " } else {\n" +#~ " return CoinFlip::Tails;\n" +#~ " }\n" +#~ "}\n" +#~ "\n" +#~ "fn main() {\n" +#~ " println!(\"You got: {:?}\", flip_coin());\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```c++\n" +#~ "void say_hello(std::unique_ptr person) {\n" +#~ " std::cout << \"Hello \" << person->name << std::endl;\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```c++\n" +#~ "void say_hello(std::unique_ptr person) {\n" +#~ " std::cout << \"Hola \" << person->name << std::endl;\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```java\n" +#~ "void sayHello(Person person) {\n" +#~ " System.out.println(\"Hello \" + person.getName());\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```java\n" +#~ "void sayHello(Person person) {\n" +#~ " System.out.println(\"Hola \" + person.getName());\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust,editable\n" +#~ "fn main() {\n" +#~ " let s1: String = String::from(\"Hello!\");\n" +#~ " let s2: String = s1;\n" +#~ " println!(\"s2: {s2}\");\n" +#~ " // println!(\"s1: {s1}\");\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable\n" +#~ "fn main() {\n" +#~ " let s1: String = String::from(\"Hola!\");\n" +#~ " let s2: String = s1;\n" +#~ " println!(\"s2: {s2}\");\n" +#~ " // println!(\"s1: {s1}\");\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```c++\n" +#~ "std::string s1 = \"Cpp\";\n" +#~ "std::string s2 = s1; // Duplicate the data in s1.\n" +#~ "```" +#~ msgstr "" +#~ "```c++\n" +#~ "std::string s1 = \"Cpp\";\n" +#~ "std::string s2 = s1; // Duplicar datos en s1.\n" +#~ "```" + +#~ msgid "" +#~ "```bob\n" +#~ " Stack Heap\n" +#~ ".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +#~ ": : : :\n" +#~ ": s1 : : :\n" +#~ ": +-----------+-------+ : : +----+----+----+ :\n" +#~ ": | ptr | o---+---+--+--+-->| C | p | p | :\n" +#~ ": | len | 3 | : : +----+----+----+ :\n" +#~ ": | capacity | 3 | : : :\n" +#~ ": +-----------+-------+ : : :\n" +#~ ": : `- - - - - - - - - - - -'\n" +#~ "`- - - - - - - - - - - - - -'\n" +#~ "```" +#~ msgstr "" +#~ "```bob\n" +#~ " _Stack_ _Heap_\n" +#~ ".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +#~ ": : : :\n" +#~ ": s1 : : :\n" +#~ ": +-----------+-------+ : : +----+----+----+ :\n" +#~ ": | ptr | o---+---+--+--+-->| C | p | p | :\n" +#~ ": | len | 3 | : : +----+----+----+ :\n" +#~ ": | capacity | 3 | : : :\n" +#~ ": +-----------+-------+ : : :\n" +#~ ": : `- - - - - - - - - - - -'\n" +#~ "`- - - - - - - - - - - - - -'\n" +#~ "```" + +#~ msgid "" +#~ "```bob\n" +#~ " Stack Heap\n" +#~ ".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +#~ ": : : :\n" +#~ ": s1 : : :\n" +#~ ": +-----------+-------+ : : +----+----+----+ :\n" +#~ ": | ptr | o---+---+--+--+-->| C | p | p | :\n" +#~ ": | len | 3 | : : +----+----+----+ :\n" +#~ ": | capacity | 3 | : : :\n" +#~ ": +-----------+-------+ : : :\n" +#~ ": : : :\n" +#~ ": s2 : : :\n" +#~ ": +-----------+-------+ : : +----+----+----+ :\n" +#~ ": | ptr | o---+---+-----+-->| C | p | p | :\n" +#~ ": | len | 3 | : : +----+----+----+ :\n" +#~ ": | capacity | 3 | : : :\n" +#~ ": +-----------+-------+ : : :\n" +#~ ": : `- - - - - - - - - - - -'\n" +#~ "`- - - - - - - - - - - - - -'\n" +#~ "```" +#~ msgstr "" +#~ "```bob\n" +#~ " _Stack_ _Heap_\n" +#~ ".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +#~ ": : : :\n" +#~ ": s1 : : :\n" +#~ ": +-----------+-------+ : : +----+----+----+ :\n" +#~ ": | ptr | o---+---+--+--+-->| C | p | p | :\n" +#~ ": | len | 3 | : : +----+----+----+ :\n" +#~ ": | capacity | 3 | : : :\n" +#~ ": +-----------+-------+ : : :\n" +#~ ": : : :\n" +#~ ": s2 : : :\n" +#~ ": +-----------+-------+ : : +----+----+----+ :\n" +#~ ": | ptr | o---+---+-----+-->| C | p | p | :\n" +#~ ": | len | 3 | : : +----+----+----+ :\n" +#~ ": | capacity | 3 | : : :\n" +#~ ": +-----------+-------+ : : :\n" +#~ ": : `- - - - - - - - - - - -'\n" +#~ "`- - - - - - - - - - - - - -'\n" +#~ "```" + +#~ msgid "[Solution](solutions-afternoon.md#designing-a-library)" +#~ msgstr "[Soluciones](solutions-afternoon.md#designing-a-library)" + +#~ msgid "`binary_search` returns `Result`." +#~ msgstr "`binary_search` devuelve `Result`." + +#~ msgid "If found, `Result::Ok` holds the index where the element is found." +#~ msgstr "" +#~ "Si se encuentra, `Result::Ok` contiene el índice donde se halla el " +#~ "elemento." + +#~ msgid "" +#~ "Otherwise, `Result::Err` contains the index where such an element should " +#~ "be inserted." +#~ msgstr "" +#~ "De lo contrario, `Result::Err` contendrá el índice donde se debe insertar " +#~ "dicho elemento." + +#~ msgid "" +#~ "```bob\n" +#~ " Stack Heap\n" +#~ ".- - - - - - -. .- - - - - - -.\n" +#~ ": : : :\n" +#~ ": five : : :\n" +#~ ": +-----+ : : +-----+ :\n" +#~ ": | o---|---+-----+-->| 5 | :\n" +#~ ": +-----+ : : +-----+ :\n" +#~ ": : : :\n" +#~ ": : : :\n" +#~ "`- - - - - - -' `- - - - - - -'\n" +#~ "```" +#~ msgstr "" +#~ "```bob\n" +#~ " _Stack_ _Heap_\n" +#~ ".- - - - - - -. .- - - - - - -.\n" +#~ ": : : :\n" +#~ ": five : : :\n" +#~ ": +-----+ : : +-----+ :\n" +#~ ": | o---|---+-----+-->| 5 | :\n" +#~ ": +-----+ : : +-----+ :\n" +#~ ": : : :\n" +#~ ": : : :\n" +#~ "`- - - - - - -' `- - - - - - -'\n" +#~ "```" + +#~ msgid "" +#~ "```rust,editable,compile_fail\n" +#~ "trait NotEquals: Equals {\n" +#~ " fn not_equals(&self, other: &Self) -> bool {\n" +#~ " !self.equals(other)\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable,compile_fail\n" +#~ "trait NotEquals: Equals {\n" +#~ " fn not_equals(&self, other: &Self) -> bool {\n" +#~ " !self.equals(other)\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "`Button`: has a `label` and a callback function which is invoked when the " +#~ "button is pressed." +#~ msgstr "" +#~ "`Button`: tiene una `label` y una función de retrollamada que se invoca " +#~ "cuando se pulsa el botón." + +#~ msgid "" +#~ "```javascript\n" +#~ "rust_binary {\n" +#~ " name: \"hello_rust_with_dep\",\n" +#~ " crate_name: \"hello_rust_with_dep\",\n" +#~ " srcs: [\"src/main.rs\"],\n" +#~ " rustlibs: [\n" +#~ " \"libgreetings\",\n" +#~ " \"libtextwrap\",\n" +#~ " ],\n" +#~ " prefer_rlib: true,\n" +#~ "}\n" +#~ "\n" +#~ "rust_library {\n" +#~ " name: \"libgreetings\",\n" +#~ " crate_name: \"greetings\",\n" +#~ " srcs: [\"src/lib.rs\"],\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```javascript\n" +#~ "rust_binary {\n" +#~ " name: \"hello_rust_with_dep\",\n" +#~ " crate_name: \"hello_rust_with_dep\",\n" +#~ " srcs: [\"src/main.rs\"],\n" +#~ " rustlibs: [\n" +#~ " \"libgreetings\",\n" +#~ " \"libtextwrap\",\n" +#~ " ],\n" +#~ " prefer_rlib: true,\n" +#~ "}\n" +#~ "\n" +#~ "rust_library {\n" +#~ " name: \"libgreetings\",\n" +#~ " crate_name: \"greetings\",\n" +#~ " srcs: [\"src/lib.rs\"],\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust,ignore\n" +#~ "//! Rust demo.\n" +#~ "\n" +#~ "use greetings::greeting;\n" +#~ "use textwrap::fill;\n" +#~ "\n" +#~ "/// Prints a greeting to standard output.\n" +#~ "fn main() {\n" +#~ " println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,ignore\n" +#~ "//! Rust demo.\n" +#~ "\n" +#~ "use greetings::greeting;\n" +#~ "use textwrap::fill;\n" +#~ "\n" +#~ "/// Imprime un saludo en una salida estándar.\n" +#~ "fn main() {\n" +#~ " println!(\"{}\", fill(&greeting(\"Bob\"), 24));\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust,ignore\n" +#~ "//! Greeting library.\n" +#~ "\n" +#~ "/// Greet `name`.\n" +#~ "pub fn greeting(name: &str) -> String {\n" +#~ " format!(\"Hello {name}, it is very nice to meet you!\")\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,ignore\n" +#~ "//! Greeting library.\n" +#~ "\n" +#~ "/// Saludar a `name`.\n" +#~ "pub fn greeting(name: &str) -> String {\n" +#~ " format!(\"Hello {name}, it is very nice to meet you!\")\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```java\n" +#~ "package com.example.birthdayservice;\n" +#~ "\n" +#~ "/** Birthday service interface. */\n" +#~ "interface IBirthdayService {\n" +#~ " /** Generate a Happy Birthday message. */\n" +#~ " String wishHappyBirthday(String name, int years);\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```java\n" +#~ "package com.example.birthdayservice;\n" +#~ "\n" +#~ "/** Birthday service interface. */\n" +#~ "interface IBirthdayService {\n" +#~ " /** Generate a Happy Birthday message. */\n" +#~ " String wishHappyBirthday(String name, int years);\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```javascript\n" +#~ "aidl_interface {\n" +#~ " name: \"com.example.birthdayservice\",\n" +#~ " srcs: [\"com/example/birthdayservice/*.aidl\"],\n" +#~ " unstable: true,\n" +#~ " backend: {\n" +#~ " rust: { // Rust is not enabled by default\n" +#~ " enabled: true,\n" +#~ " },\n" +#~ " },\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```javascript\n" +#~ "aidl_interface {\n" +#~ " name: \"com.example.birthdayservice\",\n" +#~ " srcs: [\"com/example/birthdayservice/*.aidl\"],\n" +#~ " unstable: true,\n" +#~ " backend: {\n" +#~ " rust: { // Rust is not enabled by default\n" +#~ " enabled: true,\n" +#~ " },\n" +#~ " },\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```bash\n" +#~ "sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom " +#~ "pkg-config qemu-system-arm\n" +#~ "rustup update\n" +#~ "rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +#~ "rustup component add llvm-tools-preview\n" +#~ "cargo install cargo-binutils cargo-embed\n" +#~ "```" +#~ msgstr "" +#~ "```bash\n" +#~ "sudo apt install gcc-aarch64-linux-gnu gdb-multiarch libudev-dev picocom " +#~ "pkg-config qemu-system-arm\n" +#~ "rustup update\n" +#~ "rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +#~ "rustup component add llvm-tools-preview\n" +#~ "cargo install cargo-binutils cargo-embed\n" +#~ "```" + +#~ msgid "" +#~ "```bash\n" +#~ "echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", " +#~ "GROUP=\"plugdev\"' |\\\n" +#~ " sudo tee /etc/udev/rules.d/50-microbit.rules\n" +#~ "sudo udevadm control --reload-rules\n" +#~ "```" +#~ msgstr "" +#~ "```bash\n" +#~ "echo 'SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0d28\", MODE=\"0664\", " +#~ "GROUP=\"plugdev\"' |\\\n" +#~ " sudo tee /etc/udev/rules.d/50-microbit.rules\n" +#~ "sudo udevadm control --reload-rules\n" +#~ "```" -#: src/exercises/concurrency/solutions-morning.md:5 -msgid "([back to exercise](dining-philosophers.md))" -msgstr "([volver al ejercicio](dining-philosophers.md))" +#~ msgid "" +#~ "```bash\n" +#~ "xcode-select --install\n" +#~ "brew install gdb picocom qemu\n" +#~ "brew install --cask gcc-aarch64-embedded\n" +#~ "rustup update\n" +#~ "rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +#~ "rustup component add llvm-tools-preview\n" +#~ "cargo install cargo-binutils cargo-embed\n" +#~ "```" +#~ msgstr "" +#~ "```bash\n" +#~ "xcode-select --install\n" +#~ "brew install gdb picocom qemu\n" +#~ "brew install --cask gcc-aarch64-embedded\n" +#~ "rustup update\n" +#~ "rustup target add aarch64-unknown-none thumbv7em-none-eabihf\n" +#~ "rustup component add llvm-tools-preview\n" +#~ "cargo install cargo-binutils cargo-embed\n" +#~ "```" -#: src/exercises/concurrency/solutions-morning.md:7 -msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: Philosopher\n" -"use std::sync::{mpsc, Arc, Mutex};\n" -"use std::thread;\n" -"use std::time::Duration;\n" -"\n" -"struct Fork;\n" -"\n" -"struct Philosopher {\n" -" name: String,\n" -" // ANCHOR_END: Philosopher\n" -" left_fork: Arc>,\n" -" right_fork: Arc>,\n" -" thoughts: mpsc::SyncSender,\n" -"}\n" -"\n" -"// ANCHOR: Philosopher-think\n" -"impl Philosopher {\n" -" fn think(&self) {\n" -" self.thoughts\n" -" .send(format!(\"Eureka! {} has a new idea!\", &self.name))\n" -" .unwrap();\n" -" }\n" -" // ANCHOR_END: Philosopher-think\n" -"\n" -" // ANCHOR: Philosopher-eat\n" -" fn eat(&self) {\n" -" // ANCHOR_END: Philosopher-eat\n" -" println!(\"{} is trying to eat\", &self.name);\n" -" let left = self.left_fork.lock().unwrap();\n" -" let right = self.right_fork.lock().unwrap();\n" -"\n" -" // ANCHOR: Philosopher-eat-end\n" -" println!(\"{} is eating...\", &self.name);\n" -" thread::sleep(Duration::from_millis(10));\n" -" }\n" -"}\n" -"\n" -"static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" -"\n" -"fn main() {\n" -" // ANCHOR_END: Philosopher-eat-end\n" -" let (tx, rx) = mpsc::sync_channel(10);\n" -"\n" -" let forks = (0..PHILOSOPHERS.len())\n" -" .map(|_| Arc::new(Mutex::new(Fork)))\n" -" .collect::>();\n" -"\n" -" for i in 0..forks.len() {\n" -" let tx = tx.clone();\n" -" let mut left_fork = Arc::clone(&forks[i]);\n" -" let mut right_fork = Arc::clone(&forks[(i + 1) % forks.len()]);\n" -"\n" -" // To avoid a deadlock, we have to break the symmetry\n" -" // somewhere. This will swap the forks without deinitializing\n" -" // either of them.\n" -" if i == forks.len() - 1 {\n" -" std::mem::swap(&mut left_fork, &mut right_fork);\n" -" }\n" -"\n" -" let philosopher = Philosopher {\n" -" name: PHILOSOPHERS[i].to_string(),\n" -" thoughts: tx,\n" -" left_fork,\n" -" right_fork,\n" -" };\n" -"\n" -" thread::spawn(move || {\n" -" for _ in 0..100 {\n" -" philosopher.eat();\n" -" philosopher.think();\n" -" }\n" -" });\n" -" }\n" -"\n" -" drop(tx);\n" -" for thought in rx {\n" -" println!(\"{thought}\");\n" -" }\n" -"}\n" -"```" -msgstr "" +#~ msgid "" +#~ "```rust,editable,compile_fail\n" +#~ "#![no_main]\n" +#~ "#![no_std]\n" +#~ "\n" +#~ "use core::panic::PanicInfo;\n" +#~ "\n" +#~ "#[panic_handler]\n" +#~ "fn panic(_panic: &PanicInfo) -> ! {\n" +#~ " loop {}\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable,compile_fail\n" +#~ "#![no_main]\n" +#~ "#![no_std]\n" +#~ "\n" +#~ "use core::panic::PanicInfo;\n" +#~ "\n" +#~ "#[panic_handler]\n" +#~ "fn panic(_panic: &PanicInfo) -> ! {\n" +#~ " loop {}\n" +#~ "}\n" +#~ "```" -#: src/exercises/concurrency/solutions-morning.md:104 -msgid "Link Checker" -msgstr "Comprobador de Enlaces" +#~ msgid "" +#~ "```rust,editable,compile_fail\n" +#~ "#![no_main]\n" +#~ "#![no_std]\n" +#~ "\n" +#~ "extern crate alloc;\n" +#~ "extern crate panic_halt as _;\n" +#~ "\n" +#~ "use alloc::string::ToString;\n" +#~ "use alloc::vec::Vec;\n" +#~ "use buddy_system_allocator::LockedHeap;\n" +#~ "\n" +#~ "#[global_allocator]\n" +#~ "static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();\n" +#~ "\n" +#~ "static mut HEAP: [u8; 65536] = [0; 65536];\n" +#~ "\n" +#~ "pub fn entry() {\n" +#~ " // Safe because `HEAP` is only used here and `entry` is only called " +#~ "once.\n" +#~ " unsafe {\n" +#~ " // Give the allocator some memory to allocate.\n" +#~ " HEAP_ALLOCATOR\n" +#~ " .lock()\n" +#~ " .init(HEAP.as_mut_ptr() as usize, HEAP.len());\n" +#~ " }\n" +#~ "\n" +#~ " // Now we can do things that require heap allocation.\n" +#~ " let mut v = Vec::new();\n" +#~ " v.push(\"A string\".to_string());\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable,compile_fail\n" +#~ "#![no_main]\n" +#~ "#![no_std]\n" +#~ "\n" +#~ "extern crate alloc;\n" +#~ "extern crate panic_halt as _;\n" +#~ "\n" +#~ "use alloc::string::ToString;\n" +#~ "use alloc::vec::Vec;\n" +#~ "use buddy_system_allocator::LockedHeap;\n" +#~ "\n" +#~ "#[global_allocator]\n" +#~ "static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();\n" +#~ "\n" +#~ "static mut HEAP: [u8; 65536] = [0; 65536];\n" +#~ "\n" +#~ "pub fn entry() {\n" +#~ " // Safe because `HEAP` is only used here and `entry` is only called " +#~ "once.\n" +#~ " unsafe {\n" +#~ " // Give the allocator some memory to allocate.\n" +#~ " HEAP_ALLOCATOR\n" +#~ " .lock()\n" +#~ " .init(HEAP.as_mut_ptr() as usize, HEAP.len());\n" +#~ " }\n" +#~ "\n" +#~ " // Ahora podemos hacer cosas que requieran asignación de _heap_.\n" +#~ " let mut v = Vec::new();\n" +#~ " v.push(\"A string\".to_string());\n" +#~ "}\n" +#~ "```" -#: src/exercises/concurrency/solutions-morning.md:106 -msgid "([back to exercise](link-checker.md))" -msgstr "([volver al ejercicio](link-checker.md))" +#~ msgid "SWD" +#~ msgstr "SWD" -#: src/exercises/concurrency/solutions-morning.md:108 -msgid "" -"```rust,compile_fail\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"use std::{sync::Arc, sync::Mutex, sync::mpsc, thread};\n" -"\n" -"// ANCHOR: setup\n" -"use reqwest::{blocking::Client, Url};\n" -"use scraper::{Html, Selector};\n" -"use thiserror::Error;\n" -"\n" -"#[derive(Error, Debug)]\n" -"enum Error {\n" -" #[error(\"request error: {0}\")]\n" -" ReqwestError(#[from] reqwest::Error),\n" -" #[error(\"bad http response: {0}\")]\n" -" BadResponse(String),\n" -"}\n" -"// ANCHOR_END: setup\n" -"\n" -"// ANCHOR: visit_page\n" -"#[derive(Debug)]\n" -"struct CrawlCommand {\n" -" url: Url,\n" -" extract_links: bool,\n" -"}\n" -"\n" -"fn visit_page(client: &Client, command: &CrawlCommand) -> Result, " -"Error> {\n" -" println!(\"Checking {:#}\", command.url);\n" -" let response = client.get(command.url.clone()).send()?;\n" -" if !response.status().is_success() {\n" -" return Err(Error::BadResponse(response.status().to_string()));\n" -" }\n" -"\n" -" let mut link_urls = Vec::new();\n" -" if !command.extract_links {\n" -" return Ok(link_urls);\n" -" }\n" -"\n" -" let base_url = response.url().to_owned();\n" -" let body_text = response.text()?;\n" -" let document = Html::parse_document(&body_text);\n" -"\n" -" let selector = Selector::parse(\"a\").unwrap();\n" -" let href_values = document\n" -" .select(&selector)\n" -" .filter_map(|element| element.value().attr(\"href\"));\n" -" for href in href_values {\n" -" match base_url.join(href) {\n" -" Ok(link_url) => {\n" -" link_urls.push(link_url);\n" -" }\n" -" Err(err) => {\n" -" println!(\"On {base_url:#}: ignored unparsable {href:?}: " -"{err}\");\n" -" }\n" -" }\n" -" }\n" -" Ok(link_urls)\n" -"}\n" -"// ANCHOR_END: visit_page\n" -"\n" -"struct CrawlState {\n" -" domain: String,\n" -" visited_pages: std::collections::HashSet,\n" -"}\n" -"\n" -"impl CrawlState {\n" -" fn new(start_url: &Url) -> CrawlState {\n" -" let mut visited_pages = std::collections::HashSet::new();\n" -" visited_pages.insert(start_url.as_str().to_string());\n" -" CrawlState {\n" -" domain: start_url.domain().unwrap().to_string(),\n" -" visited_pages,\n" -" }\n" -" }\n" -"\n" -" /// Determine whether links within the given page should be extracted.\n" -" fn should_extract_links(&self, url: &Url) -> bool {\n" -" let Some(url_domain) = url.domain() else {\n" -" return false;\n" -" };\n" -" url_domain == self.domain\n" -" }\n" -"\n" -" /// Mark the given page as visited, returning true if it had already\n" -" /// been visited.\n" -" fn mark_visited(&mut self, url: &Url) -> bool {\n" -" self.visited_pages.insert(url.as_str().to_string())\n" -" }\n" -"}\n" -"\n" -"type CrawlResult = Result, (Url, Error)>;\n" -"fn spawn_crawler_threads(\n" -" command_receiver: mpsc::Receiver,\n" -" result_sender: mpsc::Sender,\n" -" thread_count: u32,\n" -") {\n" -" let command_receiver = Arc::new(Mutex::new(command_receiver));\n" -"\n" -" for _ in 0..thread_count {\n" -" let result_sender = result_sender.clone();\n" -" let command_receiver = command_receiver.clone();\n" -" thread::spawn(move || {\n" -" let client = Client::new();\n" -" loop {\n" -" let command_result = {\n" -" let receiver_guard = command_receiver.lock().unwrap();\n" -" receiver_guard.recv()\n" -" };\n" -" let Ok(crawl_command) = command_result else {\n" -" // The sender got dropped. No more commands coming in.\n" -" break;\n" -" };\n" -" let crawl_result = match visit_page(&client, &crawl_command) " -"{\n" -" Ok(link_urls) => Ok(link_urls),\n" -" Err(error) => Err((crawl_command.url, error)),\n" -" };\n" -" result_sender.send(crawl_result).unwrap();\n" -" }\n" -" });\n" -" }\n" -"}\n" -"\n" -"fn control_crawl(\n" -" start_url: Url,\n" -" command_sender: mpsc::Sender,\n" -" result_receiver: mpsc::Receiver,\n" -") -> Vec {\n" -" let mut crawl_state = CrawlState::new(&start_url);\n" -" let start_command = CrawlCommand { url: start_url, extract_links: " -"true };\n" -" command_sender.send(start_command).unwrap();\n" -" let mut pending_urls = 1;\n" -"\n" -" let mut bad_urls = Vec::new();\n" -" while pending_urls > 0 {\n" -" let crawl_result = result_receiver.recv().unwrap();\n" -" pending_urls -= 1;\n" -"\n" -" match crawl_result {\n" -" Ok(link_urls) => {\n" -" for url in link_urls {\n" -" if crawl_state.mark_visited(&url) {\n" -" let extract_links = crawl_state." -"should_extract_links(&url);\n" -" let crawl_command = CrawlCommand { url, " -"extract_links };\n" -" command_sender.send(crawl_command).unwrap();\n" -" pending_urls += 1;\n" -" }\n" -" }\n" -" }\n" -" Err((url, error)) => {\n" -" bad_urls.push(url);\n" -" println!(\"Got crawling error: {:#}\", error);\n" -" continue;\n" -" }\n" -" }\n" -" }\n" -" bad_urls\n" -"}\n" -"\n" -"fn check_links(start_url: Url) -> Vec {\n" -" let (result_sender, result_receiver) = mpsc::channel::();\n" -" let (command_sender, command_receiver) = mpsc::channel::" -"();\n" -" spawn_crawler_threads(command_receiver, result_sender, 16);\n" -" control_crawl(start_url, command_sender, result_receiver)\n" -"}\n" -"\n" -"fn main() {\n" -" let start_url = reqwest::Url::parse(\"https://www.google.org\")." -"unwrap();\n" -" let bad_urls = check_links(start_url);\n" -" println!(\"Bad URLs: {:#?}\", bad_urls);\n" -"}\n" -"```" -msgstr "" +#~ msgid "GDB stub and Microsoft " +#~ msgstr "GDB stub y el servidor " -#: src/exercises/concurrency/solutions-afternoon.md:1 -msgid "Concurrency Afternoon Exercise" -msgstr "Concurrencia: Ejercicios de la Tarde" +#~ msgid "DAP" +#~ msgstr "DAP" -#: src/exercises/concurrency/solutions-afternoon.md:5 -msgid "([back to exercise](dining-philosophers-async.md))" -msgstr "([volver al ejercicio](dining-philosophers-async.md))" +#~ msgid " server" +#~ msgstr " de Microsoft" -#: src/exercises/concurrency/solutions-afternoon.md:7 -msgid "" -"```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: Philosopher\n" -"use std::sync::Arc;\n" -"use tokio::time;\n" -"use tokio::sync::mpsc::{self, Sender};\n" -"use tokio::sync::Mutex;\n" -"\n" -"struct Fork;\n" -"\n" -"struct Philosopher {\n" -" name: String,\n" -" // ANCHOR_END: Philosopher\n" -" left_fork: Arc>,\n" -" right_fork: Arc>,\n" -" thoughts: Sender,\n" -"}\n" -"\n" -"// ANCHOR: Philosopher-think\n" -"impl Philosopher {\n" -" async fn think(&self) {\n" -" self.thoughts\n" -" .send(format!(\"Eureka! {} has a new idea!\", &self.name))." -"await\n" -" .unwrap();\n" -" }\n" -" // ANCHOR_END: Philosopher-think\n" -"\n" -" // ANCHOR: Philosopher-eat\n" -" async fn eat(&self) {\n" -" // Pick up forks...\n" -" // ANCHOR_END: Philosopher-eat\n" -" let _first_lock = self.left_fork.lock().await;\n" -" // Add a delay before picking the second fork to allow the " -"execution\n" -" // to transfer to another task\n" -" time::sleep(time::Duration::from_millis(1)).await;\n" -" let _second_lock = self.right_fork.lock().await;\n" -"\n" -" // ANCHOR: Philosopher-eat-body\n" -" println!(\"{} is eating...\", &self.name);\n" -" time::sleep(time::Duration::from_millis(5)).await;\n" -" // ANCHOR_END: Philosopher-eat-body\n" -"\n" -" // The locks are dropped here\n" -" // ANCHOR: Philosopher-eat-end\n" -" }\n" -"}\n" -"\n" -"static PHILOSOPHERS: &[&str] =\n" -" &[\"Socrates\", \"Plato\", \"Aristotle\", \"Thales\", \"Pythagoras\"];\n" -"\n" -"#[tokio::main]\n" -"async fn main() {\n" -" // ANCHOR_END: Philosopher-eat-end\n" -" // Create forks\n" -" let mut forks = vec![];\n" -" (0..PHILOSOPHERS.len()).for_each(|_| forks.push(Arc::new(Mutex::" -"new(Fork))));\n" -"\n" -" // Create philosophers\n" -" let (philosophers, mut rx) = {\n" -" let mut philosophers = vec![];\n" -" let (tx, rx) = mpsc::channel(10);\n" -" for (i, name) in PHILOSOPHERS.iter().enumerate() {\n" -" let left_fork = Arc::clone(&forks[i]);\n" -" let right_fork = Arc::clone(&forks[(i + 1) % PHILOSOPHERS." -"len()]);\n" -" // To avoid a deadlock, we have to break the symmetry\n" -" // somewhere. This will swap the forks without deinitializing\n" -" // either of them.\n" -" if i == 0 {\n" -" std::mem::swap(&mut left_fork, &mut right_fork);\n" -" }\n" -" philosophers.push(Philosopher {\n" -" name: name.to_string(),\n" -" left_fork,\n" -" right_fork,\n" -" thoughts: tx.clone(),\n" -" });\n" -" }\n" -" (philosophers, rx)\n" -" // tx is dropped here, so we don't need to explicitly drop it later\n" -" };\n" -"\n" -" // Make them think and eat\n" -" for phil in philosophers {\n" -" tokio::spawn(async move {\n" -" for _ in 0..100 {\n" -" phil.think().await;\n" -" phil.eat().await;\n" -" }\n" -" });\n" -"\n" -" }\n" -"\n" -" // Output their thoughts\n" -" while let Some(thought) = rx.recv().await {\n" -" println!(\"Here is a thought: {thought}\");\n" -" }\n" -"}\n" -"```" -msgstr "" +#~ msgid "" +#~ "`cargo-embed` is a cargo subcommand to build and flash binaries, log " +#~ msgstr "" +#~ "`cargo-embed` es un subcomando de Cargo para compilar e instalar " +#~ "binarios, registrar salidas " -#: src/exercises/concurrency/solutions-afternoon.md:121 -msgid "([back to exercise](chat-app.md))" -msgstr "([volver al ejercicio](chat-app.md))" +#~ msgid "RTT" +#~ msgstr "TTR" -#: src/exercises/concurrency/solutions-afternoon.md:125 -msgid "" -"```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: setup\n" -"use futures_util::sink::SinkExt;\n" -"use futures_util::stream::StreamExt;\n" -"use std::error::Error;\n" -"use std::net::SocketAddr;\n" -"use tokio::net::{TcpListener, TcpStream};\n" -"use tokio::sync::broadcast::{channel, Sender};\n" -"use tokio_websockets::{Message, ServerBuilder, WebsocketStream};\n" -"// ANCHOR_END: setup\n" -"\n" -"// ANCHOR: handle_connection\n" -"async fn handle_connection(\n" -" addr: SocketAddr,\n" -" mut ws_stream: WebsocketStream,\n" -" bcast_tx: Sender,\n" -") -> Result<(), Box> {\n" -" // ANCHOR_END: handle_connection\n" -"\n" -" ws_stream\n" -" .send(Message::text(\"Welcome to chat! Type a message\".into()))\n" -" .await?;\n" -" let mut bcast_rx = bcast_tx.subscribe();\n" -"\n" -" // A continuous loop for concurrently performing two tasks: (1) " -"receiving\n" -" // messages from `ws_stream` and broadcasting them, and (2) receiving\n" -" // messages on `bcast_rx` and sending them to the client.\n" -" loop {\n" -" tokio::select! {\n" -" incoming = ws_stream.next() => {\n" -" match incoming {\n" -" Some(Ok(msg)) => {\n" -" if let Some(text) = msg.as_text() {\n" -" println!(\"From client {addr:?} {text:?}\");\n" -" bcast_tx.send(text.into())?;\n" -" }\n" -" }\n" -" Some(Err(err)) => return Err(err.into()),\n" -" None => return Ok(()),\n" -" }\n" -" }\n" -" msg = bcast_rx.recv() => {\n" -" ws_stream.send(Message::text(msg?)).await?;\n" -" }\n" -" }\n" -" }\n" -" // ANCHOR: main\n" -"}\n" -"\n" -"#[tokio::main]\n" -"async fn main() -> Result<(), Box> {\n" -" let (bcast_tx, _) = channel(16);\n" -"\n" -" let listener = TcpListener::bind(\"127.0.0.1:2000\").await?;\n" -" println!(\"listening on port 2000\");\n" -"\n" -" loop {\n" -" let (socket, addr) = listener.accept().await?;\n" -" println!(\"New connection from {addr:?}\");\n" -" let bcast_tx = bcast_tx.clone();\n" -" tokio::spawn(async move {\n" -" // Wrap the raw TCP stream into a websocket.\n" -" let ws_stream = ServerBuilder::new().accept(socket).await?;\n" -"\n" -" handle_connection(addr, ws_stream, bcast_tx).await\n" -" });\n" -" }\n" -"}\n" -"// ANCHOR_END: main\n" -"```" -msgstr "" +#~ msgid "HVC" +#~ msgstr "HVC" -#: src/exercises/concurrency/solutions-afternoon.md:212 -msgid "" -"```rust,compile_fail\n" -"// Copyright 2023 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"// ANCHOR: setup\n" -"use futures_util::stream::StreamExt;\n" -"use futures_util::SinkExt;\n" -"use http::Uri;\n" -"use tokio::io::{AsyncBufReadExt, BufReader};\n" -"use tokio_websockets::{ClientBuilder, Message};\n" -"\n" -"#[tokio::main]\n" -"async fn main() -> Result<(), tokio_websockets::Error> {\n" -" let (mut ws_stream, _) =\n" -" ClientBuilder::from_uri(Uri::from_static(\"ws://127.0.0.1:2000\"))\n" -" .connect()\n" -" .await?;\n" -"\n" -" let stdin = tokio::io::stdin();\n" -" let mut stdin = BufReader::new(stdin).lines();\n" -"\n" -" // ANCHOR_END: setup\n" -" // Continuous loop for concurrently sending and receiving messages.\n" -" loop {\n" -" tokio::select! {\n" -" incoming = ws_stream.next() => {\n" -" match incoming {\n" -" Some(Ok(msg)) => {\n" -" if let Some(text) = msg.as_text() {\n" -" println!(\"From server: {}\", text);\n" -" }\n" -" },\n" -" Some(Err(err)) => return Err(err.into()),\n" -" None => return Ok(()),\n" -" }\n" -" }\n" -" res = stdin.next_line() => {\n" -" match res {\n" -" Ok(None) => return Ok(()),\n" -" Ok(Some(line)) => ws_stream.send(Message::text(line." -"to_string())).await?,\n" -" Err(err) => return Err(err.into()),\n" -" }\n" -" }\n" -"\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" +#~ msgid " to tell the firmware to power off the system:" +#~ msgstr " para decirle al firmware que apague el sistema:" + +#~ msgid "" +#~ "```shell\n" +#~ "cargo add thiserror\n" +#~ "```" +#~ msgstr "" +#~ "```shell\n" +#~ "cargo add thiserror\n" +#~ "```" + +#~ msgid "" +#~ "```rust,compile_fail\n" +#~ "use reqwest::{blocking::Client, Url};\n" +#~ "use scraper::{Html, Selector};\n" +#~ "use thiserror::Error;\n" +#~ "\n" +#~ "#[derive(Error, Debug)]\n" +#~ "enum Error {\n" +#~ " #[error(\"request error: {0}\")]\n" +#~ " ReqwestError(#[from] reqwest::Error),\n" +#~ " #[error(\"bad http response: {0}\")]\n" +#~ " BadResponse(String),\n" +#~ "}\n" +#~ "\n" +#~ "#[derive(Debug)]\n" +#~ "struct CrawlCommand {\n" +#~ " url: Url,\n" +#~ " extract_links: bool,\n" +#~ "}\n" +#~ "\n" +#~ "fn visit_page(client: &Client, command: &CrawlCommand) -> " +#~ "Result, Error> {\n" +#~ " println!(\"Checking {:#}\", command.url);\n" +#~ " let response = client.get(command.url.clone()).send()?;\n" +#~ " if !response.status().is_success() {\n" +#~ " return Err(Error::BadResponse(response.status().to_string()));\n" +#~ " }\n" +#~ "\n" +#~ " let mut link_urls = Vec::new();\n" +#~ " if !command.extract_links {\n" +#~ " return Ok(link_urls);\n" +#~ " }\n" +#~ "\n" +#~ " let base_url = response.url().to_owned();\n" +#~ " let body_text = response.text()?;\n" +#~ " let document = Html::parse_document(&body_text);\n" +#~ "\n" +#~ " let selector = Selector::parse(\"a\").unwrap();\n" +#~ " let href_values = document\n" +#~ " .select(&selector)\n" +#~ " .filter_map(|element| element.value().attr(\"href\"));\n" +#~ " for href in href_values {\n" +#~ " match base_url.join(href) {\n" +#~ " Ok(link_url) => {\n" +#~ " link_urls.push(link_url);\n" +#~ " }\n" +#~ " Err(err) => {\n" +#~ " println!(\"On {base_url:#}: ignored unparsable {href:?}: " +#~ "{err}\");\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ " Ok(link_urls)\n" +#~ "}\n" +#~ "\n" +#~ "fn main() {\n" +#~ " let client = Client::new();\n" +#~ " let start_url = Url::parse(\"https://www.google.org\").unwrap();\n" +#~ " let crawl_command = CrawlCommand{ url: start_url, extract_links: " +#~ "true };\n" +#~ " match visit_page(&client, &crawl_command) {\n" +#~ " Ok(links) => println!(\"Links: {links:#?}\"),\n" +#~ " Err(err) => println!(\"Could not extract links: {err:#}\"),\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,compile_fail\n" +#~ "use reqwest::{blocking::Client, Url};\n" +#~ "use scraper::{Html, Selector};\n" +#~ "use thiserror::Error;\n" +#~ "\n" +#~ "#[derive(Error, Debug)]\n" +#~ "enum Error {\n" +#~ " #[error(\"request error: {0}\")]\n" +#~ " ReqwestError(#[from] reqwest::Error),\n" +#~ " #[error(\"bad http response: {0}\")]\n" +#~ " BadResponse(String),\n" +#~ "}\n" +#~ "\n" +#~ "#[derive(Debug)]\n" +#~ "struct CrawlCommand {\n" +#~ " url: Url,\n" +#~ " extract_links: bool,\n" +#~ "}\n" +#~ "\n" +#~ "fn visit_page(client: &Client, command: &CrawlCommand) -> " +#~ "Result, Error> {\n" +#~ " println!(\"Checking {:#}\", command.url);\n" +#~ " let response = client.get(command.url.clone()).send()?;\n" +#~ " if !response.status().is_success() {\n" +#~ " return Err(Error::BadResponse(response.status().to_string()));\n" +#~ " }\n" +#~ "\n" +#~ " let mut link_urls = Vec::new();\n" +#~ " if !command.extract_links {\n" +#~ " return Ok(link_urls);\n" +#~ " }\n" +#~ "\n" +#~ " let base_url = response.url().to_owned();\n" +#~ " let body_text = response.text()?;\n" +#~ " let document = Html::parse_document(&body_text);\n" +#~ "\n" +#~ " let selector = Selector::parse(\"a\").unwrap();\n" +#~ " let href_values = document\n" +#~ " .select(&selector)\n" +#~ " .filter_map(|element| element.value().attr(\"href\"));\n" +#~ " for href in href_values {\n" +#~ " match base_url.join(href) {\n" +#~ " Ok(link_url) => {\n" +#~ " link_urls.push(link_url);\n" +#~ " }\n" +#~ " Err(err) => {\n" +#~ " println!(\"On {base_url:#}: ignored unparsable {href:?}: " +#~ "{err}\");\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ " Ok(link_urls)\n" +#~ "}\n" +#~ "\n" +#~ "fn main() {\n" +#~ " let client = Client::new();\n" +#~ " let start_url = Url::parse(\"https://www.google.org\").unwrap();\n" +#~ " let crawl_command = CrawlCommand{ url: start_url, extract_links: " +#~ "true };\n" +#~ " match visit_page(&client, &crawl_command) {\n" +#~ " Ok(links) => println!(\"Links: {links:#?}\"),\n" +#~ " Err(err) => println!(\"Could not extract links: {err:#}\"),\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```shell\n" +#~ "cargo run\n" +#~ "```" +#~ msgstr "" +#~ "```shell\n" +#~ "cargo run\n" +#~ "```" + +#~ msgid "" +#~ "```rust,editable,compile_fail\n" +#~ "use futures::executor::block_on;\n" +#~ "\n" +#~ "async fn count_to(count: i32) {\n" +#~ " for i in 1..=count {\n" +#~ " println!(\"Count is: {i}!\");\n" +#~ " }\n" +#~ "}\n" +#~ "\n" +#~ "async fn async_main(count: i32) {\n" +#~ " count_to(count).await;\n" +#~ "}\n" +#~ "\n" +#~ "fn main() {\n" +#~ " block_on(async_main(10));\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust,editable,compile_fail\n" +#~ "use futures::executor::block_on;\n" +#~ "\n" +#~ "async fn count_to(count: i32) {\n" +#~ " for i in 1..=count {\n" +#~ " println!(\"Count is: {i}!\");\n" +#~ " }\n" +#~ "}\n" +#~ "\n" +#~ "async fn async_main(count: i32) {\n" +#~ " count_to(count).await;\n" +#~ "}\n" +#~ "\n" +#~ "fn main() {\n" +#~ " block_on(async_main(10));\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "**Note:** Please ignore the `// ANCHOR: label` and `// ANCHOR_END: label` " +#~ "comments you see in the solutions. They are there to make it possible to " +#~ "re-use parts of the solutions as the exercises." +#~ msgstr "" +#~ "**Nota:** Ignora los comentarios `// ANCHOR: label` y `// ANCHOR_END: " +#~ "label` que aparecen en las soluciones. Están ahí para que sea posible " +#~ "reutilizar algunas partes de las soluciones de los ejercicios." #~ msgid "Extra Work in Modern C++" #~ msgstr "Trabajo adicional en C++ moderno" @@ -24270,9 +20231,6 @@ msgstr "" #~ msgid "Double-frees." #~ msgstr "Errores double free." -#~ msgid "Memory leaks." -#~ msgstr "Pérdidas de memoria." - #~ msgid "Garbage collection pauses." #~ msgstr "Pausas en la recolección de memoria residual." @@ -24459,17 +20417,6 @@ msgstr "" #~ "println!();\n" #~ "```" -#~ msgid "" -#~ "```rust,should_panic\n" -#~ "// TODO: remove this when you're done with your implementation.\n" -#~ "#![allow(unused_variables, dead_code)]\n" -#~ "```" -#~ msgstr "" -#~ "```rust,should_panic\n" -#~ "// TODO: borra esto cuando termines de implementarlo.\n" -#~ "#![allow(unused_variables, dead_code)]\n" -#~ "```" - #~ msgid "" #~ "Note that since `println!` is a macro, `x` is not moved, even using the " #~ "function like syntax of `println!(\"x: {}\", x)`"