<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Rust - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Rust - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 08 Jun 2026 04:58:10 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/tag/rust/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Curso de programación de aprender Rust: Tutorial interactivo de lenguaje Rust en Replit ]]>
                </title>
                <description>
                    <![CDATA[ Artículo original escrito por: Shaun Hamilton [https://www.freecodecamp.org/news/author/shaun/] Artículo original: Learn Rust Programming Course – Interactive Rust Language Tutorial on Replit [https://www.freecodecamp.org/news/rust-in-replit/] Traducido y adaptado por: Rafael D. Hernandez [/espanol/news/author/rafael/] Durante seis años consecutivos, Rust ha sido votado como el lenguaje de programación más querido por StackOverflow [https://insights.stackoverflow.com/survey/2021#technology-most ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/rust-en-replit/</link>
                <guid isPermaLink="false">61fd8035e56f6e08aa1c4ab6</guid>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rafael D. Hernandez ]]>
                </dc:creator>
                <pubDate>Thu, 10 Feb 2022 02:46:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/02/rust-and-sunset.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Artículo original escrito por</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> </strong></strong></strong></strong></strong></strong></strong></strong><a href="https://www.freecodecamp.org/news/author/shaun/">Shaun Hamilton</a><br><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Artículo original</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> </strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong><a href="https://www.freecodecamp.org/news/rust-in-replit/">Learn Rust Programming Course – Interactive Rust Language Tutorial on Replit</a><br><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Traducido y adaptado por</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> </strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong><a href="https://www.freecodecamp.org/espanol/news/author/rafael/">Rafael D. Hernandez</a></p><p>Durante seis años consecutivos, Rust ha sido votado como el lenguaje de programación más querido por <a href="https://insights.stackoverflow.com/survey/2021#technology-most-loved-dreaded-and-wanted">StackOverflow</a>.</p><p>Así que si estás listo para aprender este popular lenguaje de programación, este curso te presentará Rust para que puedas empezar a usarlo en tus proyectos.</p><p>Trabajará completamente dentro de tu navegador utilizando el entorno de programación interactivo <a href="https://replit.com/">Replit</a>. freeCodeCamp se ha asociado con Replit, que ha hecho posible este curso.</p><figure class="kg-card kg-embed-card" data-test-label="fitted">
        <div class="fluid-width-video-container">
          <div style="padding-top: 56.17885560589808%;" class="fluid-width-video-wrapper">
            <iframe src="https://www.youtube.com/embed/MsocPEZBd-M?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" title="Embedded content" loading="lazy" name="fitvid0" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; position: absolute; top: 0px; left: 0px; width: 499.688px; height: 280.719px;"></iframe>
          </div>
        </div>
      </figure><p>También hay una versión en video de este curso en ingles en el <a href="https://youtu.be/MsocPEZBd-M">canal de YouTube de freeCodeCamp</a>.</p><p>Para aprovechar al máximo este curso, debes tener conocimientos intermedios de al menos otro lenguaje de programación. Si eres nuevo en la programación, deberías probar el <a href="https://www.freecodecamp.org/learn/">currículo interactivo de freeCodeCamp</a> y luego volver a este curso.</p><p>Para ayudarte a aprender Rust, crearemos dos proyectos:</p><ol><li>Una calculadora para la línea de comandos</li><li>Una herramienta de línea de comandos que toma dos imágenes y combina sus píxeles</li></ol><h2 id="tabla-de-contenidos">Tabla de contenidos</h2><p>Estas son las secciones y temas que cubriremos en este curso. Puedes hacer clic en la tabla de contenido a continuación para saltar a partes particulares, o simplemente puedes ir de principio a fin.</p><!--kg-card-begin: markdown--><ul>
<li><a href="#descripci-n-de-rust">Descripción del Rust</a></li>
<li><a href="#como-usar-rust-en-replit">Cómo usar Rust en Replit</a></li>
<li><a href="#descripci-n-de-rust">Fundamentos de Rust</a>
<ul>
<li><a href="#variables-en-rust">Variables en Rust</a></li>
<li><a href="#funciones-en-rust">Funciones en Rust</a></li>
<li><a href="#cadenas-y-slices-en-rust">Cadenas y slices en Rust</a></li>
<li><a href="#el-tipo-de-char-en-rust">El tipo de char en Rust</a></li>
<li><a href="#tipos-de-n-meros-en-rust">Tipos de números en Rust</a></li>
<li><a href="#structs-en-rust">Structs en Rust</a></li>
<li><a href="#enumeros-en-rust">Enumeros en Rust</a></li>
<li><a href="#macros-en-rust">Macros en Rust</a></li>
<li><a href="#propiedad-en-rust">Propiedad en Rust</a></li>
</ul>
</li>
<li><a href="#proyecto-1-construir-una-calculadora-de-cli-en-rust">Proyecto # 1-Construir una calculadora de CLI en Rust</a>
<ul>
<li><a href="#resultado-del-proyecto">Resultado del proyecto</a></li>
<li><a href="#calculadora-de-cli-metodolog-a-de-proyecto">Calculadora de CLI metodología de proyecto</a>
<ul>
<li><a href="#paso-1-crear-un-nuevo-proyecto">Paso 1-Crear un nuevo proyecto</a></li>
<li><a href="#paso-2-comprender-la-sintaxis">Paso 2-Comprender la sintaxis</a></li>
<li><a href="#paso-3-ejecutar-el-proyecto">Paso 3-Ejecutar el proyecto</a></li>
<li><a href="#paso-4-argumentos-de-la-l-nea-de-comandos">Paso 4-Argumentos de la línea de comandos</a></li>
<li><a href="#paso-5-analiza-cadenas-en-n-meros">Paso 5-Analizar cadenas en números</a></li>
<li><a href="#paso-6-realiza-operaciones-aritm-ticas-b-sicas">Paso 6-Realizar operaciones aritméticas básicas</a></li>
<li><a href="#paso-7-formatear-la-salida">Paso 7-Formatear la salida</a></li>
<li><a href="#paso-8-re-ne-todo">Paso 8-Reúne todo</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#proyecto-2-construye-un-combinador-de-im-genes-en-rust">Proyecto # 2-Construye un combinador de imágenes en Rust</a>
<ul>
<li><a href="#resultado-del-proyecto">Resultado del Proyecto</a></li>
<li><a href="#metodolog-a-del-proyecto-combinador-de-im-genes">Metodología del proyecto combinador de imágenes</a>
<ul>
<li><a href="#paso-1-crear-un-nuevo-proyecto">Paso 1-Crear un nuevo proyecto</a></li>
<li><a href="#paso-2-a-ade-un-nuevo-m-dulo-para-args">Paso 2-Añadir un nuevo módulo para args</a></li>
<li><a href="#paso-3-importar-y-usar-el-m-dulo-args">Paso 3-Importar y usar el módulo args</a></li>
<li><a href="#paso-4-a%C3%B1adir-una-caja-externa">Paso 4-Añadir una caja externa</a></li>
<li><a href="#paso-5-leer-un-archivo-de-imagen">Paso 5-Leer un archivo de imagen</a></li>
<li><a href="#paso-6-Maneja-errores-con-result">Paso 6-Manejar errores con resultado</a></li>
<li><a href="#paso-7-cambia-el-tama-o-de-las-im-genes-para-que-coincidan">Paso 7-Cambiar el tamaño de las imágenes para que coincidan</a></li>
<li><a href="#paso-8%E2%80%93crea-una-imagen-flotante">Paso 8-Crear una imagen flotante</a></li>
<li><a href="#paso-9-crea-los-datos-de-imagen-combinados">Paso 9-Crear los datos de imagen combinados</a></li>
<li><a href="#paso-10-adjunta-los-datos-combinados-a-la-imagen-flotante">Paso 10: Adjunte los datos combinados a la imagen flotante</a></li>
<li><a href="#paso-11-escribe-la-imagen-en-un-archivo">Paso 11-Escribe la imagen en un archivo</a></li>
<li><a href="#paso-12-une-todo">Paso 12-Une todo</a></li>
</ul>
</li>
</ul>
</li>
<li>Conclusion</li>
</ul>
<!--kg-card-end: markdown--><h2 id="descripci-n-de-rust">Descripción de Rust</h2><p>Rust es un lenguaje de programación a <em>nivel de sistemas</em>.</p><blockquote>"[Rust] se ocupa de detalles de bajo nivel de administración de memoria, representación de datos y concurrencia.""... el lenguaje está diseñado para guiarlo naturalmente hacia un código confiable que sea eficiente en términos de velocidad y uso de memoria."(Fuente: Documentacion de Rust)</blockquote><p>La herramienta principal dentro del ecosistema de Rust es:</p><ul><li><strong>rustc</strong> - El compilador que toma tu código Rust y lo compila en binario (código legible por máquina)</li><li><strong>rustup</strong> - La utilidad de línea de comandos para instalar y actualizar Rust</li><li><strong>cargo</strong> - El sistema de construcción de Rust y el gestor de paquetes</li></ul><h2 id="c-mo-usar-rust-en-replit">Cómo usar Rust en Replit</h2><p>Para este curso, usarás este <a href="https://github.com/freeCodeCamp/Rust-In-Replit/">repositorio de GitHub</a> como un boilerplate.</p><p>Para comenzar, has clic en el siguiente enlace para crear una nueva RESPUESTA desde el modelo estándar:</p><!--kg-card-begin: markdown--><p><a href="https://replit.com/github/freeCodeCamp/Rust-in-Replit"><img src="https://www.freecodecamp.org/espanol/news/content/images/2022/02/Rust-in-Replit.svg" alt="Rust-in-Replit" width="95" height="20" loading="lazy"></a></p>
<!--kg-card-end: markdown--><h2 id="fundamentos-de-rust"><strong>Fundamentos de Rust</strong></h2><h3 id="variables-en-rust"><strong>Variables en Rust</strong></h3><p>Puedes declarar variables utilizando las palabras clave <code>let</code>, <code>const</code> o <code>static</code>:</p><pre><code class="language-rust">let mi_variable = 0;
const Mi_CONSTANT: u8 = 0;
static Mi_STATIC: u8 = 0;
</code></pre><p>De forma predeterminada, todas las variables son inmutables. Puedes hacer que una variable sea mutable utilizando la palabra clave <code>mut</code>:</p><pre><code class="language-rust">let mut mi_variable_mutable = 0;
</code></pre><p>La convención de Rust se basa en las siguientes convenciones de carcasa:</p><!--kg-card-begin: html--><table style="box-sizing: inherit; margin: 0.5em 0px 2.5em; padding: 0px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; line-height: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen, Ubuntu, Cantarell, &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 1.6rem; vertical-align: top; border-spacing: 0px; border-collapse: collapse; display: inline-block; overflow-x: auto; max-width: 100%; width: auto; white-space: nowrap; background: radial-gradient(at left center, rgba(0, 0, 0, 0.2) 0px, rgba(0, 0, 0, 0) 75%) 0px center / 10px 100% no-repeat scroll, radial-gradient(at right center, rgba(0, 0, 0, 0.2) 0px, rgba(0, 0, 0, 0) 75%) 100% center / 10px 100% scroll rgb(255, 255, 255); color: rgb(10, 10, 35); letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><thead style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><tr style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><th style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 1.2rem; vertical-align: baseline; color: var(--gray85); letter-spacing: 0.2px; text-align: left; text-transform: uppercase; background-color: var(--gray10);">OBJECT</th><th style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 1.2rem; vertical-align: baseline; color: var(--gray85); letter-spacing: 0.2px; text-align: left; text-transform: uppercase; background-color: var(--gray10);">CASING</th></tr></thead><tbody style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><tr style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to right, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-size: 20px 100%; background-repeat: no-repeat;">Variables</td><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to left, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-position: 100% 0px; background-size: 20px 100%; background-repeat: no-repeat;">snake_case</td></tr><tr style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to right, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-size: 20px 100%; background-repeat: no-repeat;">Functions</td><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to left, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-position: 100% 0px; background-size: 20px 100%; background-repeat: no-repeat;">snake_case</td></tr><tr style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to right, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-size: 20px 100%; background-repeat: no-repeat;">Files</td><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to left, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-position: 100% 0px; background-size: 20px 100%; background-repeat: no-repeat;">snake_case</td></tr><tr style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to right, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-size: 20px 100%; background-repeat: no-repeat;">Constants</td><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to left, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-position: 100% 0px; background-size: 20px 100%; background-repeat: no-repeat;">SCREAMING_SNAKE_CASE</td></tr><tr style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to right, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-size: 20px 100%; background-repeat: no-repeat;">Statics</td><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to left, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-position: 100% 0px; background-size: 20px 100%; background-repeat: no-repeat;">SCREAMING_SNAKE_CASE</td></tr><tr style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to right, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-size: 20px 100%; background-repeat: no-repeat;">Types</td><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to left, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-position: 100% 0px; background-size: 20px 100%; background-repeat: no-repeat;">PascalCase</td></tr><tr style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to right, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-size: 20px 100%; background-repeat: no-repeat;">Traits</td><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to left, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-position: 100% 0px; background-size: 20px 100%; background-repeat: no-repeat;">PascalCase</td></tr><tr style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline;"><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to right, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-size: 20px 100%; background-repeat: no-repeat;">Enums</td><td style="box-sizing: inherit; margin: 0px; padding: 6px 12px; border: var(--gray10) 1px solid; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 16px; vertical-align: baseline; background-image: linear-gradient(to left, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0) 100%); background-position: 100% 0px; background-size: 20px 100%; background-repeat: no-repeat;">PascalCase</td></tr></tbody></table><!--kg-card-end: html--><p>Dado que Rust se escribe estáticamente, necesitarás escribir variables explícitamente, a menos que la variable se declare con <code>let</code> y el tipo se pueda inferir.</p><h3 id="funciones-en-rust"><strong>Funciones en Rust</strong></h3><p>Declaras funciones usando la palabra clave <code>fn</code>:</p><pre><code class="language-rust">fn main() {
  // Este es un comentario de código
}
</code></pre><p>Las funciones devuelven usando la palabra clave <code>return</code>, y necesitas especificar explícitamente el tipo de retorno de una función, a menos que el tipo de retorno sea una tupla vacía <code>()</code>:</p><pre><code class="language-rust">fn main() -&gt; () { // Tipo de retorno innecesario
  mi_func();
}

fn mi_func() -&gt; u8 {
  return 0;
}
</code></pre><p>Las funciones también devuelven una expresión que carece del punto y coma:</p><pre><code class="language-rust">fn mi_func() -&gt; u8 {
  0
}
</code></pre><p>Los parámetros de la función se escriben usando la sintaxis <code>:</code>:</p><pre><code class="language-rust">fn main() {
  let _variable_no_usada = mi_func(10);
}

fn mi_func(x: u8) -&gt; i32 {
  x as i32
}
</code></pre><p>El guion bajo antes del nombre de una variable es una convención para indicar que la variable no está utilizada. La palabra clave <code>as</code> afirma el tipo de la expresión, siempre que la conversión de tipo sea válida.</p><h3 id="cadenas-y-slices-en-rust">Cadenas y slices en Rust</h3><p>Un punto común de confusión para los Rust principiantes es la diferencia entre el struc (tipo de dato) de <code>String</code> y el tipo <code>str</code>.</p><pre><code class="language-rust">let mi_str: &amp;str = "Hola, mundo!";

let mi_cadena: String = String::from("Hola, mundo!");
</code></pre><p>En el ejemplo anterior, <code>mi_str</code> es una referencia a un literal de cadena, y <code>mi_cadena</code> es una instancia de la estructura de <code>String</code>.</p><p>Una distinción importante entre los dos es que <code>mi_str</code> se almacena en la pila, y <code>mi_cadena</code> se asigna a la pila. Esto significa que el valor de <code>mi_str</code> no puede cambiar, y su tamaño es fijo, mientras que <code>my_cadena</code> puede tener un tamaño desconocido en tiempo de compilación.</p><p>El <em>literal de cadena</em> también se conoce como un <em>segmento de cadena</em>. Esto se debe a que a <code>&amp;str</code> se refiere a una parte de una cadena. En general, así es como los arreglos y las cadenas son similares:</p><pre><code class="language-rust">let mi_cadena = String::from("El zorro marrón rápido");
let mi_str: &amp;str = &amp;my_string[3..8]; // "zorro"

let mi_arr: [usize; 5] = [1, 2, 3, 4, 5];
let mi_arr_slice: &amp;[usize] = &amp;my_arr[0..3]; // [1, 2, 3]
</code></pre><p>La notación <code>[T; n]</code> se utiliza para crear un arreglo de <code>n</code> elementos de tipo <code>T</code>.</p><h3 id="el-tipo-de-char-en-rust">El tipo de <code>char</code> en Rust</h3><p>Un <code>char</code> es un USV (Valor Escalar Unicode), que se representa en unicode con valores como <code>U+221E</code>, el unicode para '∞'. Puede pensar en una colección o arreglo de <code>char</code> como una cadena:</p><pre><code class="language-rust">let mi_str: &amp;str = "Hola, mundo!";

let colleccion_de_chars: &amp;str = mi_str.chars().as_str();
</code></pre><h3 id="tipos-de-n-meros-en-rust">Tipos de números en Rust</h3><p>Hay muchos tipos de números en Rust:</p><ul><li>Enteros sin signo: <code>u8</code>, <code>u16</code>, <code>u32</code>, <code>u64</code>, <code>u128</code></li><li>Enteros firmados: <code>i8</code>, <code>i16</code>, <code>i32</code>, <code>i64</code>, <code>i128</code></li><li>Números de punto flotante: <code>f32</code>, <code>f64</code></li></ul><p>Los enteros sin signo solo representan números enteros positivos</p><p>Los enteros con signo representan números enteros positivos y negativos.</p><p>Y los flotadores solo representan fracciones positivas y negativas.</p><h3 id="structs-en-rust">Structs en Rust</h3><p>Un <em>struc</em> es un tipo de datos personalizado que se utiliza para agrupar datos relacionados. Ya te has encontrado con una struct en la sección <a href="#cadenas-y-slices-en-rust">Cadenas y Slices</a>:</p><pre><code class="language-rust">struct String {
  vec: Vec&lt;u8&gt;,
}
</code></pre><p>La struct de <code>String</code> consiste en un campo <code>vec</code>, que es un <code>Vec</code> de <code>u8</code>s. El <code>Vec</code> es un arreglo de tamaño dinámico.</p><p>Una instancia de un struct despues se declara dando valores a los campos:</p><pre><code class="language-rust">struct MiStruct {
  field_1: u8,
}

let mi_struct = MiStruct { field_1: 0, };
</code></pre><p>Anteriormente, el struct de <code>String</code> se usaba con su función <code>from</code> para crear una <code>String</code> de un <code>&amp;str</code>. Esto es posible, porque la función <code>from</code> está implementada para <code>String</code>:</p><pre><code class="language-rust">impl String {
  fn from(s: &amp;str) -&gt; Self {
    String {
      vec: Vec::from(s.as_bytes()),
    }
  }
}
</code></pre><p>Tu utilizas la palabra clave <code>Self</code> en lugar del tipo de struct.</p><p>Structs también pueden tomar otras variantes:</p><pre><code class="language-rust">struct MiUnitStruct;
struct MiTupleStruct(u8, u8);
</code></pre><h3 id="enumeros-en-rust"><strong>Enumeros en Rust</strong></h3><p>Al igual que en otros lenguajes, los enum son útiles para actuar como tipos y como valores.</p><pre><code class="language-rust">enum MisErrores {
  DemasiadoCansado,
 HoraDelDia(String)
  TazaDeCafeVacia,
}

fn trabajo() -&gt; Resultado&lt;(), MisErrores&gt; { // Resultado tambien es un enum
  if state == "falta punto y coma" {
    Err(MisErrores::DemasiadoCansado)
  } else if state == "06:00" {
    Err(MisErrores::HoraDelDia("Es demasiado pronto para trabajar".to_string()))
  } else if state == "22:00" {
    Err(MisErrores::HoraDelDia("Es demasiado tarde para trabajar".to_string()))
  } else if state == "empty" {
    Err(MisErrores::TazaDeCafeVacia)
  } else {
    Ok(())
  }
}
</code></pre><h3 id="macros-en-rust"><strong>Macros en Rust</strong></h3><p>Una macro es similar a una función, pero se puede pensar en ella como una pieza de código que escribe otro código. Por ahora, las principales diferencias entre una función y una macro a tener en cuenta son:</p><ul><li>Las macros se llaman usando un bang (<code>!</code>)</li><li>Las macros pueden tomar un número variable de argumentos, mientras que las funciones de Rust no pueden</li></ul><p>Una de las macros más comunes es <code>println!</code> macro, que se imprime en la consola:</p><pre><code class="language-rust">let my_str = "Hola, mundo!";
println!("{}", mi_str);
</code></pre><p>Se utiliza la sintaxis <code>{}</code> para insertar una variable en una cadena.</p><p>Otra macro común es <code>panic!</code>. <em>Entrar en pánico</em> es la forma que Rust trabaja con &nbsp;"errores". Es prudente pensar en un panic en Rust como un error mal manejado. La macro acepta un literal de cadena y entra en pánico con ese mensaje.</p><pre><code class="language-rust">let yo_soy_un_error = true;

if (yo_soy_un_error) {
  panic!("Ha habido un error");
}
</code></pre><pre><code class="language-bash">$ cargo run
   Compiling fcc-rust-in-replit v0.1.0 (/home/runner/Rust-in-Replit)
    Finished dev [unoptimized + debuginfo] target(s) in 1.66s
     Running `target/debug/calculator`
thread 'main' panicked at 'Hubo un error', src/main.rs
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
</code></pre><h3 id="propiedad-en-rust"><strong>Propiedad en Rust</strong></h3><p>Un concepto importante en Rust es la <em>propiedad</em>. Hay tres reglas principales de <em>propiedad</em>:</p><ul><li>Cada valor en Rust tiene una variable que se llama su <em>propietario</em>.</li><li>Solo puede haber un propietario a la vez.</li><li>Cuando el propietario se salga del alcance, el valor se eliminará.(<a href="https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html?highlight=heap#ownership-rules">Fuente: The Rust Book</a>)</li></ul><p>Así es como Rust se sale con la suya al no tener un colector de basura típico, al tiempo que no requiere que el programador administre explícitamente la memoria. Aquí hay un ejemplo de propiedad:</p><pre><code class="language-rust">fn main() { // primera_cadena aún no está declarado -&gt; no tiene valor
  let primera_cadena = String::from("freeCodeCamp"); // primera_cadena ahora es el propietario del valor "freeCodeCamp"
  let segunda_cadena = primera_cadena; // segunda_cadena toma posesión del valor "freeCodeCamp"

  println!("Hola, {}!", primera_cadena); // primera_cadena NO es válida, porque el valor se movió a segunda_cadena
}
</code></pre><p>Como la <code>println!</code> macro intenta hacer referencia a una variable no válida, este código no se compila. Para solucionar esto, en lugar de mover el valor de <code>primera_cadena</code> a <code>segunda_cadena</code>, se puede asignar a <code>segunda_cadena</code> una referencia a <code>primera_cadena</code>:</p><pre><code class="language-rust">fn main() {
  let first_string: String = String::from("freeCodeCamp");
  let second_string: &amp;String = &amp;first_string; // first_string is still the owner of the value "freeCodeCamp"

  println!("Hello, {}!", first_string);
}
</code></pre><p>El ampersand (<code>&amp;</code>) indica que el valor es una referencia. Es decir, <code>segunda_cadena</code> ya no toma posesión de <code>"freeCodeCamp"</code>, sino que apunta al mismo punto en memoria que <code>primera_cadena</code>.</p><h2 id="proyecto-1-construir-una-calculadora-de-cli-en-rust">Proyecto # 1-Construir una calculadora de CLI en Rust</h2><h3 id="resultado-del-proyecto">Resultado del proyecto</h3><p>Al final de este proyecto, podrás realizar operaciones aritméticas básicas sobre números utilizando la línea de comandos.</p><p>Los ejemplos de entrada y salida esperados se ven así:</p><pre><code class="language-bash">$ calculator 1 + 1
$ 1 + 1 = 2

$ calculator 138 / 4
$ 138 / 4 = 34.5
</code></pre><h3 id="calculadora-de-cli-metodolog-a-de-proyecto">Calculadora de CLI metodología de proyecto</h3><h4 id="paso-1-crear-un-nuevo-proyecto">Paso 1-Crear un nuevo proyecto</h4><p>Usa Cargo para crear un nuevo proyecto llamado <code>calculator</code>:</p><pre><code class="language-bash">$ cargo new calculator
</code></pre><p>Esto crea un nuevo directorio llamado <code>calculator</code>, lo inicializa como un repositorio Git y agrega una plantilla útil para tu proyecto.</p><p>Esta plantilla incluye:</p><ul><li><code>Cargo.toml</code> – El archivo de manifiesto utilizado por Cargo para administrar los metadatos de tu proyecto</li><li><code>src/</code> – El directorio donde debe estar el código del proyecto</li><li><code>src/main.rs</code> – El archivo predeterminado que Cargo usa como punto de entrada de la aplicación</li></ul><h4 id="paso-2-comprender-la-sintaxis">Paso 2-Comprender la sintaxis</h4><p>El archivo <code>calculator/Cargo.toml</code> contiene lo siguiente:</p><pre><code class="language-toml">[package]
name = "calculator"
version = "0.1.0"
edition = "2018"

# Ve más claves y sus definiciones en https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

</code></pre><p>El <code>[package]</code> indica los metadatos de tu proyecto.</p><p>El encabezado <code>[dependencies]</code> indica las cajas de las que depende el proyecto. Las cajas son como librerias externas.</p><p>El archivo <code>calculator/src/main.rs</code> contiene lo siguiente:</p><pre><code class="language-rust">fn main() {
  println!("Hola, mundo!");
}
</code></pre><p>Este archivo contiene una declaración de función con el identificador <code>main</code>. De forma predeterminada, rustc llama a la función <code>main</code> primero cada vez que se ejecuta el ejecutable.</p><p><code>println!</code> es una macro incorporada que se imprime en la consola.</p><h3 id="paso-3-ejecutar-el-proyecto">Paso 3-Ejecutar el proyecto</h3><p>Puedes usar Cargo para ejecutar el código de tu proyecto:</p><pre><code class="language-bash"># Within the calculator/ directory
$ cargo run
   Compiling fcc-rust-in-replit v0.1.0 (/home/runner/Rust-in-Replit-1)
    Finished dev [unoptimized + debuginfo] target(s) in 0.80s
     Running `target/debug/calculator`
Hello, world!
</code></pre><p>O bien, puede usar rustc para compilar su proyecto, luego puede ejecutar el binario:</p><pre><code class="language-bash"># Dentro de la calculator/ directory
$ rustc src/main.rs
$ ./main
Hola, mundo!
</code></pre><h4 id="paso-4-argumentos-de-la-l-nea-de-comandos">Paso 4-Argumentos de la línea de comandos</h4><p>La libreria estándar de Rust viene con un módulo <code>env</code>, que permite el acceso a los argumentos de la línea de comandos pasados al llamar al programa.</p><p>Las exportaciones necesarias desde el módulo <code>env</code> son la función <code>args</code> y la estructura <code>Args</code>. La función <code>args</code> devuelve una instancia de la struct <code>Args</code> y se importa al ámbito de archivo con:</p><pre><code class="language-rust">use std::env::{args, Args};
</code></pre><p>Para tener una idea de cómo se ve la estructura <code>Args</code>, la variable <code>args</code> se imprime en la consola:</p><pre><code class="language-rust">fn main() {
  let args: Args = args();
  println!("{:?}", args);
}
</code></pre><pre><code class="language-bash">$ cargo run -- fCC
   Compiling calculator v0.1.0 (/home/runner/Rust-in-Replit/calculator)
    Finished dev [unoptimized + debuginfo] target(s) in 1.71s
     Running `target/debug/calculator`
Args { inner: ["target/debug/toto", "fCC"] }
</code></pre><p>Lo anterior muestra que la estructura <code>Args</code> contiene un <code>field</code> llamado <code>inner</code> que consiste en la ubicación del binario compilado y los argumentos de la línea de comandos pasados al programa.</p><p>Para acceder a los valores de los argumentos, puede usar el método n-ésimo en la variable args. El método n-ésimo toma un argumento de índice y devuelve el valor de ese índice envuelto en una opción. Por lo tanto, el valor debe desenvolverse.</p><pre><code class="language-rust">fn main() {
  let mut args: Args = args();

  let first: String = args.nth(1).unwrap();
}
</code></pre><p>La variable <code>args</code> debe declararse como mutable, porque el método <code>nth</code> mutable itera sobre los elementos y elimina el elemento al que se accede.</p><pre><code class="language-rust">fn main() {
  let mut args: Args = args();

  // El primer argumento es la ubicación del binario compilado, así que saltar
  let primero: String = args.nth(1).unwrap();
  // Después de acceder al segundo argumento, el elemento iterador siguiente se convierte en el primero
  let operador: String = args.nth(0).unwrap();
  let segundo: String = args.nth(0).unwrap();

  println!("{} {} {}", primero, operador, segundo);
}
</code></pre><pre><code class="language-bash">$ cargo run -- 1 + 1
   Compiling calculator v0.1.0 (/home/runner/Rust-in-Replit/calculator)
    Finished dev [unoptimized + debuginfo] target(s) in 1.71s
     Running `target/debug/calculator`
1 + 1
</code></pre><h4 id="paso-5-analiza-cadenas-en-n-meros">Paso 5-Analiza cadenas en números</h4><p>La <code>primero</code> y <code>segundo</code> variables son cadenas, y es necesario analizar en números. La struct de <code>String</code> implementa el método <code>parse</code>, que toma una anotación de tipo y devuelve un <code>Result</code> que contiene el valor analizado.</p><pre><code class="language-rust">use std::env::{args, Args};

fn main() {
  let mut args: Args = args();

  let primero: String = args.nth(1).unwrap();
  let operador: String = args.nth(0).unwrap();
  let segundo: String = args.nth(0).unwrap();

  let primer_numero = primero.parse::&lt;f32&gt;().unwrap();
  let segundo_numero = segundo.parse::&lt;f32&gt;().unwrap();

  println!("{} {} {}", primer_numero, operador, segundo_numero);
}
</code></pre><p>El método de <code>parse</code> anterior utiliza la sintaxis <em>turbofish</em> para especificar el tipo en el que se intentará analizar la cadena.</p><h4 id="paso-6-realiza-operaciones-aritm-ticas-b-sicas">Paso 6-Realiza operaciones aritméticas básicas</h4><p>Rust utiliza los operadores estándar para sumar, restar, multiplicar y dividir.</p><p>Para manejar las operaciones, se define una función llamada <code>operate</code> que tomará tres argumentos: el operador como un <code>char</code> y los dos números como <code>f32</code>s. La función también debe devolver un <code>f32</code> que represente el resultado de la operación.</p><pre><code class="language-rust">fn operate(operador: char, primer_numero: f32, segundo_numero: f32) -&gt; f32 {
  match operador {
    '+' =&gt; primer_numero + segundo_numero,
    '-' =&gt; primer_numero - segundo_numero,
    '/' =&gt; primer_numero / segundo_numero,
    '*' | 'X' | 'x' =&gt; primer_numero * segundo_numero,
    _ =&gt; panic!("Operador utilizado no válido."),
  }
}
</code></pre><p>La expresión <code>match</code> funciona de manera similar a una sentencia <code>switch</code> en otros lenguajes de programación. La expresión <code>match</code> toma un valor y una lista de <em>arms</em>. Cada <em>arm</em> es un patrón y un bloque. El patrón es un valor con el que se puede coincidir, y el bloque es el código que se debe ejecutar si el patrón coincide. El patrón <code>_</code> es un comodín, que actúa como una cláusula <code>else</code>.</p><p>La multiplicación <em>arm</em> incluye la comparación <code>OR</code> para permitir que se manejen los casos de <code>X</code> y <code>x</code>.</p><p>Ahora, para llamar a <code>operate</code> con el <code>operador</code>, primero debe convertirlo en un <code>char</code>. Esto se hace con el método <code>chars</code> en la struct de <code>String</code>, que devuelve un iterador sobre los caracteres de la cadena. Luego, se desenvuelve el primer carácter:</p><pre><code class="language-rust">fn main() {
  let mut args: Args = args();

  let primero: String = args.nth(1).unwrap();
  let operador: char = args.nth(0).unwrap().chars().next().unwrap();
  let segundo: String = args.nth(0).unwrap();

  let primer_numero = primero.parse::&lt;f32&gt;().unwrap();
  let segundo_numero = segundo.parse::&lt;f32&gt;().unwrap();
  let resultado = operate(operador, primer_numero, segundo_numero);

  println!("{} {} {}", primer_numero, operador, segundo_numero);
}
</code></pre><p>El retorno de <code>operate</code> se almacena en la variable <code>resultado</code>.</p><h4 id="paso-7-formatear-la-salida">Paso 7-Formatear la salida</h4><p>Para obtener el resultado deseado, las variables <code>primer_numero</code>, <code>segungo_numero</code>, <code>operador</code> y <code>resultado</code> deben formatearse. ¡Puedes usar el <code>format!</code> macro para crear una <code>String</code> a partir de una cadena de formato y una lista de argumentos:</p><pre><code class="language-rust">fn resultado(primer_numero: f32, operador: char, segundo_numero: f32, resultado: f32) -&gt; String {
  format!(
    "{} {} {} = {}",
    primer_numero, operador, segundo_numero, resultado
  )
}
</code></pre><h4 id="paso-8-re-ne-todo">Paso 8-Reúne Todo</h4><pre><code class="language-rust">use std::env::{args, Args};

fn main() {
  let mut args: Args = args();

  let primero: String = args.nth(1).unwrap();
  let operador: char = args.nth(0).unwrap().chars().next().unwrap();
  let segundo: String = args.nth(0).unwrap();

  let primer_numero = primero.parse::&lt;f32&gt;().unwrap();
  let segundo_numero = segundo.parse::&lt;f32&gt;().unwrap();
  let resultado = operate(operador, primer_numero, segundo_numero);

  println!("{}", resultado(primer_numero, operador, segundo_numero, resultado));
}

fn resultado(primer_numero: f32, operador: char, segundo_numero: f32, resultado: f32) -&gt; String {
  format!(
    "{} {} {} = {}",
    primer_numero, operador, segundo_numero, resultado
  )
}

fn operate(operador: char, primer_numero: f32, segundo_numero: f32) -&gt; f32 {
  match operador {
    '+' =&gt; primer_numero + segundo_numero,
    '-' =&gt; primer_numero - segundo_numero,
    '/' =&gt; primer_numero / segundo_numero,
    '*' | 'X' | 'x' =&gt; primer_numero * segundo_numero,
    _ =&gt; panic!("Operador utilizado no válido."),
  }
}
</code></pre><p>Para crear el código en un binario ejecutable, ejecuta el siguiente comando:</p><pre><code class="language-bash">$ cargo build --release
   Compiling calculator v0.1.0 (/home/runner/Rust-in-Replit/calculator)
    Finished release [optimized] target(s) in 3.26s
</code></pre><p>La bandera <code>--release</code> release indica a Cargo que compile el binario en modo release. Esto reducirá el tamaño del binario y también eliminará cualquier información de depuración.</p><p>El binario está construido en el directorio <code>target/release</code>. Para ejecutar el binario y probar la aplicación, ejecuta el siguiente comando:</p><pre><code class="language-bash">$ target/release/calculator 1 + 1
1 + 1 = 2
</code></pre><h2 id="proyecto-2-construye-un-combinador-de-im-genes-en-rust">Proyecto # 2-Construye un combinador de imágenes en Rust</h2><h3 id="resultado-del-proyecto-1">Resultado del proyecto</h3><p>Al final de este proyecto, podrás combinar dos imágenes utilizando la línea de comandos.</p><p>Aquí hay un ejemplo de una entrada esperada:</p><pre><code class="language-bash">$ combiner ./image1.png ./image2.png ./output.png
</code></pre><p>Para ver un ejemplo de la salida, no busques más allá de la primera imagen de este artículo ☝️</p><h3 id="metodolog-a-del-proyecto-combinador-de-im-genes">Metodología del proyecto combinador de Imágenes</h3><h3 id="paso-1-crea-un-nuevo-proyecto">Paso 1-Crea un nuevo proyecto</h3><p>Usa Cargo para crear un nuevo proyecto llamado <code>combiner</code>:</p><pre><code class="language-bash">$ cargo new combiner
</code></pre><h4 id="paso-2-a-ade-un-nuevo-m-dulo-para-args">Paso 2-Añade un nuevo módulo para args</h4><p>Para prevenir la <code>main.rs</code> para que el archivo no se vuelva demasiado abrumador, crea un nuevo archivo con el nombre <code>args.rs</code> en el directorio <code>src</code>.</p><p>Dentro de <code>args.rs</code>, crea una función llamada <code>get_nth_arg</code> que toma un <code>usize</code>, <code>n</code> y devuelve una <code>String</code>. Luego, desde el módulo <code>std::env</code>, llama a la función <code>args</code> y encadena el <code>nth</code> método para obtener el <code>n</code> argumento, desenvolviendo el valor:</p><pre><code class="language-rust">fn get_nth_arg(n: usize) -&gt; String {
  std::env::args().nth(n).unwrap()
}
</code></pre><p>Define una estructura pública llamada <code>Args</code> que conste de tres campos públicos de tipo <code>String</code>: <code>imagen_1</code>, <code>imagen_2</code> y <code>resultado</code>:</p><pre><code class="language-rust">pub struct Args {
  pub imagen_1: String,
  pub imagen_2: String,
  pub resultado: String,
}
</code></pre><p>Declara la struct y sus campos como públicos con la palabra clave <code>pub</code> para que puedas acceder a ellos desde fuera del <code>args.rs</code> archivo.</p><p>Por último, puedes usar la función <code>get_nth_arg</code> para crear una nueva estructura <code>Args</code> en una <code>new</code> función:</p><pre><code class="language-rust">impl Args {
  pub fn new() -&gt; Self {
    Args {
      imagen_1: get_nth_arg(1),
      imagen_2: get_nth_arg(2),
      resultado: get_nth_arg(3),
    }
  }
}
</code></pre><p>Todos juntos, el <code>args.rs</code> el archivo se ve así:</p><pre><code class="language-rust">pub struct Args {
  pub imagen_1: String,
  pub imagen_2: String,
  pub resultado: String,
}

impl Args {
  pub fn new() -&gt; Self {
    Args {
      imagen_1: get_nth_arg(1),
      imagen_2: get_nth_arg(2),
      resultado: get_nth_arg(3),
    }
  }
}

fn get_nth_arg(n: usize) -&gt; String {
  std::env::args().nth(n).unwrap()
}
</code></pre><h4 id="paso-3-importar-y-usar-el-m-dulo-args">Paso 3-Importar y usar el módulo <code>args</code></h4><p>Dentro de <code>main.rs</code>, tienes que declarar la <code>args.rs</code> archivo como módulo. Luego, para usar la estructura <code>Args</code>, debe importarla:</p><pre><code class="language-rust">mod args;
use args::Args;

fn main() {
  let args = Args::new();
  println!("{:?}", args);
}
</code></pre><p>Pero probar el código revela un error:</p><pre><code class="language-bash">$ cargo run -- arg1 arg2 arg3
   Compiling combiner v0.1.0 (/home/runner/Rust-in-Replit/combiner)
error[E0277]: `args::Args` doesn't implement `Debug`
  --&gt; src/main.rs:12:20
   |
12 |   println!("{:?}", args);
   |                    ^^^^ `args::Args` cannot be formatted using `{:?}`
   |
   = help: the trait `Debug` is not implemented for `args::Args`
   = note: add `#[derive(Debug)]` or manually implement `Debug`
   = note: required by `std::fmt::Debug::fmt`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: could not compile `combiner`

To learn more, run the command again with --verbose.
</code></pre><p>De manera similar a cómo se implementan las funciones para estructuras, los rasgos se pueden implementar para estructuras. Sin embargo, el rasgo de <code>Debug</code> es especial en el sentido de que se puede implementar usando atributos:</p><pre><code class="language-rust">#[derive(Debug)]
pub struct Args {
  pub imagen_1: String,
  pub imagen_2: String,
  pub resultado: String,
}
</code></pre><p>El rasgo de <code>Debug</code> se ha derivado para la estructura <code>Args</code>. Esto significa que el rasgo de <code>Debug</code> se implementa automáticamente para la estructura, sin tener que implementarlo manualmente ?.</p><p>Ahora, al ejecutar el código funciona:</p><pre><code class="language-bash">$ cargo run -- arg1 arg2 arg3
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/combiner arg1 arg2 arg3`
Args { imagen_1: "arg1", imagen_2: "arg2", resultado: "arg3" }
</code></pre><h4 id="paso-4-a-adir-una-caja-externa">Paso 4-Añadir una caja externa</h4><p>De la misma manera que otros lenguajes tienen librerias o paquetes, Rust tiene cajas. Para codificar y decodificar imágenes, puedes usar la caja <code>image</code>.</p><p>Agrega la caja <code>image</code> con la versión <code>0.23.14</code> a el archivo <code>Cargo.toml</code>:</p><pre><code class="language-toml">[package]
name = "combiner"
version = "0.1.0"
edition = "2018"

# Ve más claves y sus definiciones en https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
image = "0.23.14"
</code></pre><p>Ahora, cuando se llames a <code>cargo run</code>, Cargo buscará e instalará la caja <code>image</code>.</p><h4 id="paso-5-leer-un-archivo-de-imagen">Paso 5-Leer un archivo de imagen</h4><p>La caja <code>image</code> viene con un módulo de <code>io</code> que incluye una struct de <code>Reader</code>. Esta struct implementa una función <code>open</code> que toma una ruta a un archivo de imagen y devuelve un <code>Result</code> que contiene un <em>reader</em>. Puedes formatear y decodificar este<em> reader</em> para obtener el formato de imagen (por ejemplo, PNG, JGP, etc.) y los datos de imagen.</p><p>Crea una función llamada <code>find_image_from_path</code> para abrir el archivo de imagen desde un argumento de <code>path</code>:</p><pre><code class="language-rust">fn find_image_from_path(path: String) -&gt; (DynamicImage, ImageFormat) {
  let image_reader: Reader&lt;BufReader&lt;File&gt;&gt; = Reader::open(path).unwrap();
  let image_format: ImageFormat = image_reader.format().unwrap();
  let image: DynamicImage = image_reader.decode().unwrap();
  (image, image_format)
}
</code></pre><p>Las variables <code>image</code> y <code>image_format</code> se devuelven como una tupla.</p><p>Incluye las importaciones necesarias en la parte superior del archivo:</p><pre><code class="language-rust">use image::{ io::Reader, DynamicImage, ImageFormat };

fn main() {
  // ...
  let (image_1, image_1_format) = find_image_from_path(args.image_1);
  let (image_2, image_2_format) = find_image_from_path(args.image_2);
}
</code></pre><p>Dentro de <code>main</code>, la tupla devuelta se puede estructurar en dos variables nuevas para cada ruta de imagen.</p><h4 id="paso-6-maneja-errores-con-result">Paso 6-Maneja errores con <code>Result</code></h4><p>Es importante ser capaz de manejar los errores que surgen. Por ejemplo, es posible que tengas un caso en el que se dan dos imágenes de formatos diferentes como argumentos para combinar.</p><p>Una forma semántica de manejar tal error es devolver un <code>Result</code> que puede consistir en un <code>Ok</code> o un <code>Err</code>.</p><pre><code class="language-rust">fn main() -&gt; Result&lt;(), ImageDataErrors&gt; {
  let args = Args::new();
  println!("{:?}", args);

  let (image_1, image_1_format) = find_image_from_path(args.image_1);
  let (image_2, image_2_format) = find_image_from_path(args.image_2);

  if image_1_format != image_2_format {
    return Err(ImageDataErrors::DifferentImageFormats);
  }
  Ok(())
}
</code></pre><p>La función <code>main</code> devuelve un <code>Err</code> que contiene una enumeración con varianza de unidad <code>DifferentImageFormats</code> si los dos formatos de imagen no son iguales. De lo contrario, devuelve un <code>Ok</code> con una tupla vacía.</p><p>La enumeración se define como:</p><pre><code class="language-rust">enum ImageDataErrors {
  DifferentImageFormats,
}
</code></pre><h4 id="paso-7-cambia-el-tama-o-de-las-im-genes-para-que-coincidan">Paso 7-Cambia el tamaño de las imágenes para que coincidan</h4><p>Para facilitar la combinación de las imágenes, cambia el tamaño de la imagen más grande para que coincida con la imagen más pequeña.</p><p>En primer lugar, puedes encontrar la imagen más pequeña utilizando el método <code>dimensions</code>, que devuelve el ancho y el alto de la imagen como una tupla. Estas tuplas se pueden comparar, y la más pequeña devuelve:</p><pre><code class="language-rust">fn get_smallest_dimensions(dim_1: (u32, u32), dim_2: (u32, u32)) -&gt; (u32, u32) {
  let pix_1 = dim_1.0 * dim_1.1;
  let pix_2 = dim_2.0 * dim_2.1;
  return if pix_1 &lt; pix_2 { dim_1 } else { dim_2 };
}
</code></pre><p>Se accede a los valores de la tupla mediante notación de puntos desde la indexación basada en cero.</p><p>Si <code>image_2</code> es la imagen más pequeña, entonces <code>image_1</code> necesita redimensionarse para que coincida con las dimensiones más pequeñas. De lo contrario, <code>image_2</code> necesita redimensionarse.</p><pre><code class="language-rust">fn standardise_size(image_1: DynamicImage, image_2: DynamicImage) -&gt; (DynamicImage, DynamicImage) {
  let (width, height) = get_smallest_dimensions(image_1.dimensions(), image_2.dimensions());
  println!("width: {}, height: {}\n", width, height);

  if image_2.dimensions() == (width, height) {
    (image_1.resize_exact(width, height, Triangle), image_2)
  } else {
    (image_1, image_2.resize_exact(width, height, Triangle))
  }
}
</code></pre><p>El método <code>resize_exact</code> implementado en la struct de <code>DynamicImage</code> mutable toma prestada la imagen y, utilizando los argumentos <code>width</code>, <code>height</code> y <code>filterType</code>, redimensiona la imagen.</p><p>Usando el retorno de la función <code>standardise_size</code>, puede volver a declarar las variables <code>image_1</code> e <code>image_2</code>:</p><pre><code class="language-rust">use image::{ io::Reader, DynamicImage, ImageFormat, imageops::FilterType::Triangle };

fn main() -&gt; Result&lt;(), ImageDataErrors&gt; {
  // ...
  let (image_1, image_2) = standardise_size(image_1, image_2);
  Ok(())
}
</code></pre><h4 id="paso-8-crea-una-imagen-flotante"><strong>Paso 8 – </strong>Crea una imagen flotante</h4><p>Para manejar la salida, crea una struct temporal que contenga los metadatos de la imagen de salida.</p><p>Define una struct llamada <code>FloatingImage</code> para contener el <code>width</code>, <code>height</code> y <code>data</code> de la imagen, así como el <code>name</code> del archivo de salida:</p><pre><code class="language-rust">struct FloatingImage {
  width: u32,
  height: u32,
  data: Vec&lt;u8&gt;,
  name: String,
}
</code></pre><p>A continuación, implementa una <code>new</code> función para la <code>FloatingImage</code> que toma valores para el <code>width</code>, <code>height</code> y el <code>name</code> de la imagen de salida:</p><pre><code class="language-rust">impl FloatingImage {
  fn new(width: u32, height: u32, name: String) -&gt; Self {
    let buffer_capacity = 3_655_744;
    let buffer: Vec&lt;u8&gt; = Vec::with_capacity(buffer_capacity);
    FloatingImage {
      width,
      height,
      data: buffer,
      name,
    }
  }
}
</code></pre><p>Como aún no had creado los datos para la imagen, crea un búfer en forma de <code>Vec</code> de <code>u8</code> con una capacidad de 3.655.744 (956 x 956 x 4). La sintaxis <code>&lt;number&gt;_&lt;number&gt;</code> es la numeración fácil de leer de Rust que separa el número en grupos o tres dígitos.</p><p>Usa los valores de <code>width</code> y <code>height</code> de la variable <code>image_1</code> para crear una instancia de la <code>FloatingImage</code>, y usa el tercer argumento almacenado en <code>args</code> para establecer el nombre de la <code>FloatingImage</code>:</p><pre><code class="language-rust">fn main() -&gt; Result&lt;(), ImageDataErrors&gt; {
  // ...
  let mut output = FloatingImage::new(image_1.width(), image_1.height(), args.output);
  Ok(())
}
</code></pre><p>Declara las variables de <code>outpu</code> como mutables para que pueda modificar el campo de <code>data</code> más adelante.</p><h4 id="paso-9-crea-los-datos-de-imagen-combinados">Paso 9-Crea los datos de imagen combinados</h4><p>Para procesar las imágenes, debes convertirlas en un vector de píxeles RGBA. Los píxeles se almacenan como <code>u8</code>, porque sus valores están entre 0 y 255.</p><p>La struct de <code>DynamicImage</code> implementa el método <code>to_rgba8</code>, que devuelve un <code>ImageBuffer</code> que contiene un <code>Vec&lt;u8&gt;</code>, y el <code>ImageBuffer</code> implementa el método <code>into_vec</code>, que devuelve el <code>Vec&lt;u8&gt;</code>:</p><pre><code class="language-rust">fn combine_images(image_1: DynamicImage, image_2: DynamicImage) -&gt; Vec&lt;u8&gt; {
  let vec_1 = image_1.to_rgba8().into_vec();
  let vec_2 = image_2.to_rgba8().into_vec();

  alternate_pixels(vec_1, vec_2)
}
</code></pre><p>Luego, las variables <code>vec_1</code> y <code>vec_2</code> se pasan a la función <code>alternate_pixels</code>, que devuelve los datos de imagen combinados alternando los conjuntos de píxeles RGBA de las dos imágenes:</p><pre><code class="language-rust">fn alternate_pixels(vec_1: Vec&lt;u8&gt;, vec_2: Vec&lt;u8&gt;) -&gt; Vec&lt;u8&gt; {
  // A Vec&lt;u8&gt; is created with the same length as vec_1
  let mut combined_data = vec![0u8; vec_1.len()];

  let mut i = 0;
  while i &lt; vec_1.len() {
    if i % 8 == 0 {
      combined_data.splice(i..=i + 3, set_rgba(&amp;vec_1, i, i + 3));
    } else {
      combined_data.splice(i..=i + 3, set_rgba(&amp;vec_2, i, i + 3));
    }
    i += 4;
  }

  combined_data
}
</code></pre><p>La función <code>set_rgba</code> toma una referencia a un <code>Vec&lt;u8&gt;</code> y devuelve el conjunto de píxeles RGBA para ese <code>Vec&lt;u8&gt;</code> que comienza y termina en un índice dado:</p><pre><code class="language-rust">fn set_rgba(vec: &amp;Vec&lt;u8&gt;, start: usize, end: usize) -&gt; Vec&lt;u8&gt; {
  let mut rgba = Vec::new();
  for i in start..=end {
    let val = match vec.get(i) {
      Some(d) =&gt; *d,
      None =&gt; panic!("Index out of bounds"),
    };
    rgba.push(val);
  }
  rgba
}
</code></pre><p>El <code>..=</code> syntax es la sintaxis de rango de Rust que permite que el rango incluya el valor final. El símbolo <code>*</code> antes de una variable es el operador de desreferencia de Rust, que permite acceder al valor de la variable.</p><p>Y ahora, asigna el retorno de <code>combine_images</code> a la variable <code>combined_data</code>:</p><pre><code class="language-rust">fn main() -&gt; Result&lt;(), ImageDataErrors&gt; {
  // ...
  let combined_data = combine_images(image_1, image_2);
  Ok(())
}
</code></pre><h4 id="paso-10-adjunta-los-datos-combinados-a-la-imagen-flotante">Paso 10: Adjunta los datos combinados a la imagen flotante</h4><p>Para establecer los datos de <code>combined_data</code> en la imagen de <code>output</code>, se define un método en <code>FloatingImage</code> para establecer el campo de <code>data</code> de <code>output</code> al valor de <code>combined_data</code>.</p><p>Hasta ahora, solo has implementado funciones en struct. Los métodos se definen de manera similar, pero toman una instancia de la struct como su primer argumento:</p><pre><code class="language-rust">struct MyStruct {
  name: String,
}
impl MyStruct {
  fn change_name(&amp;mut self, new_name: &amp;str) {
    self.name = new_name.to_string();
  }
}

let mut my_struct = MyStruct { name: String::from("Shaun") };
// my_struct.name == "Shaun"
my_struct.change_name("Tom");
// my_struct.name == "Tom"
</code></pre><p>Dado que necesitas cambiar el valor de la instancia de <code>FloatingImage</code>, el método <code>set_data</code> toma una referencia mutable a la instancia como primer argumento.</p><pre><code class="language-rust">impl FloatingImage {
  // ...
  fn set_data(&amp;mut self, data: Vec&lt;u8&gt;) -&gt; Result&lt;(), ImageDataErrors&gt; {
    // If the previously assigned buffer is too small to hold the new data
    if data.len() &gt; self.data.capacity() {
      return Err(ImageDataErrors::BufferTooSmall);
    }
    self.data = data;
    Ok(())
  }
}
</code></pre><p>La enumeración debe ampliarse para incluir la nueva variante de unidad <code>BufferTooSmall</code>:</p><pre><code class="language-rust">enum ImageDataErrors {
  // ...
  BufferTooSmall,
}
</code></pre><p><em>Aviso</em>: El método todavía solo se llama con un argumento:</p><pre><code class="language-rust">fn main() -&gt; Result&lt;(), ImageDataErrors&gt; {
  // ...
  output.set_data(combined_data)?;
  Ok(())
}
</code></pre><p>El <code>?</code> sintaxis al final de una expresión es una forma abreviada de manejar el resultado de una llamada a una función. Si la llamada a la función devuelve un error, el operador de <em>propagación de errores</em> devolverá el error de la llamada a la función.</p><h4 id="paso-11-escribe-la-imagen-en-un-archivo">Paso 11-Escribe la imagen en un archivo</h4><p>Por último, guarda la nueva imagen en un archivo. La caja <code>image</code> tiene una función <code>save_buffer_with_format</code> que toma la siguiente forma:</p><pre><code class="language-rust">fn save_buffer_with_format(
    path: AsRef&lt;Path&gt;,
    buf: &amp;[u8],
    width: u32,
    height: u32,
    color: image::ColorType,
    format: image::ImageFormat
  ) -&gt; image::ImageResult&lt;()&gt;;
</code></pre><p>Dado que <code>AsRef</code> está implementado para <code>String</code>, puedes usar un argumento de tipo <code>String</code> para el <code>path</code>.</p><pre><code class="language-rust">fn main() -&gt; Result&lt;(), ImageDataErrors&gt; {
  // ...
  image::save_buffer_with_format(
    output.name,
    &amp;output.data,
    output.width,
    output.height,
    image::ColorType::Rgba8,
    image_1_format,
  )
  .unwrap();
  Ok(())
}
</code></pre><h4 id="paso-12-une-todo">Paso 12-Une todo</h4><p>Aquí está el código final:</p><pre><code class="language-rust">mod args;

use args::Args;
use image::{
  imageops::FilterType::Triangle, io::Reader, DynamicImage, GenericImageView, ImageFormat,
};

fn main() -&gt; Result&lt;(), ImageDataErrors&gt; {
  let args = Args::new();
  println!("{:?}", args);

  let (image_1, image_1_format) = find_image_from_path(args.image_1);
  let (image_2, image_2_format) = find_image_from_path(args.image_2);

  if image_1_format != image_2_format {
    return Err(ImageDataErrors::DifferentImageFormats);
  }

  let (image_1, image_2) = standardise_size(image_1, image_2);
  let mut output = FloatingImage::new(image_1.width(), image_1.height(), args.output);

  let combined_data = combine_images(image_1, image_2);

  output.set_data(combined_data)?;

  image::save_buffer_with_format(
    output.name,
    &amp;output.data,
    output.width,
    output.height,
    image::ColorType::Rgba8,
    image_1_format,
  )
  .unwrap();
  Ok(())
}

enum ImageDataErrors {
  BufferTooSmall,
  DifferentImageFormats,
}

struct FloatingImage {
  width: u32,
  height: u32,
  data: Vec&lt;u8&gt;,
  name: String,
}

impl FloatingImage {
  fn new(width: u32, height: u32, name: String) -&gt; Self {
    let buffer_capacity = 3_655_744;
    let buffer: Vec&lt;u8&gt; = Vec::with_capacity(buffer_capacity);
    FloatingImage {
      width,
      height,
      data: buffer,
      name,
    }
  }
  fn set_data(&amp;mut self, data: Vec&lt;u8&gt;) -&gt; Result&lt;(), ImageDataErrors&gt; {
    if data.len() &gt; self.data.capacity() {
      return Err(ImageDataErrors::BufferTooSmall);
    }
    self.data = data;
    Ok(())
  }
}

fn find_image_from_path(path: String) -&gt; (DynamicImage, ImageFormat) {
  let image_reader = Reader::open(path).unwrap();
  let image_format = image_reader.format().unwrap();
  let image = image_reader.decode().unwrap();
  (image, image_format)
}

fn standardise_size(image_1: DynamicImage, image_2: DynamicImage) -&gt; (DynamicImage, DynamicImage) {
  let (width, height) = get_smallest_dimensions(image_1.dimensions(), image_2.dimensions());
  println!("width: {}, height: {}\n", width, height);
  if image_2.dimensions() == (width, height) {
    (image_1.resize_exact(width, height, Triangle), image_2)
  } else {
    (image_1, image_2.resize_exact(width, height, Triangle))
  }
}

fn get_smallest_dimensions(dim_1: (u32, u32), dim_2: (u32, u32)) -&gt; (u32, u32) {
  let pix_1 = dim_1.0 * dim_1.1;
  let pix_2 = dim_2.0 * dim_2.1;
  return if pix_1 &lt; pix_2 { dim_1 } else { dim_2 };
}

fn combine_images(image_1: DynamicImage, image_2: DynamicImage) -&gt; Vec&lt;u8&gt; {
  let vec_1 = image_1.to_rgba8().into_vec();
  let vec_2 = image_2.to_rgba8().into_vec();

  alternate_pixels(vec_1, vec_2)
}

fn alternate_pixels(vec_1: Vec&lt;u8&gt;, vec_2: Vec&lt;u8&gt;) -&gt; Vec&lt;u8&gt; {
  let mut combined_data = vec![0u8; vec_1.len()];

  let mut i = 0;
  while i &lt; vec_1.len() {
    if i % 8 == 0 {
      combined_data.splice(i..=i + 3, set_rgba(&amp;vec_1, i, i + 3));
    } else {
      combined_data.splice(i..=i + 3, set_rgba(&amp;vec_2, i, i + 3));
    }
    i += 4;
  }

  combined_data
}

fn set_rgba(vec: &amp;Vec&lt;u8&gt;, start: usize, end: usize) -&gt; Vec&lt;u8&gt; {
  let mut rgba = Vec::new();
  for i in start..=end {
    let val = match vec.get(i) {
      Some(d) =&gt; *d,
      None =&gt; panic!("Index out of bounds"),
    };
    rgba.push(val);
  }
  rgba
}
</code></pre><p>Construyendo el binario:</p><pre><code class="language-bash">$ cargo build --release
</code></pre><p>Crear una imagen combinada, usando las imágenes en <a href="https://github.com/freeCodeCamp/Rust-In-Replit">freeCodeCamp/Rust-In-Replit</a>:</p><pre><code class="language-bash">$ ./target/release/combiner images/pro.png images/fcc_glyph.png images/output.png
</code></pre><p>Y aquí está el resultado en <code>images/output.png</code>:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/11/output.png" class="kg-image" alt="Output combined image" width="600" height="400" loading="lazy"></figure><h2 id="conclusion">Conclusion</h2><p>Con eso, ahora conoces los conceptos básicos de Rust.</p><p>Todavía hay mucho por aprender. Por lo tanto, mira este espacio para obtener más contenido ?.</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
