<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Gaurav Gahlot</title>
    <description>The latest articles on Forem by Gaurav Gahlot (@gauravgahlot).</description>
    <link>https://forem.com/gauravgahlot</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F516503%2Fac48237b-f853-4029-b8f7-0831c989480f.jpeg</url>
      <title>Forem: Gaurav Gahlot</title>
      <link>https://forem.com/gauravgahlot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gauravgahlot"/>
    <language>en</language>
    <item>
      <title>RustHours - Getting Started with Rust</title>
      <dc:creator>Gaurav Gahlot</dc:creator>
      <pubDate>Thu, 26 Dec 2024 15:42:38 +0000</pubDate>
      <link>https://forem.com/gauravgahlot/rusthours-getting-started-with-rust-5bkm</link>
      <guid>https://forem.com/gauravgahlot/rusthours-getting-started-with-rust-5bkm</guid>
      <description>&lt;p&gt;The very first live stream on Rust Hours. We started from zero to building a very small CLI application. The stream aims to help everyone learn Rust with a “follow along” approach.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/bDSZXoaNrw4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>rust</category>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Secure Your Kubernetes Applications with Self-Signed Certificates</title>
      <dc:creator>Gaurav Gahlot</dc:creator>
      <pubDate>Sun, 29 Sep 2024 14:01:55 +0000</pubDate>
      <link>https://forem.com/gauravgahlot/secure-your-kubernetes-applications-with-self-signed-certificates-jfj</link>
      <guid>https://forem.com/gauravgahlot/secure-your-kubernetes-applications-with-self-signed-certificates-jfj</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Securing communication in microservices is a fundamental step to protect sensitive data and enforce privacy standards. Kubernetes supports several methods for securing applications. One such approach is to use SSL/TLS for encrypting traffic, and a cost-effective way to achieve this is by utilizing self-signed certificates.&lt;/p&gt;

&lt;p&gt;In this blog post, I will walk you through the steps to secure your Kubernetes applications using self-signed certificates.&lt;/p&gt;

&lt;p&gt;Let's get to it.&lt;/p&gt;



&lt;h2&gt;
  
  
  The Application
&lt;/h2&gt;

&lt;p&gt;Our application is a basic HTTP server that serves a list of to-do items. Here’s the complete code with comments for clarity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/json"&lt;/span&gt; &lt;span class="c"&gt;// Provides functions for encoding and decoding JSON data&lt;/span&gt;
    &lt;span class="s"&gt;"log/slog"&lt;/span&gt;      &lt;span class="c"&gt;// A package for structured logging&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;      &lt;span class="c"&gt;// Provides HTTP client and server implementations&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;          &lt;span class="c"&gt;// Provides functionality for measuring and displaying time&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/google/uuid"&lt;/span&gt; &lt;span class="c"&gt;// Generates universally unique identifiers (UUIDs)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// The port on which the HTTP server will listen for incoming requests.&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;":80"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Register the 'handleTodo' function to handle requests to the '/todo' path.&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handleTodo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"starting HTTP server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Starts the HTTP server on the specified port.&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"server failure"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// handleTodo handles the /todo URL path&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;handleTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"request received at path /todo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Set the 'Content-Type' header and HTTP status code of the reponse.&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Get a list of to-do items.&lt;/span&gt;
    &lt;span class="n"&gt;todoItems&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getTodoList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Encodes the list of to-do items as JSON and writes it to the HTTP response.&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todoItems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to write response"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// getTodoList returns a list of to-do items&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getTodoList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;todoItem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;todoItem&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;DueDate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"write a todo-app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;DueDate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"define K8s manifests"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;DueDate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"use certificates"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// todoItem defines a to-do item&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;todoItem&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Due date of the to-do item&lt;/span&gt;
    &lt;span class="n"&gt;DueDate&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="s"&gt;`json:"dueDate"`&lt;/span&gt;

    &lt;span class="c"&gt;// A unique identifier for the to-do item&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;    &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;

    &lt;span class="c"&gt;// Title of the to-do item&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;    &lt;span class="s"&gt;`json:"title"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;The above program creates an HTTP server that responds to &lt;code&gt;/todo&lt;/code&gt; requests with a predefined list of to-do items in JSON format. It uses UUIDs for unique identifiers and sets due dates in the future. The server logs important information and errors using the &lt;code&gt;slog&lt;/code&gt; package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate Self-Signed Certificate
&lt;/h2&gt;

&lt;p&gt;As the next step, we need to create a self-signed certificate for our application. In order to do that, we will be using OpenSSL.&lt;/p&gt;

&lt;p&gt;Following are the steps to generate the self-signed certificate using OpenSSL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate an RSA private key
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; tls.key 4096
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;ul&gt;
&lt;li&gt;Generate a CSR (Certificate Signing Request) with the required CN and Subject
Alternative Names (SANs). Use the &lt;code&gt;openssl req&lt;/code&gt; command with the &lt;code&gt;-subj&lt;/code&gt; and
&lt;code&gt;-addext&lt;/code&gt; options:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; tls.key &lt;span class="nt"&gt;-out&lt;/span&gt; tls.csr &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s2"&gt;"/CN=todo-app"&lt;/span&gt; &lt;span class="nt"&gt;-addext&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"subjectAltName=DNS:todo-app.default.svc.cluster.local,DNS:localhost,DNS:todo-app"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;ul&gt;
&lt;li&gt;Generate the Self-Signed Certificate using the information from the CSR:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="nt"&gt;-in&lt;/span&gt; tls.csr &lt;span class="nt"&gt;-signkey&lt;/span&gt; tls.key &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-out&lt;/span&gt; tls.crt &lt;span class="nt"&gt;-extensions&lt;/span&gt; req_ext &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-extfile&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"[req_ext]&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;subjectAltName=DNS:todo-app.default.svc.cluster.local,DNS:localhost,DNS:todo-app"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;ul&gt;
&lt;li&gt;(Optional) To view the content of the generated certificate in a human-readable form, you can use the openssl command-line tool to read the certificate and display its details.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  openssl x509 &lt;span class="nt"&gt;-in&lt;/span&gt; tls.crt &lt;span class="nt"&gt;-text&lt;/span&gt; &lt;span class="nt"&gt;-noout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Cluster Setup
&lt;/h2&gt;

&lt;p&gt;We can leverage &lt;a href="https://kind.sigs.k8s.io/" rel="noopener noreferrer"&gt;Kind&lt;/a&gt;’s &lt;code&gt;extraPortMapping&lt;/code&gt; config option when creating a cluster to forward ports from the host to an ingress controller running on a node.&lt;/p&gt;

&lt;p&gt;Create a kind cluster with &lt;code&gt;extraPortMappings&lt;/code&gt; and &lt;code&gt;node-labels&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;extraPortMappings&lt;/code&gt; allow the local host to make requests to the Ingress
controller over ports &lt;code&gt;80/443&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node-labels&lt;/code&gt; only allow the ingress controller to run on a specific node(s)
matching the label selector
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Three node cluster with an ingress-ready control-plane node&lt;/span&gt;
&lt;span class="c1"&gt;# and extra port mappings over 80/443 and 2 workers.&lt;/span&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cluster&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kind.x-k8s.io/v1alpha4&lt;/span&gt;
&lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;control-plane&lt;/span&gt;
    &lt;span class="na"&gt;kubeadmConfigPatches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;kind: InitConfiguration&lt;/span&gt;
        &lt;span class="s"&gt;nodeRegistration:&lt;/span&gt;
          &lt;span class="s"&gt;kubeletExtraArgs:&lt;/span&gt;
            &lt;span class="s"&gt;node-labels: "ingress-ready=true"&lt;/span&gt;
    &lt;span class="na"&gt;extraPortMappings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
        &lt;span class="na"&gt;hostPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
        &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;443&lt;/span&gt;
        &lt;span class="na"&gt;hostPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;443&lt;/span&gt;
        &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Check the cluster state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.kube/kind.yaml

➜ kubectl get nodes
NAME                 STATUS   ROLES           AGE     VERSION
kind-control-plane   Ready    control-plane   7d20h   v1.27.3
kind-worker          Ready    &amp;lt;none&amp;gt;          7d20h   v1.27.3
kind-worker2         Ready    &amp;lt;none&amp;gt;          7d20h   v1.27.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;strong&gt;Ingress NGINX&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The manifests contains kind specific patches to forward the hostPorts to the ingress controller, set taint tolerations and schedule it to the custom labelled node.&lt;/p&gt;

&lt;p&gt;Now the Ingress is all setup. Wait until it's ready to process requests by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--namespace&lt;/span&gt; ingress-nginx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ready pod &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--selector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;controller &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;90s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Deploying the Application
&lt;/h2&gt;

&lt;p&gt;As the first step, let's create a namespace called &lt;code&gt;todo&lt;/code&gt;, where will deploy our application and it's supporting resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create namespace todo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to create a &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets" rel="noopener noreferrer"&gt;Kubernetes TLS Secret&lt;/a&gt; to store the self-signed certificate generated in a previous step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create secret &lt;span class="nt"&gt;-n&lt;/span&gt; todo tls todo-app &lt;span class="nt"&gt;--cert&lt;/span&gt; tls.crt &lt;span class="nt"&gt;--key&lt;/span&gt; tls.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Now, let's use the following YAML manifest to deploy our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;kubectl apply -f - &amp;lt;&amp;lt; EOF&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app:v0.1.0&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ingressClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;todo-app.default.svc.cluster.local"&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;localhost"&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;todo-app"&lt;/span&gt;
      &lt;span class="na"&gt;secretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/todo"&lt;/span&gt;
            &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;todo-app&lt;/span&gt;
                &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a deployment, a service, and an ingress resource for the todo-app.&lt;/p&gt;



&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;We can use the &lt;code&gt;curl&lt;/code&gt; utility to test if we can reach our server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ curl &lt;span class="nt"&gt;--cacert&lt;/span&gt; tls.crt https://localhost/todo

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 &lt;span class="nt"&gt;--&lt;/span&gt;:--:-- &lt;span class="nt"&gt;--&lt;/span&gt;:--:-- &lt;span class="nt"&gt;--&lt;/span&gt;:--:--     0
curl: &lt;span class="o"&gt;(&lt;/span&gt;60&lt;span class="o"&gt;)&lt;/span&gt; SSL certificate problem: unable to get &lt;span class="nb"&gt;local &lt;/span&gt;issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, it seems that there is an issue with certificate verification.&lt;/p&gt;

&lt;p&gt;Let's try to use &lt;code&gt;curl&lt;/code&gt; with the &lt;code&gt;-k&lt;/code&gt; option which allows to establish an insecure connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ curl &lt;span class="nt"&gt;-kv&lt;/span&gt; https://localhost/todo
&lt;span class="k"&gt;*&lt;/span&gt;   Trying &lt;span class="o"&gt;[&lt;/span&gt;::1]:443...
&lt;span class="k"&gt;*&lt;/span&gt; Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;::1&lt;span class="o"&gt;)&lt;/span&gt; port 443
&lt;span class="k"&gt;*&lt;/span&gt; ALPN: curl offers h2,http/1.1
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;304&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Client hello &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;304&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Server hello &lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;304&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Unknown &lt;span class="o"&gt;(&lt;/span&gt;8&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;304&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Certificate &lt;span class="o"&gt;(&lt;/span&gt;11&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;304&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, CERT verify &lt;span class="o"&gt;(&lt;/span&gt;15&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;304&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Finished &lt;span class="o"&gt;(&lt;/span&gt;20&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;304&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Finished &lt;span class="o"&gt;(&lt;/span&gt;20&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
&lt;span class="k"&gt;*&lt;/span&gt; ALPN: server accepted h2
&lt;span class="k"&gt;*&lt;/span&gt; Server certificate:
&lt;span class="k"&gt;*&lt;/span&gt;  subject: &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Acme Co&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Kubernetes Ingress Controller Fake Certificate
&lt;span class="k"&gt;*&lt;/span&gt;  start &lt;span class="nb"&gt;date&lt;/span&gt;: Sep 29 08:28:21 2024 GMT
&lt;span class="k"&gt;*&lt;/span&gt;  expire &lt;span class="nb"&gt;date&lt;/span&gt;: Sep 29 08:28:21 2025 GMT
&lt;span class="k"&gt;*&lt;/span&gt;  issuer: &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Acme Co&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Kubernetes Ingress Controller Fake Certificate
&lt;span class="k"&gt;*&lt;/span&gt;  SSL certificate verify result: unable to get &lt;span class="nb"&gt;local &lt;/span&gt;issuer certificate &lt;span class="o"&gt;(&lt;/span&gt;20&lt;span class="o"&gt;)&lt;/span&gt;, continuing anyway.
&lt;span class="k"&gt;*&lt;/span&gt; using HTTP/2
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;HTTP/2] &lt;span class="o"&gt;[&lt;/span&gt;1] OPENED stream &lt;span class="k"&gt;for &lt;/span&gt;https://localhost/todo
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;HTTP/2] &lt;span class="o"&gt;[&lt;/span&gt;1] &lt;span class="o"&gt;[&lt;/span&gt;:method: GET]
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;HTTP/2] &lt;span class="o"&gt;[&lt;/span&gt;1] &lt;span class="o"&gt;[&lt;/span&gt;:scheme: https]
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;HTTP/2] &lt;span class="o"&gt;[&lt;/span&gt;1] &lt;span class="o"&gt;[&lt;/span&gt;:authority: localhost]
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;HTTP/2] &lt;span class="o"&gt;[&lt;/span&gt;1] &lt;span class="o"&gt;[&lt;/span&gt;:path: /todo]
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;HTTP/2] &lt;span class="o"&gt;[&lt;/span&gt;1] &lt;span class="o"&gt;[&lt;/span&gt;user-agent: curl/8.4.0]
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;HTTP/2] &lt;span class="o"&gt;[&lt;/span&gt;1] &lt;span class="o"&gt;[&lt;/span&gt;accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; GET /todo HTTP/2
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Host: localhost
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; User-Agent: curl/8.4.0
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&amp;lt; HTTP/2 200
&amp;lt; &lt;span class="nb"&gt;date&lt;/span&gt;: Sun, 29 Sep 2024 09:16:45 GMT
&amp;lt; content-type: application/json
&amp;lt; content-length: 354
&amp;lt; strict-transport-security: max-age&lt;span class="o"&gt;=&lt;/span&gt;31536000&lt;span class="p"&gt;;&lt;/span&gt; includeSubDomains
&amp;lt;
&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;"dueDate"&lt;/span&gt;:&lt;span class="s2"&gt;"2024-10-06T09:16:45.708178138Z"&lt;/span&gt;,&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="s2"&gt;"38afce86-0a6c-4b00-8d47-4dd0d836b89c"&lt;/span&gt;,&lt;span class="s2"&gt;"title"&lt;/span&gt;:&lt;span class="s2"&gt;"write a todo-app"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"dueDate"&lt;/span&gt;:&lt;span class="s2"&gt;"2024-10-07T09:16:45.708189179Z"&lt;/span&gt;,&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="s2"&gt;"4e42c873-b6cb-47b2-9d6b-0f476b59c332"&lt;/span&gt;,&lt;span class="s2"&gt;"title"&lt;/span&gt;:&lt;span class="s2"&gt;"define K8s manifests"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"dueDate"&lt;/span&gt;:&lt;span class="s2"&gt;"2024-10-08T09:16:45.708191304Z"&lt;/span&gt;,&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="s2"&gt;"dc8385d6-4c19-4605-b65d-3ad1ce2102fc"&lt;/span&gt;,&lt;span class="s2"&gt;"title"&lt;/span&gt;:&lt;span class="s2"&gt;"use certificates"&lt;/span&gt;&lt;span class="o"&gt;}]&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; Connection &lt;span class="c"&gt;#0 to host localhost left intact&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look closely, you will notice that the server is using a fake certificate. This is why our previous request with &lt;code&gt;--cacert&lt;/code&gt; option failed to verify.&lt;/p&gt;

&lt;p&gt;Let's fix that by updating the default certificate used by the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Default SSL Certificate
&lt;/h3&gt;

&lt;p&gt;The Ingress NGINX controller documentation states that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For HTTPS, a certificate is naturally required. For this reason the Ingress&lt;br&gt;
controller provides the flag &lt;code&gt;--default-ssl-certificate&lt;/code&gt;. The secret referred to&lt;br&gt;
by this flag contains the default certificate to be used when accessing the&lt;br&gt;
catch-all server. If this flag is not provided NGINX will use a self-signed&lt;br&gt;
certificate.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The complete documentation can be found &lt;a href="https://kubernetes.github.io/ingress-nginx/user-guide/tls/#default-ssl-certificate" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can patch the NGINX Ingress controller deployment to use the certificate from &lt;code&gt;todo/todo-app&lt;/code&gt; (namespace/secret-name) TLS secret as the default SSL certificate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl patch deployment &lt;span class="se"&gt;\&lt;/span&gt;
  ingress-nginx-controller &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; &lt;span class="s2"&gt;"ingress-nginx"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'[{
    "op": "add",
    "path": "/spec/template/spec/containers/0/args/-",
    "value": "--default-ssl-certificate=todo/todo-app"
  }]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Give it a few seconds so that the change is applied, and try again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--cacert&lt;/span&gt; tls.crt https://localhost/todo | jq &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
  &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"dueDate"&lt;/span&gt;: &lt;span class="s2"&gt;"2024-10-06T09:25:40.344474844Z"&lt;/span&gt;,
    &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"f8b2d51d-f9d7-4468-a78b-f187e5fb7db7"&lt;/span&gt;,
    &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"write a todo-app"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;,
  &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"dueDate"&lt;/span&gt;: &lt;span class="s2"&gt;"2024-10-07T09:25:40.344487552Z"&lt;/span&gt;,
    &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"6506e497-208b-4a70-8181-2e6d3460738b"&lt;/span&gt;,
    &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"define K8s manifests"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;,
  &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"dueDate"&lt;/span&gt;: &lt;span class="s2"&gt;"2024-10-08T09:25:40.344489594Z"&lt;/span&gt;,
    &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"6a2c7af4-07e3-45f3-a04d-8aafcac2e4bc"&lt;/span&gt;,
    &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"use certificates"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Congratulations!! 🥳&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The post aimed to outline the steps to generate and deploy self-signed certificates using OpenSSL, configure Kubernetes secrets, and set up Ingress resources for SSL encryption. This gives you the foundational knowledge to enhance the security of your microservices and ensure encrypted communication.&lt;/p&gt;

&lt;p&gt;Remember, as your applications grow and move closer to production, transitioning to certificates issued by trusted Certificate Authorities (CAs) would provide more security and reliability, especially for public-facing services.&lt;/p&gt;

&lt;p&gt;If you find it helpful, stay tuned for more. Happy securing!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>ingress</category>
      <category>nginx</category>
      <category>ssl</category>
    </item>
    <item>
      <title>Running a Compiled Python Script from C# Applications</title>
      <dc:creator>Gaurav Gahlot</dc:creator>
      <pubDate>Sun, 15 Sep 2024 13:02:18 +0000</pubDate>
      <link>https://forem.com/gauravgahlot/running-a-compiled-python-script-from-c-applications-45dg</link>
      <guid>https://forem.com/gauravgahlot/running-a-compiled-python-script-from-c-applications-45dg</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The interoperability between different programming languages enables developers&lt;br&gt;
to leverage the best features of each language. One such powerful combination&lt;br&gt;
is using Python and C# together.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I'm not a C# expert&lt;/em&gt;. This blogpost is purely based on my learning while I was&lt;br&gt;
trying to run a Python script from a C# application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/675601" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fasciinema.org%2Fa%2F675601.svg" alt="asciicast"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python Installation&lt;/strong&gt;: Ensure Python is installed on your machine and that
the Python executable is accessible via the system's &lt;code&gt;PATH&lt;/code&gt;. You can download
Python from the &lt;a href="https://www.python.org/" rel="noopener noreferrer"&gt;official Python website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C# Development Environment&lt;/strong&gt;: You'll need an environment for writing and
running C# code. Visual Studio is a popular choice, but you can use any editor
or IDE of your choice.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  A Python Script
&lt;/h2&gt;

&lt;p&gt;In order to keep it simple, we will be using the following Python script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file as &lt;code&gt;greeter.py&lt;/code&gt; to follow along.&lt;/p&gt;

&lt;p&gt;Before running a Python script from C#, you would typically compile it into a&lt;br&gt;
&lt;code&gt;.pyc&lt;/code&gt; file. Here’s how you can compile your Python script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open a terminal or command prompt.&lt;/li&gt;
&lt;li&gt;Run the following command:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; compileall greeter.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command will generate a directory named &lt;code&gt;__pycache__&lt;/code&gt; containing the&lt;br&gt;
compiled &lt;code&gt;.pyc&lt;/code&gt; file. In our case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ tree &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
├── __pycache__
│   └── greeter.cpython-312.pyc
└── greeter.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  C# Application
&lt;/h2&gt;

&lt;p&gt;We start off by creating a &lt;code&gt;console&lt;/code&gt; application using the &lt;code&gt;dotnet&lt;/code&gt; CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;netpy &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;netpy
dotnet new console
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we add the &lt;a href="https://github.com/pythonnet/pythonnet" rel="noopener noreferrer"&gt;pythonnet&lt;/a&gt; package to the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package pythonnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the &lt;code&gt;Program.cs&lt;/code&gt; file with the code below to run the compiled (&lt;code&gt;.pyc&lt;/code&gt;)&lt;br&gt;
Python script (&lt;code&gt;greeter.py&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Python.Runtime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Specify the path to the Python shared library (DLL or .so file)&lt;/span&gt;
&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PythonDLL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/opt/homebrew/Cellar/python@3.12/3.12.4/Frameworks/Python.framework/Versions/3.12/lib/libpython3.12.dylib"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize the Python engine&lt;/span&gt;
&lt;span class="n"&gt;PythonEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Use a try-finally block to ensure proper cleanup&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Acquire the GIL (Global Interpreter Lock)&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Py&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GIL&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Add path to __pycache__ directory&lt;/span&gt;
        &lt;span class="kt"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Py&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sys"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/Users/gaurav.gahlot/workspace/playground/netpy"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Import the compiled .pyc file&lt;/span&gt;
        &lt;span class="kt"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;greeter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Py&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"greeter"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Call the Greet function&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;greeter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;finally&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Necessary for proper serialization&lt;/span&gt;
    &lt;span class="n"&gt;AppContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetSwitch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Shutdown the Python runtime&lt;/span&gt;
    &lt;span class="n"&gt;PythonEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  Detailed Explanation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Python.Runtime&lt;/code&gt; Initialization:

&lt;ul&gt;
&lt;li&gt;You must set &lt;code&gt;Runtime.PythonDLL&lt;/code&gt; property or &lt;code&gt;PYTHONNET_PYDLL&lt;/code&gt; environment
variable starting with version 3.0, otherwise you will receive
&lt;code&gt;BadPythonDllException&lt;/code&gt; upon calling &lt;code&gt;Initialize&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can read more about the same in their &lt;a href="https://github.com/pythonnet/pythonnet#embedding-python-in-net" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Initialize Python Engine:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PythonEngine.Initialize()&lt;/code&gt;: This initializes the Python engine, making
Python functionalities available within the C# environment.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Using Python with GIL:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;using (Py.GIL())&lt;/code&gt;: Ensures that the Global Interpreter Lock (GIL) is acquired,
which is necessary for thread-safety when interacting with Python objects.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Modifying Python Path:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dynamic sys = Py.Import("sys")&lt;/code&gt; and &lt;code&gt;sys.path.append("path")&lt;/code&gt;: Adds the
&lt;code&gt;__pycache__&lt;/code&gt; directory to the Python path. This is where the compiled &lt;code&gt;.pyc&lt;/code&gt;
file resides.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Import and Execute:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dynamic greeter = Py.Import("greeter")&lt;/code&gt;: Imports the compiled Python script.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;string result = greeter.Greet("Alice")&lt;/code&gt;: Calls the Greet function from the
imported script and prints the result.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Clean Up:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AppContext.SetSwitch("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", true)&lt;/code&gt;:
Ensures proper serialization. You can learn more about it in this &lt;a href="https://github.com/pythonnet/pythonnet/issues/2282" rel="noopener noreferrer"&gt;GitHub issue&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PythonEngine.Shutdown()&lt;/code&gt;: Properly shuts down the Python engine to clean up resources.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;



&lt;h3&gt;
  
  
  Running the Application
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ensure that you have saved the code changes in &lt;code&gt;Program.cs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open your terminal and navigate to the directory containing &lt;code&gt;Program.cs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run the application using &lt;code&gt;dotnet run&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;workspace/playground/netpy via .NET 8.0.401
➜ dotnet run
Hello, Alice!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will execute the Python script and print the output to the console.&lt;/p&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using &lt;a href="https://github.com/pythonnet/pythonnet" rel="noopener noreferrer"&gt;Python.NET&lt;/a&gt; simplifies the process of integrating Python with C#.&lt;br&gt;
You can leverage the capabilities of Python directly from your C# applications,&lt;br&gt;
making it possible to use Python's extensive libraries and simplicity alongside&lt;br&gt;
C#'s strong performance and robust framework.&lt;/p&gt;

&lt;p&gt;I hope this helps you get started with running compiled Python scripts&lt;br&gt;
from C# applications smoothly.&lt;/p&gt;

</description>
      <category>compiling</category>
      <category>python</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Building a Rust Command-Line Utility - wc-rs</title>
      <dc:creator>Gaurav Gahlot</dc:creator>
      <pubDate>Fri, 26 Jul 2024 06:39:58 +0000</pubDate>
      <link>https://forem.com/gauravgahlot/building-a-rust-command-line-utility-wc-rs-3ga6</link>
      <guid>https://forem.com/gauravgahlot/building-a-rust-command-line-utility-wc-rs-3ga6</guid>
      <description>&lt;p&gt;Delving into Rust's capabilities, this post guides you through the process of crafting a command-line utility, &lt;code&gt;wc-rs&lt;/code&gt;, mirroring the functionality of the classic &lt;code&gt;wc&lt;/code&gt; tool with a modern twist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The motivation to build &lt;code&gt;wc-rs&lt;/code&gt; comes from John Crickett's &lt;a href="https://codingchallenges.fyi/challenges/challenge-wc/" rel="noopener noreferrer"&gt;build your own &lt;code&gt;wc&lt;/code&gt; tool&lt;/a&gt; coding challenge. Solving these challenges is a great way of learning different concepts, in my opinion. So, here we are starting with our first one.&lt;/p&gt;

&lt;p&gt;The challenge is to build your own version of the Unix command line tool wc. The functional requirements for wc are concisely described by it’s man page - give it a go in your local terminal now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;man &lt;span class="nb"&gt;wc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The TL/DR version is: &lt;code&gt;wc&lt;/code&gt; – word, line, character, and byte count.&lt;/p&gt;

&lt;p&gt;So, let's get Rusty!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Walkthrough
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;wc-rs&lt;/code&gt; program is designed to be familiar to those who have used the original &lt;code&gt;wc&lt;/code&gt; command, but under the hood, it leverages Rust's advanced features for improved performance and reliability.&lt;/p&gt;

&lt;p&gt;The complete code is available at &lt;a href="https://github.com/gauravgahlot/getting-rusty/tree/main/wc-rs" rel="noopener noreferrer"&gt;gauravgahlot/getting-rustywc-rs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;clap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the clap crate to simplify command-line argument parsing, making it effortless to define and handle the flags and options our program accepts.&lt;/p&gt;

&lt;h3&gt;
  
  
  The CLI Struct
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Parser)]&lt;/span&gt;
&lt;span class="nd"&gt;#[command(name&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"wc-rs"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="nd"&gt;#[command(version&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="nd"&gt;#[command(about=&lt;/span&gt;&lt;span class="s"&gt;"The wc-rs utility displays the count of lines, words, characters, and bytes contained in each input file"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;long_about=None)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;CLI&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/// The number of bytes in each input file is written to the&lt;/span&gt;
    &lt;span class="cd"&gt;/// standard output. This will cancel out any prior usage of the&lt;/span&gt;
    &lt;span class="cd"&gt;/// -m option.&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(short&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'c'&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="cd"&gt;/// The number of lines in each input file is written to the&lt;/span&gt;
    &lt;span class="cd"&gt;/// standard output.&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(short)]&lt;/span&gt;
    &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="cd"&gt;/// The number of words in each input file is written to the&lt;/span&gt;
    &lt;span class="cd"&gt;/// standard output.&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(short)]&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="cd"&gt;/// The number of characters in each input file is written to the&lt;/span&gt;
    &lt;span class="cd"&gt;/// standard output.&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(short&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'m'&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;CLI&lt;/code&gt; struct provides the skeleton for the command-line interface of &lt;code&gt;wc-rs&lt;/code&gt;. With clap, beyond just defining the struct, we annotate it with information like the program's name, version, and a brief description.&lt;/p&gt;

&lt;h4&gt;
  
  
  Flags and Options
&lt;/h4&gt;

&lt;p&gt;Each field in the &lt;code&gt;CLI&lt;/code&gt; struct represents a command-line flag or option, complete with descriptive comments that clap uses to generate help messages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-c&lt;/code&gt; for byte count&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-l&lt;/code&gt; for line count&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-w&lt;/code&gt; for word count&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-m&lt;/code&gt; for character count&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;files&lt;/code&gt; field holds an optional list of files to process. If it's empty, &lt;code&gt;wc-rs&lt;/code&gt; reads from standard input.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Output Struct
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Default)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we prepare to crunch numbers, we store our results in the &lt;code&gt;Output&lt;/code&gt; struct. This is where the counts of bytes, lines, words, and characters will be accumulated, along with an optional filename for display purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Main Event
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;main&lt;/code&gt; function is where we tie everything together. We parse the command-line arguments, iterate over files (or standard input), and calculate the statistics. We handle files and potential I/O errors gracefully, reflecting Rust's commitment to safe and explicit error management.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;CLI&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.files&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;BufReader&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="nf"&gt;process_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="nf"&gt;.lock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nf"&gt;process_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;print_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Processing the Input
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;process_lines&lt;/code&gt; function is at the heart of &lt;code&gt;wc-rs&lt;/code&gt;. It takes a&lt;br&gt;
reader—anything that implements the &lt;code&gt;BufRead&lt;/code&gt; trait—and an &lt;code&gt;Output&lt;/code&gt; struct by mutable reference, updating the counts as it iterates over the lines in the text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;process_lines&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BufRead&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;from_stdin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="nf"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;from_stdin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;line_words&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.split_terminator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;line_words&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="n"&gt;line_words&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.for_each&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.chars&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We account for characters and bytes differently depending on whether we're reading from a file or from standard input to ensure accuracy. Word counts are obtained by splitting lines on spaces, highlighting Rust's iterator and collection capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Showing the Numbers
&lt;/h3&gt;

&lt;p&gt;Finally, &lt;code&gt;print_output&lt;/code&gt; is responsible for displaying the collected counts. Following the flags provided, it either prints specific stats or defaults to all counts if no flags are specified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;print_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;CLI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;print_all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.chars&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;print_all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.file&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.chars&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.chars&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.file&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.chars&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="py"&gt;.chars&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;print_all&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.words&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.chars&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="py"&gt;.chars&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;total"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Getting &lt;code&gt;wc-rs&lt;/code&gt; Up and Running
&lt;/h2&gt;

&lt;p&gt;To try out &lt;code&gt;wc-rs&lt;/code&gt;, you'll compile and install it with cargo, Rust's build system and package manager. Once installed, running the program is just like using the traditional &lt;code&gt;wc&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;You can install the CLI using the below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Help
&lt;/h3&gt;

&lt;p&gt;By using the &lt;code&gt;--help&lt;/code&gt; option you can obtain the usage help for the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wc-rs &lt;span class="nt"&gt;--help&lt;/span&gt;
The wc-rs utility displays the count of lines, words, characters, and bytes contained &lt;span class="k"&gt;in &lt;/span&gt;each input file

Usage: wc-rs &lt;span class="o"&gt;[&lt;/span&gt;OPTIONS] &lt;span class="o"&gt;[&lt;/span&gt;FILES]...

Arguments:
  &lt;span class="o"&gt;[&lt;/span&gt;FILES]...

Options:
  &lt;span class="nt"&gt;-c&lt;/span&gt;             The number of bytes &lt;span class="k"&gt;in &lt;/span&gt;each input file is written to the standard output. This will cancel out any prior usage of the &lt;span class="nt"&gt;-m&lt;/span&gt; option
  &lt;span class="nt"&gt;-l&lt;/span&gt;             The number of lines &lt;span class="k"&gt;in &lt;/span&gt;each input file is written to the standard output
  &lt;span class="nt"&gt;-w&lt;/span&gt;             The number of words &lt;span class="k"&gt;in &lt;/span&gt;each input file is written to the standard output
  &lt;span class="nt"&gt;-m&lt;/span&gt;             The number of characters &lt;span class="k"&gt;in &lt;/span&gt;each input file is written to the standard output
  &lt;span class="nt"&gt;-h&lt;/span&gt;, &lt;span class="nt"&gt;--help&lt;/span&gt;     Print &lt;span class="nb"&gt;help&lt;/span&gt;
  &lt;span class="nt"&gt;-V&lt;/span&gt;, &lt;span class="nt"&gt;--version&lt;/span&gt;  Print version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Getting details of a single file:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wc-rs test.txt
        5       5       22      test.txt
      &lt;span class="c"&gt;#lines  #words  #bytes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Getting details for multiple files:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wc-rs &lt;span class="nt"&gt;-wm&lt;/span&gt; test.txt Cargo.toml
        5       16      test.txt
        25      138     Cargo.toml
        30      154     total
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Getting details for data from standard input
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wc-rs
data from std input
        1       4       19
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Display number of lines and characters only
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wc-rs &lt;span class="nt"&gt;-lm&lt;/span&gt; test.txt
        5       16      test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;wc-rs&lt;/code&gt; might be a simple tool, but it embodies the elegance and robustness of Rust for command-line applications. Through an exploration of this utility, we’ve seen the power of meticulous error handling, the convenience of &lt;code&gt;clap&lt;/code&gt; for argument parsing, and how straightforward it can be to work with files and strings in Rust.&lt;br&gt;
Whether you're an experienced developer or new to the command line, &lt;code&gt;wc-rs&lt;/code&gt; is a testament to Rust's capability to reinvent classic tools with a modern and reliable twist.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cli</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Raspberry Pi - Blinking an LED with Rust</title>
      <dc:creator>Gaurav Gahlot</dc:creator>
      <pubDate>Fri, 01 Sep 2023 06:14:24 +0000</pubDate>
      <link>https://forem.com/gauravgahlot/raspberry-pi-blinking-an-led-with-rust-5dh3</link>
      <guid>https://forem.com/gauravgahlot/raspberry-pi-blinking-an-led-with-rust-5dh3</guid>
      <description>&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Raspberry Pi (I am using Raspberry Pi 4 Model B)&lt;/li&gt;
&lt;li&gt;LED (8mm, 3.5V, 30mA)&lt;/li&gt;
&lt;li&gt;Resistor (220Ω)&lt;/li&gt;
&lt;li&gt;Breadboard&lt;/li&gt;
&lt;li&gt;Jumper wires (2 MF)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We assume that you have already installed Rust on your Raspberry Pi. If not, you can follow the instructions &lt;a href="https://gauravgahlot.in/rust-getting-started/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;h2&gt;
  
  
  GPIO Pins
&lt;/h2&gt;

&lt;p&gt;GPIO stands for General Purpose Input/Output. Raspberry Pi has 40 GPIO pins. These pins are used to connect external devices to the Raspberry Pi. These pins can be used as either input or output pins. We will be using these pins to connect our LED to the Raspberry Pi.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.raspberrypi.com%2Fdocumentation%2Fcomputers%2Fimages%2FGPIO-Pinout-Diagram-2.png" alt="GPIO Pins"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Image Source - &lt;a href="https://www.raspberrypi.com/documentation/computers/raspberry-pi.html" rel="noopener noreferrer"&gt;Raspberry Pi Documentation&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The numbers in the above image are the Physical Pin Numbers. Also known as the Board Pin Numbers. The numbers in the image below are the BCM Pin Numbers. Also known as the GPIO Pin Numbers. These numbers are used in the code to refer to the GPIO pins.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.raspberrypi.com%2Fdocumentation%2Fcomputers%2Fimages%2FGPIO.png" alt="BCM Pin Number"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Image Source - &lt;a href="https://www.raspberrypi.com/documentation/computers/raspberry-pi.html" rel="noopener noreferrer"&gt;Raspberry Pi Documentation&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  The Circuit
&lt;/h2&gt;

&lt;p&gt;The LED that I am using has the following specifications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forward Voltage: 3.5V&lt;/li&gt;
&lt;li&gt;Forward Current: 30mA (0.03A)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One can tap into 3.3V or 5V power provided by the Raspberry Pi pins. Since, the LED requires 3.5V, we will be using the 5V pin. Also, we need a resistor to limit the current flowing through the LED. We can use the following formula to calculate the value of the resistor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;R &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;V - Vf&lt;span class="o"&gt;)&lt;/span&gt; / I

where,
R &lt;span class="o"&gt;=&lt;/span&gt; Resistor value &lt;span class="k"&gt;in &lt;/span&gt;Ohms
V &lt;span class="o"&gt;=&lt;/span&gt; Voltage of the power &lt;span class="nb"&gt;source
&lt;/span&gt;Vf &lt;span class="o"&gt;=&lt;/span&gt; Forward Voltage of the LED
I &lt;span class="o"&gt;=&lt;/span&gt; Forward Current of the LED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;The value of the resistor in Ohms will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;R &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;5 - 3.5&lt;span class="o"&gt;)&lt;/span&gt; / 0.03
R &lt;span class="o"&gt;=&lt;/span&gt; 50Ω
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we need at least a 50 ohm resistor. I’ll choose 220 ohms. &lt;em&gt;The higher the resistor value you use, the dimmer the LED.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is the circuit diagram we will be referring:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgauravgahlot.in%2Fraspberry-pi-blinking-led-rust%2Fcircuit-diagram.jpeg" alt="Circuit Diagram for LED"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Circuit Diagram for LED&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We will be using the BCM Pin 23 (Physical Pin 16) to power the circuit. The power flows through a 220Ω resistor and then through the LED. Note that the longer leg of the LED is connected to the resistor, while the shorter leg of the LED is connected to the ground pin 6 of the Raspberry Pi.&lt;/p&gt;



&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;It's time to write the code that will make our LED blink. Create a new Rust project named &lt;code&gt;led-blinking&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo new led-blinking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following dependency to the &lt;code&gt;Cargo.toml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;rppal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.14.1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;rppal&lt;/code&gt; (Raspberry Pi Peripheral Access Library) crate provides access to the Raspberry Pi's GPIO, I2C, PWM, SPI and UART peripherals. You can read more about it &lt;a href="https://crates.io/crates/rppal" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Now, update the &lt;code&gt;src/main.rs&lt;/code&gt; file with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rppal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;gpio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Gpio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rppal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;system&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DeviceInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// GPIO uses BCM pin numbering. BCM GPIO 23 is tied to physical pin 16.&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GPIO_LED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Blinking an LED on a {}."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;DeviceInfo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nf"&gt;.model&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;gpio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Gpio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;pin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gpio&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GPIO_LED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.into_output&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Blink the LED by setting the pin's logic level high for a second.&lt;/span&gt;
        &lt;span class="n"&gt;pin&lt;/span&gt;&lt;span class="nf"&gt;.set_high&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_millis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;pin&lt;/span&gt;&lt;span class="nf"&gt;.set_low&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_millis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s understand the code. First, we import the &lt;code&gt;thread&lt;/code&gt; and &lt;code&gt;time&lt;/code&gt; modules from the standard library. Then, we import the &lt;code&gt;Gpio&lt;/code&gt; struct from the &lt;code&gt;rppal::gpio&lt;/code&gt; module. The &lt;code&gt;Gpio&lt;/code&gt; struct provides access to the GPIO pins. Then, we import the &lt;code&gt;DeviceInfo&lt;/code&gt; struct from the &lt;code&gt;rppal::system&lt;/code&gt; module. The &lt;code&gt;DeviceInfo&lt;/code&gt; struct provides information about the Raspberry Pi device in use.&lt;/p&gt;

&lt;p&gt;Next, we create a new instance of the &lt;code&gt;Gpio&lt;/code&gt; struct. Then, we get the pin 23 using the &lt;code&gt;get&lt;/code&gt; method. The &lt;code&gt;get&lt;/code&gt; method returns a &lt;code&gt;Result&amp;lt;OutputPin, Error&amp;gt;&lt;/code&gt;. We use the &lt;code&gt;unwrap&lt;/code&gt; method to get the &lt;code&gt;OutputPin&lt;/code&gt; struct. Then, we convert the &lt;code&gt;OutputPin&lt;/code&gt; struct into an output pin using the &lt;code&gt;into_output&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Finally, we enter an infinite loop. In each iteration of the loop, we set the pin to high using the &lt;code&gt;set_high&lt;/code&gt; method. Then, we sleep for a second using the &lt;code&gt;sleep&lt;/code&gt; method. Then, we set the pin to low using the &lt;code&gt;set_low&lt;/code&gt; method and sleep for a second again.&lt;/p&gt;



&lt;h2&gt;
  
  
  Build and Run
&lt;/h2&gt;

&lt;p&gt;Now, let’s build the project with &lt;code&gt;cargo build&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;led-blinking on master &lt;span class="o"&gt;[&lt;/span&gt;?] via 🦀 v1.55.0
➜ cargo build
   Compiling libc v0.2.101
   Compiling rppal v0.12.0
   Compiling led-blinking v0.1.0 &lt;span class="o"&gt;(&lt;/span&gt;/home/gaurav/Projects/led-blinking&lt;span class="o"&gt;)&lt;/span&gt;
    Finished dev &lt;span class="o"&gt;[&lt;/span&gt;unoptimized + debuginfo] target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;2.25s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let’s run the project with &lt;code&gt;cargo run&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;led-blinking on master &lt;span class="o"&gt;[&lt;/span&gt;?] via 🦀 v1.55.0
➜ cargo run
    Finished dev &lt;span class="o"&gt;[&lt;/span&gt;unoptimized + debuginfo] target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;0.00s
     Running &lt;span class="sb"&gt;`&lt;/span&gt;target/debug/led-blinking&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the LED blinking. If you want to stop the program, press &lt;code&gt;Ctrl + C&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgauravgahlot.in%2Fraspberry-pi-blinking-led-rust%2Fglowing-led.jpeg" alt="Glowing LED"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Glowing LED&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this blog post, we learned how to blink an LED with Rust on Raspberry Pi. We also learned how to calculate the value of the resistor required to limit the current flowing through the LED. If you have any questions or suggestions, feel free to drop a comment. A few useful links are given below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi.com/documentation/computers/raspberry-pi.html" rel="noopener noreferrer"&gt;Raspberry Pi Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://crates.io/crates/rppal" rel="noopener noreferrer"&gt;RPPAL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.rs/rppal/0.14.1/rppal/" rel="noopener noreferrer"&gt;RPPAL Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading, see you in the next one!&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>rust</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to load dynamic libraries in Rust?</title>
      <dc:creator>Gaurav Gahlot</dc:creator>
      <pubDate>Mon, 14 Aug 2023 06:54:18 +0000</pubDate>
      <link>https://forem.com/gauravgahlot/how-to-load-dynamic-libraries-in-rust-3di6</link>
      <guid>https://forem.com/gauravgahlot/how-to-load-dynamic-libraries-in-rust-3di6</guid>
      <description>&lt;h2&gt;
  
  
  What is Dynamic Library Loading?
&lt;/h2&gt;

&lt;p&gt;Dynamic library loading, also known as dynamic loading or runtime dynamic linking, is a programming technique that allows a program to load external libraries (also known as dynamic link libraries or shared libraries) into memory and use their functionalities at runtime, rather than at compile time. These libraries contain compiled code that can be executed by the program, enabling modularization, code reuse, and flexibility.&lt;/p&gt;

&lt;p&gt;Dynamic library loading is in contrast to static linking, where all the necessary code is included in the program's executable binary during the compilation process. With dynamic library loading, the program remains smaller in size, and libraries can be updated or replaced without requiring changes to the main program.&lt;/p&gt;



&lt;h2&gt;
  
  
  Dynamic Library Loading in Rust
&lt;/h2&gt;

&lt;p&gt;Rust provides a safe and ergonomic interface for loading dynamic libraries at runtime. The &lt;a href="https://crates.io/crates/libloading" rel="noopener noreferrer"&gt;libloading&lt;/a&gt; crate provides a cross-platform API for loading dynamic libraries and calling functions defined in those libraries. It also provides a safe wrapper around the &lt;code&gt;dlopen&lt;/code&gt; and &lt;code&gt;dlsym&lt;/code&gt; functions on Unix-like systems and the &lt;code&gt;LoadLibrary&lt;/code&gt; and &lt;code&gt;GetProcAddress&lt;/code&gt; functions on Windows.&lt;/p&gt;

&lt;p&gt;The complete source code is available on &lt;a href="https://github.com/gauravgahlot/getting-rusty/tree/main/lib-loading" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup the workspace
&lt;/h3&gt;

&lt;p&gt;Let's start by creating a new Rust project named &lt;code&gt;lib-loading&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo new lib-loading

&lt;span class="c"&gt;# remove the src directory as we will be creating a workspace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, update the &lt;code&gt;Cargo.toml&lt;/code&gt; file to create a workspace and add two members to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[workspace]&lt;/span&gt;

&lt;span class="py"&gt;members&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;"hello-world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"executor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  Create a dynamic library
&lt;/h3&gt;

&lt;p&gt;Let's now create a library named &lt;code&gt;hello-world&lt;/code&gt; with the following &lt;code&gt;Cargo.toml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo new hello-world &lt;span class="nt"&gt;--lib&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[package]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello-world"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;edition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2021"&lt;/span&gt;

&lt;span class="nn"&gt;[lib]&lt;/span&gt;
&lt;span class="py"&gt;crate-type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"dylib"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;crate-type&lt;/code&gt; field in the &lt;code&gt;[lib]&lt;/code&gt; section. This tells the compiler to build a dynamic library instead of the default static library. This output type will create &lt;code&gt;*.so&lt;/code&gt; files on Linux, &lt;code&gt;*.dylib&lt;/code&gt; files on macOS, and &lt;code&gt;*.dll&lt;/code&gt; files on Windows.&lt;/p&gt;

&lt;p&gt;You can read more about different crate-types in the &lt;a href="https://doc.rust-lang.org/reference/linkage.html#crate-type" rel="noopener noreferrer"&gt;Rust Reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, update the &lt;code&gt;src/lib.rs&lt;/code&gt; file to define a function named &lt;code&gt;execute&lt;/code&gt; that prints a message to the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Name mangling is a compiler technique that encodes function names with additional information like the function's parameters and return type. However, this makes it difficult to call functions from other languages or dynamically loaded libraries. &lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;no_mangle&lt;/code&gt; attribute turns off Rust's name mangling, so that it has a well defined symbol to link to. This allows us to call the function from the dynamically loaded library.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3&gt;
  
  
  Create a binary crate
&lt;/h3&gt;

&lt;p&gt;Next, let's create a binary crate named &lt;code&gt;executor&lt;/code&gt; that will load the &lt;code&gt;hello-world&lt;/code&gt; library and call the &lt;code&gt;execute&lt;/code&gt; function defined in it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo new executor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a dependency on the &lt;code&gt;libloading&lt;/code&gt; crate to the &lt;code&gt;Cargo.toml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[package]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"executor"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;edition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2021"&lt;/span&gt;

&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;libloading&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.8"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, update the &lt;code&gt;src/main.rs&lt;/code&gt; file to load the &lt;code&gt;hello-world&lt;/code&gt; library and call the &lt;code&gt;execute&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;libloading&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Library&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;library_filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Load the "hello_world" library&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Library&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;library_filename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello_world"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

         &lt;span class="c1"&gt;// Get the function pointer&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"execute"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Call the function&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;blockquote&gt;
&lt;p&gt;It's a good practice to use the &lt;code&gt;library_filename&lt;/code&gt; function to get the platform-specific filename of the library. This function returns &lt;code&gt;libhello_world.so&lt;/code&gt; on Linux, &lt;code&gt;libhello_world.dylib&lt;/code&gt; on macOS, and &lt;code&gt;hello_world.dll&lt;/code&gt; on Windows.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3&gt;
  
  
  Build and run the project
&lt;/h3&gt;

&lt;p&gt;First, let's build the project with &lt;code&gt;cargo build&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lib-loading on master &lt;span class="o"&gt;[&lt;/span&gt;?] via 🦀 v1.69.0
➜ cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;
   Compiling cfg-if v1.0.0
   Compiling hello-world v0.1.0 &lt;span class="o"&gt;(&lt;/span&gt;/Users/gaurav.gahlot/workspace/playground/lib-loading/hello-world&lt;span class="o"&gt;)&lt;/span&gt;
   Compiling libloading v0.8.0
   Compiling executor v0.1.0 &lt;span class="o"&gt;(&lt;/span&gt;/Users/gaurav.gahlot/workspace/playground/lib-loading/executor&lt;span class="o"&gt;)&lt;/span&gt;
    Finished release &lt;span class="o"&gt;[&lt;/span&gt;optimized] target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;1.42s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, run the &lt;code&gt;executor&lt;/code&gt; using &lt;code&gt;cargo run&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lib-loading on master &lt;span class="o"&gt;[&lt;/span&gt;?] via 🦀 v1.69.0 took 2s
➜ cargo run &lt;span class="nt"&gt;-p&lt;/span&gt; executor &lt;span class="nt"&gt;--release&lt;/span&gt;
    Finished release &lt;span class="o"&gt;[&lt;/span&gt;optimized] target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;0.02s
     Running &lt;span class="sb"&gt;`&lt;/span&gt;target/release/executor&lt;span class="sb"&gt;`&lt;/span&gt;

Hello, world!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Congratulations! You've successfully loaded a dynamic library and called a function defined in it.&lt;/p&gt;



&lt;h2&gt;
  
  
  When to use Dynamic Library Loading?
&lt;/h2&gt;

&lt;p&gt;Dynamic library loading is useful in several scenarios where you want to achieve modularity, flexibility, and runtime extensibility in your applications. Here are some situations where dynamic library loading can be advantageous:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugin Systems:&lt;/strong&gt; If you're building an application that supports plugins or extensions, dynamic library loading can allow you to load and unload these plugins at runtime without modifying or restarting the main application. This can be useful for applications like text editors, web browsers, or media players that support third-party plugins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modular Applications:&lt;/strong&gt; When you're developing a large application, dynamic library loading can help you break down the functionality into smaller, manageable components. This can lead to faster development cycles, easier maintenance, and improved code organization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hot Reload:&lt;/strong&gt; For certain types of applications like game development tools or graphical design software, dynamic library loading can enable hot reloading. This means you can modify parts of the application's code, compile them into a dynamic library, and load that library without restarting the entire application. This greatly speeds up development iterations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Platform-Specific Implementations:&lt;/strong&gt; If your application needs to interact with platform-specific features, dynamic library loading allows you to provide different implementations for different platforms. You can load the appropriate library based on the runtime environment, avoiding unnecessary code in the main application binary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versioning and Updates:&lt;/strong&gt; When you want to provide updates or bug fixes to a specific part of your application, you can distribute and load only the updated dynamic library without needing users to update the entire application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Sharing:&lt;/strong&gt; Dynamic libraries can be used to share resources like database connections, network sockets, or other system resources across multiple parts of your application. This can help optimize resource usage and improve performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Language Interoperability:&lt;/strong&gt; If you need to interface with code written in other programming languages (e.g., C or C++), dynamic libraries provide a way to call functions written in those languages from your Rust code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security and Isolation:&lt;/strong&gt; In some cases, you might want to isolate certain components of your application for security reasons. Dynamic libraries can help you encapsulate sensitive code, limiting its exposure to the main application.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;h2&gt;
  
  
  Challenges of Dynamic Library Loading
&lt;/h2&gt;

&lt;p&gt;Dynamic library loading also introduces complexity and potential challenges. Here are a few things to consider when using dynamic libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory Management:&lt;/strong&gt; You need to manage memory and resource allocation properly, ensuring that you release resources and unload libraries when they're no longer needed to avoid memory leaks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility:&lt;/strong&gt; Ensuring that dynamically loaded libraries are compatible with your application's version and other libraries can be challenging. Version mismatches can lead to crashes or unexpected behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unsafe Code:&lt;/strong&gt; Working with dynamically loaded libraries often involves using the &lt;code&gt;unsafe&lt;/code&gt; keyword due to the inherent risks associated with runtime operations that Rust's safety mechanisms cannot fully verify.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Debugging issues in dynamically loaded libraries can be more challenging compared to monolithic applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Overhead:&lt;/strong&gt; There can be a slight performance overhead when using dynamic libraries compared to statically linking code directly into your application binary.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In summary, dynamic library loading is most beneficial when you need to create modular, flexible, and extensible applications, but it requires careful design, proper resource management, and an understanding of the potential trade-offs. Rust's safety mechanisms can help you avoid many of the pitfalls associated with dynamic library loading, but you still need to be aware of the risks and challenges involved.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>dynamic</category>
      <category>loading</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Getting started with Rust on Raspberry Pi</title>
      <dc:creator>Gaurav Gahlot</dc:creator>
      <pubDate>Fri, 30 Jun 2023 06:05:42 +0000</pubDate>
      <link>https://forem.com/gauravgahlot/getting-started-with-rust-on-raspberry-pi-1aoe</link>
      <guid>https://forem.com/gauravgahlot/getting-started-with-rust-on-raspberry-pi-1aoe</guid>
      <description>&lt;p&gt;In this blog post, we will learn how to get started with Rust on Raspberry Pi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Rust is a modern programming language that is blazingly fast, memory-efficient, and type-safe.&lt;br&gt;
It is a great language for systems programming, and it is used by companies like Mozilla, Dropbox, and Cloudflare.&lt;/p&gt;

&lt;p&gt;Raspberry Pi is a low-cost, credit-card sized computer that plugs into a computer monitor or TV, and uses a standard keyboard and mouse.&lt;br&gt;
It is a capable little device that enables people of all ages to explore computing, and to learn how to program in language of their choice.&lt;/p&gt;

&lt;p&gt;Let's get started.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;In terms of hardware, you will need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Raspberry Pi 4 (4GB RAM) (already setup with Raspberry Pi OS)&lt;/li&gt;
&lt;li&gt;Keyboard and Mouse&lt;/li&gt;
&lt;li&gt;Monitor or TV&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you haven't already setup your Raspberry Pi, you can follow the instructions in earlier post - &lt;a href="//../setup-raspberry-pi-without-a-monitor"&gt;Setup Raspberry Pi without an external monitor&lt;/a&gt;.&lt;br&gt;
If you don't have a Raspberry Pi, you can still follow along using a virtual machine. &lt;/p&gt;

&lt;p&gt;Let's ensure that our Raspberry Pi is up-to-date.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gaurav@RPi4:~ &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
Linux RPi4 6.1.21-v8+ &lt;span class="c"&gt;#1642 SMP PREEMPT Mon Apr  3 17:24:16 BST 2023 aarch64 GNU/Linux&lt;/span&gt;

gaurav@RPi4:~ &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; password &lt;span class="k"&gt;for &lt;/span&gt;gaurav:
Hit:1 http://archive.raspberrypi.org/debian bullseye InRelease
Hit:2 http://raspbian.raspberrypi.org/raspbian bullseye InRelease
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following package was automatically installed and is no longer required:
  libfuse2
Use &lt;span class="s1"&gt;'sudo apt autoremove'&lt;/span&gt; to remove it.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing Rust
&lt;/h2&gt;

&lt;p&gt;The Rust documentation suggests to use a script available for us to install Rust with Rustup and Cargo on Raspberry Pi.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gaurav@RPi4:~ &lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--proto&lt;/span&gt; &lt;span class="s1"&gt;'=https'&lt;/span&gt; &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="nt"&gt;-sSf&lt;/span&gt; https://sh.rustup.rs | sh
info: downloading installer

Welcome to Rust!

This will download and &lt;span class="nb"&gt;install &lt;/span&gt;the official compiler &lt;span class="k"&gt;for &lt;/span&gt;the Rust
programming language, and its package manager, Cargo.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  /home/gaurav/.rustup

This can be modified with the RUSTUP_HOME environment variable.

The Cargo home directory is located at:

  /home/gaurav/.cargo

This can be modified with the CARGO_HOME environment variable.

The cargo, rustc, rustup and other commands will be added to
Cargo&lt;span class="s1"&gt;'s bin directory, located at:

  /home/gaurav/.cargo/bin

This path will then be added to your PATH environment variable by
modifying the profile files located at:

  /home/gaurav/.profile
  /home/gaurav/.bashrc

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:


   default host triple: aarch64-unknown-linux-gnu
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
&amp;gt;1

info: profile set to '&lt;/span&gt;default&lt;span class="s1"&gt;'
info: default host triple is aarch64-unknown-linux-gnu
info: syncing channel updates for '&lt;/span&gt;stable-aarch64-unknown-linux-gnu&lt;span class="s1"&gt;'
info: latest update on 2023-06-01, rust version 1.70.0 (90c541806 2023-05-31)
info: downloading component '&lt;/span&gt;cargo&lt;span class="s1"&gt;'
  6.7 MiB /   6.7 MiB (100 %)   1.3 MiB/s in  4s ETA:  0s
info: downloading component '&lt;/span&gt;clippy&lt;span class="s1"&gt;'
info: downloading component '&lt;/span&gt;rust-docs&lt;span class="s1"&gt;'
 13.6 MiB /  13.6 MiB (100 %)   3.7 MiB/s in  4s ETA:  0s
info: downloading component '&lt;/span&gt;rust-std&lt;span class="s1"&gt;'
 32.8 MiB /  32.8 MiB (100 %)   2.9 MiB/s in 11s ETA:  0s
info: downloading component '&lt;/span&gt;rustc&lt;span class="s1"&gt;'
 75.5 MiB /  75.5 MiB (100 %)   3.4 MiB/s in 24s ETA:  0s
info: downloading component '&lt;/span&gt;rustfmt&lt;span class="s1"&gt;'
info: installing component '&lt;/span&gt;cargo&lt;span class="s1"&gt;'
info: installing component '&lt;/span&gt;clippy&lt;span class="s1"&gt;'
info: installing component '&lt;/span&gt;rust-docs&lt;span class="s1"&gt;'
 13.6 MiB /  13.6 MiB (100 %)   1.6 MiB/s in  7s ETA:  0s
info: installing component '&lt;/span&gt;rust-std&lt;span class="s1"&gt;'
 32.8 MiB /  32.8 MiB (100 %)   5.8 MiB/s in  5s ETA:  0s
info: installing component '&lt;/span&gt;rustc&lt;span class="s1"&gt;'
 75.5 MiB /  75.5 MiB (100 %)   6.3 MiB/s in 11s ETA:  0s
info: installing component '&lt;/span&gt;rustfmt&lt;span class="s1"&gt;'
info: default toolchain set to '&lt;/span&gt;stable-aarch64-unknown-linux-gnu&lt;span class="s1"&gt;'

  stable-aarch64-unknown-linux-gnu installed - rustc 1.70.0 (90c541806 2023-05-31)


Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo'&lt;/span&gt;s bin directory &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.cargo/bin&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

To configure your current shell, run:
&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.cargo/env"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that you will be prompted to choose an installation option. You can press the return key or enter 1 to continue with the defaults as I did. Of course, you can choose other options as needed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice the information at the end of the command execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo&lt;span class="s1"&gt;'s bin directory ($HOME/.cargo/bin).

To configure your current shell, run:
source "$HOME/.cargo/env"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may choose to restart, but I will source the env file to continue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gaurav@RPi4:~ &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.cargo/env"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once done, we can check the version of the components installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gaurav@RPi4:~ &lt;span class="nv"&gt;$ &lt;/span&gt;rustup &lt;span class="nt"&gt;-V&lt;/span&gt;
rustup 1.26.0 &lt;span class="o"&gt;(&lt;/span&gt;5af9b9484 2023-04-05&lt;span class="o"&gt;)&lt;/span&gt;
info: This is the version &lt;span class="k"&gt;for &lt;/span&gt;the rustup toolchain manager, not the rustc compiler.
info: The currently active &lt;span class="sb"&gt;`&lt;/span&gt;rustc&lt;span class="sb"&gt;`&lt;/span&gt; version is &lt;span class="sb"&gt;`&lt;/span&gt;rustc 1.70.0 &lt;span class="o"&gt;(&lt;/span&gt;90c541806 2023-05-31&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

gaurav@RPi4:~ &lt;span class="nv"&gt;$ &lt;/span&gt;rustc &lt;span class="nt"&gt;-V&lt;/span&gt;
rustc 1.70.0 &lt;span class="o"&gt;(&lt;/span&gt;90c541806 2023-05-31&lt;span class="o"&gt;)&lt;/span&gt;

gaurav@RPi4:~ &lt;span class="nv"&gt;$ &lt;/span&gt;cargo &lt;span class="nt"&gt;-V&lt;/span&gt;
cargo 1.70.0 &lt;span class="o"&gt;(&lt;/span&gt;ec8a8a0ca 2023-04-25&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Our First Program
&lt;/h2&gt;

&lt;p&gt;I prefer to keep my projects in a directory &lt;code&gt;workspace&lt;/code&gt; in my home directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/workspace
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create a simple Rust program to print "Hello World!" to the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gaurav@RPi4:~/workspace &lt;span class="nv"&gt;$ &lt;/span&gt;cargo new &lt;span class="nt"&gt;--bin&lt;/span&gt; hello-world
     Created binary &lt;span class="o"&gt;(&lt;/span&gt;application&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;hello-world&lt;span class="sb"&gt;`&lt;/span&gt; package

gaurav@RPi4:~/workspace &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;hello-world/
gaurav@RPi4:~/workspace/hello-world &lt;span class="nv"&gt;$ &lt;/span&gt;tree &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
├── Cargo.toml
└── src
    └── main.rs

1 directory, 2 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, take a look at the contents of the &lt;code&gt;main.rs&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;gaurav&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;RPi4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;world&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="py"&gt;.rs&lt;/span&gt;
&lt;span class="err"&gt;───────┬─────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;
       &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="py"&gt;.rs&lt;/span&gt;
&lt;span class="err"&gt;───────┼─────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;
   &lt;span class="mi"&gt;1&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;     &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;───────┴─────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's run our program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gaurav@RPi4:~/workspace/hello-world &lt;span class="nv"&gt;$ &lt;/span&gt;cargo run
   Compiling hello-world v0.1.0 &lt;span class="o"&gt;(&lt;/span&gt;/home/gaurav/workspace/hello-world&lt;span class="o"&gt;)&lt;/span&gt;
    Finished dev &lt;span class="o"&gt;[&lt;/span&gt;unoptimized + debuginfo] target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;1.33s
     Running &lt;span class="sb"&gt;`&lt;/span&gt;target/debug/hello-world&lt;span class="sb"&gt;`&lt;/span&gt;
Hello, world!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations! You have successfully run your first Rust program on the Raspberry Pi. 🥳&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we learned how to install Rust on the Raspberry Pi. We also created a simple Rust program and ran it on the Raspberry Pi.&lt;br&gt;
In the next article in this series, we will learn how to setup a sophisticated Rust development environment on the Raspberry Pi.&lt;br&gt;
So, stay tuned!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>raspberrypi</category>
      <category>beginners</category>
      <category>setup</category>
    </item>
    <item>
      <title>Setup your Raspberry Pi 4 - without an external monitor</title>
      <dc:creator>Gaurav Gahlot</dc:creator>
      <pubDate>Mon, 20 Dec 2021 14:37:33 +0000</pubDate>
      <link>https://forem.com/docker/setup-your-raspberry-pi-4-without-an-external-monitor-300e</link>
      <guid>https://forem.com/docker/setup-your-raspberry-pi-4-without-an-external-monitor-300e</guid>
      <description>&lt;p&gt;I received my first Raspberry Pi yesterday. I have got a Raspberry Pi 4 Model B with &lt;code&gt;8GB&lt;/code&gt; RAM. As I was doing the setup, I found it difficult to get all the information in one place, so I decided to write this blog post.&lt;/p&gt;

&lt;p&gt;This post documents the steps to setup a brand new Raspberry Pi &lt;em&gt;without an external monitor&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here is what we are going to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;install the Raspberry Pi OS (64-bit)&lt;/li&gt;
&lt;li&gt;setup internet connection over WiFi&lt;/li&gt;
&lt;li&gt;SSH and run updates&lt;/li&gt;
&lt;li&gt;setup VNC Viewer&lt;/li&gt;
&lt;li&gt;install Docker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have quite a lot to cover, so let's get started. &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Following are some prerequisites for the setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Raspberry Pi board (obviously)&lt;/li&gt;
&lt;li&gt;connector for power supply&lt;/li&gt;
&lt;li&gt;microSD card (depends on your Pi model though) and a card reader&lt;/li&gt;
&lt;li&gt;another system to do the work (on the same network)&lt;/li&gt;
&lt;li&gt;SSID (network name)&lt;/li&gt;
&lt;li&gt;PSK (network password)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing Raspberry Pi OS
&lt;/h2&gt;

&lt;p&gt;The very first thing you need for the setup is the &lt;a href="https://www.raspberrypi.com/software/" rel="noopener noreferrer"&gt;Raspberry Pi Imager&lt;/a&gt;. Raspberry Pi Imager is the quick and easy way to install Raspberry Pi OS and other operating systems to a microSD card, ready to use with your Raspberry Pi. The imager provides a wide range of stable operating systems. However, they are all 32-bit (I think). You can very well choose either one and move forward. &lt;/p&gt;

&lt;p&gt;Since the Raspberry Pi 4 supports 64-bit OS, I will be installing the 64-bit Raspberry Pi OS. You can download the same from &lt;a href="https://forums.raspberrypi.com/viewtopic.php?t=275370" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Please note that it's still in beta testing and a list of known issues can be found on the same forum.&lt;/p&gt;

&lt;p&gt;Follow the steps below to install the OS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect your microSD card to the system where you have downloaded the OS and imager.&lt;/li&gt;
&lt;li&gt;In the imager select the &lt;code&gt;Choose OS&lt;/code&gt; option.&lt;/li&gt;
&lt;li&gt;Scroll down the pop-up list and select &lt;code&gt;Use custom&lt;/code&gt; at the end.&lt;/li&gt;
&lt;li&gt;Select the downloaded OS (&lt;code&gt;.zip&lt;/code&gt; file)&lt;/li&gt;
&lt;li&gt;Now select &lt;code&gt;Choose Storage&lt;/code&gt; and select the connected SD card.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Write&lt;/code&gt; and wait for the process to complete.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If you choose an OS from the recommended list, it will first download the OS and then write it to the SD card. This will take a little longer, so be patient.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setup Wifi
&lt;/h2&gt;

&lt;p&gt;Now that we have installed the OS, it's time to setup the network.&lt;/p&gt;

&lt;p&gt;Open the SD card in a file manager of your choosing. If you are using a Windows based system, the SD card will directly land you in the &lt;code&gt;boot&lt;/code&gt; directory. You can double check it by looking for these files:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

bootcode.bin
loader.bin
start.elf
kernel.img
cmdline.txt


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create a file named &lt;code&gt;wpa_supplicant.conf&lt;/code&gt; next to the above files, i.e., in the &lt;code&gt;boot&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;However, if you are on a &lt;code&gt;Linux&lt;/code&gt; based system you need to create the file as &lt;code&gt;/etc/wpa_supplicant/wpa_supplicant.conf&lt;/code&gt;. Now, add the following content to your file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us
&lt;span class="nv"&gt;update_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nv"&gt;ctrl_interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/run/wpa_supplicant

&lt;span class="nv"&gt;network&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;
  &lt;span class="nv"&gt;scan_ssid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
  &lt;span class="nv"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"network_SSID_here"&lt;/span&gt;
  &lt;span class="nv"&gt;psk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"network_password_here"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Save the file and ensure that the file extension is &lt;code&gt;.conf&lt;/code&gt;.&lt;br&gt;
Insert the SD in the slot of the Pi board, connect the power and turn it on. As the Pi boots you should see the blinking &lt;code&gt;green&lt;/code&gt; and &lt;code&gt;red&lt;/code&gt; lights. Once the boot is complete the &lt;code&gt;green&lt;/code&gt; light will turn off. &lt;/p&gt;

&lt;h2&gt;
  
  
  SSH and Run Updates
&lt;/h2&gt;

&lt;p&gt;Now, it's time to find the IP address of your Raspberry Pi. There are multiple ways to scan a network and get connected devices. In order to make it easy you can use an IP Scanner. This &lt;a href="https://www.dnsstuff.com/scan-network-for-device-ip-address#how-to-find-all-ip-addresses-on-a-network" rel="noopener noreferrer"&gt;article&lt;/a&gt; provides a good list of scanners that you can choose from. Select and install one.&lt;/p&gt;

&lt;p&gt;Scan your network and you should see a Raspberry Pi device connected. Here is an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feayz6ivk9guziwzks36k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feayz6ivk9guziwzks36k.png" alt="IP Scanner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note the IP address. Let's SSH into the Pi with default credentials.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# username - pi&lt;/span&gt;
&lt;span class="c"&gt;# password - raspberry&lt;/span&gt;

➜ ssh pi@192.168.0.232
pi@192.168.0.232&lt;span class="s1"&gt;'s password:
Linux raspberrypi 5.10.63-v8+ #1488 SMP PREEMPT Thu Nov 18 16:16:16 GMT 2021 aarch64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Dec  4 00:43:28 2021 from 192.168.0.233
pi@raspberrypi:~ $


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here are a few things you should do as you login:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# change the password&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;passwd

&lt;span class="c"&gt;# get updates&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update

&lt;span class="c"&gt;# upgrade the system&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Raspberry Pi OS also provides a configuration manager that you can start using the &lt;code&gt;sudo raspi-config&lt;/code&gt; command. It will prompt you with the following or similar term-UI:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

Raspberry Pi 4 Model B Rev 1.4


┌────────────────────────┤ Raspberry Pi Software Configuration Tool &lt;span class="o"&gt;(&lt;/span&gt;raspi-config&lt;span class="o"&gt;)&lt;/span&gt; ├─────────────────────────┐
│                                                                                                            │
│                      1 System Options       Configure system settings                                      │
│                      2 Display Options      Configure display settings                                     │
│                      3 Interface Options    Configure connections to peripherals                           │
│                      4 Performance Options  Configure performance settings                                 │
│                      5 Localisation Options Configure language and regional settings                       │
│                      6 Advanced Options     Configure advanced settings                                    │
│                      8 Update               Update this tool to the latest version                         │
│                      9 About raspi-config   Information about this configuration tool                      │
│                                                                                                            │
│                                                                                                            │
│                                                                                                            │
│                               &amp;lt;Select&amp;gt;                               &amp;lt;Finish&amp;gt;                              │
│                                                                                                            │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────┘


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Setup VNC Viewer
&lt;/h2&gt;

&lt;p&gt;Honestly, you don't really need a GUI to work with a Raspberry Pi. But it can be useful at times, especially if you are a beginner. Let's setup VNC viewer just for that.&lt;/p&gt;

&lt;p&gt;On your Pi, install the &lt;a href="https://www.realvnc.com/en/connect/download/vnc/" rel="noopener noreferrer"&gt;realvnc&lt;/a&gt; server:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;realvnc-vnc-server


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Start the VNC server using the &lt;code&gt;vncserver&lt;/code&gt; command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

vncserver

...

Running applications &lt;span class="k"&gt;in&lt;/span&gt; /etc/vnc/xstartup

VNC Server catchphrase: &lt;span class="s2"&gt;"Needle baker salute. Price diagram origin."&lt;/span&gt;
             signature: e4-20-40-65-48-3d-f7-51

Log file is /home/pi/.vnc/raspberrypi:1.log
New desktop is raspberrypi:1 &lt;span class="o"&gt;(&lt;/span&gt;192.168.0.232:1&lt;span class="o"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice the last line that provides details about how you can connect to the desktop started by the server.&lt;/p&gt;

&lt;p&gt;Now install the &lt;a href="https://www.realvnc.com/en/connect/download/viewer/" rel="noopener noreferrer"&gt;VNC Viewer&lt;/a&gt; (also know as VNC client) on the system you want to have the display on. Once installed, start the client and use the desktop address you got from the VNC server (&lt;code&gt;192.168.0.232:1&lt;/code&gt; in my case). When prompted, provide the Raspberry Pi user credentials you used to SSH into the Pi.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: With this setup, each time you want to access the GUI you will need to SSH and start the server manually. You can enable the VNC interface by default from the configuration manager (raspi-config) -&amp;gt; Interface Options -&amp;gt; VNC -&amp;gt; Enabled setting.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrq53vmcpsxjzozz6dgf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrq53vmcpsxjzozz6dgf.png" alt="VNC Viewer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You have successfully setup your Raspberry Pi. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Docker
&lt;/h2&gt;

&lt;p&gt;Installing Docker on Raspberry Pi 4 is super simple. All you need is to run the following command that gets a script and pipes it to the shell:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://get.docker.com/ | sh


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By default, Docker daemon runs a privileged service and a non-privileged user can't connect with it without using &lt;code&gt;sudo&lt;/code&gt;. Meaning, if you try executing &lt;code&gt;docker ps&lt;/code&gt; command you would get the following error message:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps
Got permission denied &lt;span class="k"&gt;while &lt;/span&gt;trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get &lt;span class="s2"&gt;"http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json"&lt;/span&gt;: dial unix /var/run/docker.sock: connect: permission denied


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In order fix this we need to add the &lt;code&gt;pi&lt;/code&gt; user to the &lt;code&gt;docker&lt;/code&gt; group. Once done, reboot the Pi.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;reboot


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;SSH again and try executing the &lt;code&gt;docker ps&lt;/code&gt; command w/o &lt;code&gt;sudo&lt;/code&gt; and you should not get any errors.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps&lt;br&gt;
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;In this blog post, we have setup a Raspberry Pi 4 Model B from scratch without an &lt;em&gt;external&lt;/em&gt; monitor connected to the Pi. We have also installed Docker and so, the Pi is all set to get you rocking on a new journey. In the next post, we will setup Rust and write our first application. Later we will containerise the application and run it on the Raspberry Pi. So, stay tuned.&lt;/p&gt;

&lt;p&gt;I hope you found the steps useful and I look forward to your valuable feedback. If you run into issue, please do let me know and I will be happy to help.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>raspberrypi</category>
      <category>beginners</category>
      <category>setup</category>
    </item>
  </channel>
</rss>
